summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit00bb99ac80741fc50ef8a289719373032f2391eb (patch)
tree3a5a9bf72f942784b38bf77dd66c534662fab5f2
downloadtdeaccessibility-00bb99ac80741fc50ef8a289719373032f2391eb.tar.gz
tdeaccessibility-00bb99ac80741fc50ef8a289719373032f2391eb.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeaccessibility@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
-rw-r--r--COPYING346
-rw-r--r--COPYING-DOCS397
-rw-r--r--INSTALL184
-rw-r--r--IconThemes/Makefile.am43
-rw-r--r--IconThemes/mono/index.theme175
-rw-r--r--IconThemes/mono/png/128x128/actions/kde.pngbin0 -> 23517 bytes
-rw-r--r--IconThemes/mono/png/16x16/actions/kde.pngbin0 -> 529 bytes
-rw-r--r--IconThemes/mono/png/192x192/actions/kde.pngbin0 -> 50789 bytes
-rw-r--r--IconThemes/mono/png/22x22/actions/kde.pngbin0 -> 758 bytes
-rw-r--r--IconThemes/mono/png/256x256/actions/kde.pngbin0 -> 52708 bytes
-rw-r--r--IconThemes/mono/png/32x32/actions/kde.pngbin0 -> 1697 bytes
-rw-r--r--IconThemes/mono/png/48x48/actions/kde.pngbin0 -> 3051 bytes
-rw-r--r--IconThemes/mono/png/64x64/actions/kde.pngbin0 -> 4286 bytes
-rw-r--r--IconThemes/mono/png/96x96/actions/kde.pngbin0 -> 21789 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_ellipse.svgzbin0 -> 1399 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_flatten.svgzbin0 -> 1555 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_gradient.svgzbin0 -> 1707 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_group.svgzbin0 -> 1637 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_image.svgzbin0 -> 2842 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_insertknots.svgzbin0 -> 3139 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_layer_deletelayer.svgzbin0 -> 1788 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_layer_lowerlayer.svgzbin0 -> 1438 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_layer_newlayer.svgzbin0 -> 1860 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_layer_novisible.svgzbin0 -> 3029 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_layer_raiselayer.svgzbin0 -> 1441 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_layer_visible.svgzbin0 -> 2992 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_pattern.svgzbin0 -> 2017 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_pencil.svgzbin0 -> 1826 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_polygon.svgzbin0 -> 1462 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_polyline.svgzbin0 -> 2523 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_rectangle.svgzbin0 -> 1522 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_rotate.svgzbin0 -> 1537 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_roundcorners.svgzbin0 -> 1451 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_roundrect.svgzbin0 -> 1522 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_select.svgzbin0 -> 1371 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_selectnodes.svgzbin0 -> 1739 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_shear.svgzbin0 -> 1584 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_sinus.svgzbin0 -> 2103 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_spiral.svgzbin0 -> 1457 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_star.svgzbin0 -> 1483 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_text.svgzbin0 -> 2936 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_transform.svgzbin0 -> 1579 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_ungroup.svgzbin0 -> 1479 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_whirl.svgzbin0 -> 1456 bytes
-rw-r--r--IconThemes/mono/scalable/actions/14_zoom.svgzbin0 -> 1954 bytes
-rw-r--r--IconThemes/mono/scalable/actions/1day.svgzbin0 -> 3359 bytes
-rw-r--r--IconThemes/mono/scalable/actions/1downarrow.svgzbin0 -> 1547 bytes
-rw-r--r--IconThemes/mono/scalable/actions/1leftarrow.svgzbin0 -> 1551 bytes
-rw-r--r--IconThemes/mono/scalable/actions/1rightarrow.svgzbin0 -> 1551 bytes
-rw-r--r--IconThemes/mono/scalable/actions/1uparrow.svgzbin0 -> 1546 bytes
-rw-r--r--IconThemes/mono/scalable/actions/2downarrow.svgzbin0 -> 1559 bytes
-rw-r--r--IconThemes/mono/scalable/actions/2leftarrow.svgzbin0 -> 1563 bytes
-rw-r--r--IconThemes/mono/scalable/actions/2rightarrow.svgzbin0 -> 1562 bytes
-rw-r--r--IconThemes/mono/scalable/actions/2uparrow.svgzbin0 -> 1558 bytes
-rw-r--r--IconThemes/mono/scalable/actions/3downarrow.svgzbin0 -> 1703 bytes
-rw-r--r--IconThemes/mono/scalable/actions/3leftarrow.svgzbin0 -> 1716 bytes
-rw-r--r--IconThemes/mono/scalable/actions/3rightarrow.svgzbin0 -> 1713 bytes
-rw-r--r--IconThemes/mono/scalable/actions/3uparrow.svgzbin0 -> 1693 bytes
-rw-r--r--IconThemes/mono/scalable/actions/5days.svgzbin0 -> 2405 bytes
-rw-r--r--IconThemes/mono/scalable/actions/7days.svgzbin0 -> 2476 bytes
-rw-r--r--IconThemes/mono/scalable/actions/abentry.svgzbin0 -> 1719 bytes
-rw-r--r--IconThemes/mono/scalable/actions/about_kde.svgzbin0 -> 3230 bytes
-rw-r--r--IconThemes/mono/scalable/actions/abs.svgzbin0 -> 3221 bytes
-rw-r--r--IconThemes/mono/scalable/actions/account.svgzbin0 -> 9187 bytes
-rw-r--r--IconThemes/mono/scalable/actions/account_open.svgzbin0 -> 2025 bytes
-rw-r--r--IconThemes/mono/scalable/actions/add.svgzbin0 -> 1833 bytes
-rw-r--r--IconThemes/mono/scalable/actions/add_group.svgzbin0 -> 2037 bytes
-rw-r--r--IconThemes/mono/scalable/actions/add_milestone.svgzbin0 -> 2425 bytes
-rw-r--r--IconThemes/mono/scalable/actions/add_sub_task.svgzbin0 -> 2124 bytes
-rw-r--r--IconThemes/mono/scalable/actions/add_target.svgzbin0 -> 1662 bytes
-rw-r--r--IconThemes/mono/scalable/actions/add_task.svgzbin0 -> 1951 bytes
-rw-r--r--IconThemes/mono/scalable/actions/add_user.svgzbin0 -> 2210 bytes
-rw-r--r--IconThemes/mono/scalable/actions/addimagefolder.svgzbin0 -> 1471 bytes
-rw-r--r--IconThemes/mono/scalable/actions/addpoint.svgzbin0 -> 3133 bytes
-rw-r--r--IconThemes/mono/scalable/actions/addquestion.svgzbin0 -> 3347 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adept_commit.svgzbin0 -> 1424 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adept_distupgrade.svgzbin0 -> 2230 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adept_install.svgzbin0 -> 1851 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adept_notifier_warning.svgzbin0 -> 2047 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adept_purge.svgzbin0 -> 1577 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adept_remove.svgzbin0 -> 1649 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adept_sourceseditor.svgzbin0 -> 2398 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adept_update.svgzbin0 -> 1948 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adjustcol.svgzbin0 -> 3058 bytes
-rw-r--r--IconThemes/mono/scalable/actions/adjustrow.svgzbin0 -> 3053 bytes
-rw-r--r--IconThemes/mono/scalable/actions/agenda.svgzbin0 -> 2398 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aim_away.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aim_offline.svgzbin0 -> 1908 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aim_online.svgzbin0 -> 2171 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aim_protocol.svgzbin0 -> 2173 bytes
-rw-r--r--IconThemes/mono/scalable/actions/airbrush.svgzbin0 -> 3446 bytes
-rw-r--r--IconThemes/mono/scalable/actions/albumfoldercomment.svgzbin0 -> 1932 bytes
-rw-r--r--IconThemes/mono/scalable/actions/albumfoldernew.svgzbin0 -> 2161 bytes
-rw-r--r--IconThemes/mono/scalable/actions/align_left.svgzbin0 -> 1768 bytes
-rw-r--r--IconThemes/mono/scalable/actions/align_right.svgzbin0 -> 1642 bytes
-rw-r--r--IconThemes/mono/scalable/actions/alignobjs.svgzbin0 -> 1806 bytes
-rw-r--r--IconThemes/mono/scalable/actions/angle.svgzbin0 -> 2173 bytes
-rw-r--r--IconThemes/mono/scalable/actions/angle_bisector.svgzbin0 -> 2244 bytes
-rw-r--r--IconThemes/mono/scalable/actions/angle_size.svgzbin0 -> 2071 bytes
-rw-r--r--IconThemes/mono/scalable/actions/answer.svgzbin0 -> 2910 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aobottom.svgzbin0 -> 1680 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aocenterh.svgzbin0 -> 1734 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aocenterv.svgzbin0 -> 1713 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aogrid.svgzbin0 -> 1938 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aoleft.svgzbin0 -> 1710 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aopos2grid.svgzbin0 -> 1757 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aoright.svgzbin0 -> 1707 bytes
-rw-r--r--IconThemes/mono/scalable/actions/aotop.svgzbin0 -> 1703 bytes
-rw-r--r--IconThemes/mono/scalable/actions/appearance.svgzbin0 -> 2180 bytes
-rw-r--r--IconThemes/mono/scalable/actions/apply.svgzbin0 -> 1424 bytes
-rw-r--r--IconThemes/mono/scalable/actions/appointment.svgzbin0 -> 3451 bytes
-rw-r--r--IconThemes/mono/scalable/actions/arc.svgzbin0 -> 2012 bytes
-rw-r--r--IconThemes/mono/scalable/actions/arc_center.svgzbin0 -> 2150 bytes
-rw-r--r--IconThemes/mono/scalable/actions/areaCircle.svgzbin0 -> 2162 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ark_adddir.svgzbin0 -> 2248 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ark_addfile.svgzbin0 -> 2024 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ark_delete.svgzbin0 -> 2273 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ark_extract.svgzbin0 -> 2230 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ark_selectall.svgzbin0 -> 2352 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ark_view.svgzbin0 -> 2125 bytes
-rw-r--r--IconThemes/mono/scalable/actions/arrange.svgzbin0 -> 1870 bytes
-rw-r--r--IconThemes/mono/scalable/actions/arrow.svgzbin0 -> 1367 bytes
-rw-r--r--IconThemes/mono/scalable/actions/arrowheads.svgzbin0 -> 1545 bytes
-rw-r--r--IconThemes/mono/scalable/actions/artsaudiomanager.svgzbin0 -> 1804 bytes
-rw-r--r--IconThemes/mono/scalable/actions/artsbuilderexecute.svgzbin0 -> 1585 bytes
-rw-r--r--IconThemes/mono/scalable/actions/artsenvironment.svgzbin0 -> 1803 bytes
-rw-r--r--IconThemes/mono/scalable/actions/artsfftscope.svgzbin0 -> 1777 bytes
-rw-r--r--IconThemes/mono/scalable/actions/artsmediatypes.svgzbin0 -> 2405 bytes
-rw-r--r--IconThemes/mono/scalable/actions/artsmidimanager.svgzbin0 -> 2389 bytes
-rw-r--r--IconThemes/mono/scalable/actions/atlantik_buy_estate.svgzbin0 -> 3287 bytes
-rw-r--r--IconThemes/mono/scalable/actions/attach.svgzbin0 -> 1493 bytes
-rw-r--r--IconThemes/mono/scalable/actions/attacher.svgzbin0 -> 1795 bytes
-rw-r--r--IconThemes/mono/scalable/actions/auction.svgzbin0 -> 2112 bytes
-rw-r--r--IconThemes/mono/scalable/actions/audioscrobbler.svgzbin0 -> 2026 bytes
-rw-r--r--IconThemes/mono/scalable/actions/authenticate.svgzbin0 -> 2085 bytes
-rw-r--r--IconThemes/mono/scalable/actions/autodiff.svgzbin0 -> 3756 bytes
-rw-r--r--IconThemes/mono/scalable/actions/autoform.svgzbin0 -> 1452 bytes
-rw-r--r--IconThemes/mono/scalable/actions/autonumber.svgzbin0 -> 4679 bytes
-rw-r--r--IconThemes/mono/scalable/actions/babelfish.svgzbin0 -> 2880 bytes
-rw-r--r--IconThemes/mono/scalable/actions/back.svgzbin0 -> 1545 bytes
-rw-r--r--IconThemes/mono/scalable/actions/backup.svgzbin0 -> 1985 bytes
-rw-r--r--IconThemes/mono/scalable/actions/backup_section.svgzbin0 -> 1993 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bank.svgzbin0 -> 1991 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bar0.svgzbin0 -> 1582 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bar1.svgzbin0 -> 1631 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bar2.svgzbin0 -> 1607 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bar3.svgzbin0 -> 1739 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bar4.svgzbin0 -> 1625 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bar5.svgzbin0 -> 1667 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bar6.svgzbin0 -> 1809 bytes
-rw-r--r--IconThemes/mono/scalable/actions/baseCircle.svgzbin0 -> 1566 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bell.svgzbin0 -> 2003 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bisection.svgzbin0 -> 1511 bytes
-rw-r--r--IconThemes/mono/scalable/actions/black_sum.svgzbin0 -> 1309 bytes
-rw-r--r--IconThemes/mono/scalable/actions/blend.svgzbin0 -> 1701 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bold.svgzbin0 -> 2166 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bookmark.svgzbin0 -> 2066 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bookmark_add.svgzbin0 -> 2619 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bookmark_folder.svgzbin0 -> 3327 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bookmark_toolbar.svgzbin0 -> 2591 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bookmarks_list_add.svgzbin0 -> 2770 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_all.svgzbin0 -> 1698 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_bottom.svgzbin0 -> 1721 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_fall.svgzbin0 -> 1804 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_horizontal.svgzbin0 -> 1718 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_inside.svgzbin0 -> 1725 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_left.svgzbin0 -> 1744 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_outline.svgzbin0 -> 1733 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_remove.svgzbin0 -> 1729 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_right.svgzbin0 -> 1686 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_top.svgzbin0 -> 1723 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_up.svgzbin0 -> 1816 bytes
-rw-r--r--IconThemes/mono/scalable/actions/border_vertical.svgzbin0 -> 1731 bytes
-rw-r--r--IconThemes/mono/scalable/actions/borderbottom.svgzbin0 -> 1608 bytes
-rw-r--r--IconThemes/mono/scalable/actions/borderleft.svgzbin0 -> 1511 bytes
-rw-r--r--IconThemes/mono/scalable/actions/borderoutline.svgzbin0 -> 1727 bytes
-rw-r--r--IconThemes/mono/scalable/actions/borderright.svgzbin0 -> 1556 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bordertool.svgzbin0 -> 1757 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bordertop.svgzbin0 -> 1599 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bottom.svgzbin0 -> 1699 bytes
-rw-r--r--IconThemes/mono/scalable/actions/brackets.svgzbin0 -> 2934 bytes
-rw-r--r--IconThemes/mono/scalable/actions/brightness.svgzbin0 -> 1929 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bring_forward.svgzbin0 -> 1656 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bring_stencil_to_front.svgzbin0 -> 1665 bytes
-rw-r--r--IconThemes/mono/scalable/actions/bug.svgzbin0 -> 2488 bytes
-rw-r--r--IconThemes/mono/scalable/actions/business_user.svgzbin0 -> 1725 bytes
-rw-r--r--IconThemes/mono/scalable/actions/button.svgzbin0 -> 2927 bytes
-rw-r--r--IconThemes/mono/scalable/actions/button_cancel.svgzbin0 -> 1584 bytes
-rw-r--r--IconThemes/mono/scalable/actions/button_fewer.svgzbin0 -> 1555 bytes
-rw-r--r--IconThemes/mono/scalable/actions/button_more.svgzbin0 -> 1805 bytes
-rw-r--r--IconThemes/mono/scalable/actions/button_ok.svgzbin0 -> 1428 bytes
-rw-r--r--IconThemes/mono/scalable/actions/calculate.svgzbin0 -> 1661 bytes
-rw-r--r--IconThemes/mono/scalable/actions/camera.svgzbin0 -> 1939 bytes
-rw-r--r--IconThemes/mono/scalable/actions/camera_test.svgzbin0 -> 4100 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cancel.svgzbin0 -> 1577 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cap_butt.svgzbin0 -> 1282 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cap_round.svgzbin0 -> 1280 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cap_square.svgzbin0 -> 1164 bytes
-rw-r--r--IconThemes/mono/scalable/actions/casesensitive.svgzbin0 -> 3047 bytes
-rw-r--r--IconThemes/mono/scalable/actions/catalogmanager.svgzbin0 -> 2903 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cd.svgzbin0 -> 1763 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cdburn.svgzbin0 -> 2578 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cdcopy.svgzbin0 -> 2002 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cdinfo.svgzbin0 -> 2125 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cdrwblank.svgzbin0 -> 1968 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cdsmall.svgzbin0 -> 1768 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cdtje.svgzbin0 -> 2577 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cell_edit.svgzbin0 -> 1682 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cell_layout.svgzbin0 -> 2879 bytes
-rw-r--r--IconThemes/mono/scalable/actions/centerofcurvature.svgzbin0 -> 1631 bytes
-rw-r--r--IconThemes/mono/scalable/actions/centralsymmetry.svgzbin0 -> 1775 bytes
-rw-r--r--IconThemes/mono/scalable/actions/centrejust.svgzbin0 -> 1779 bytes
-rw-r--r--IconThemes/mono/scalable/actions/char.svgzbin0 -> 6097 bytes
-rw-r--r--IconThemes/mono/scalable/actions/charset.svgzbin0 -> 6100 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart.svgzbin0 -> 1841 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_area.svgzbin0 -> 1677 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_area_3d.svgzbin0 -> 2105 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_bar.svgzbin0 -> 2165 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_bar_3d.svgzbin0 -> 2545 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_boxwhisker.svgzbin0 -> 1738 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_hilo.svgzbin0 -> 1495 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_bottom.svgzbin0 -> 1839 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_bottomleft.svgzbin0 -> 1843 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_bottomright.svgzbin0 -> 1849 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_left.svgzbin0 -> 1828 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_nolegend.svgzbin0 -> 1496 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_right.svgzbin0 -> 1823 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_top.svgzbin0 -> 1831 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_topleft.svgzbin0 -> 1839 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_legend_topright.svgzbin0 -> 1845 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_line.svgzbin0 -> 1699 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_line_3d.svgzbin0 -> 2493 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_pie.svgzbin0 -> 2083 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_pie_3d.svgzbin0 -> 2358 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_polar.svgzbin0 -> 2469 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chart_ring.svgzbin0 -> 2134 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chat.svgzbin0 -> 1534 bytes
-rw-r--r--IconThemes/mono/scalable/actions/check.svgzbin0 -> 1596 bytes
-rw-r--r--IconThemes/mono/scalable/actions/checkedbox.svgzbin0 -> 1597 bytes
-rw-r--r--IconThemes/mono/scalable/actions/checkmark.svgzbin0 -> 1467 bytes
-rw-r--r--IconThemes/mono/scalable/actions/chemical.svgzbin0 -> 2240 bytes
-rw-r--r--IconThemes/mono/scalable/actions/circle.svgzbin0 -> 1366 bytes
-rw-r--r--IconThemes/mono/scalable/actions/circlebcl.svgzbin0 -> 1668 bytes
-rw-r--r--IconThemes/mono/scalable/actions/circlebcp.svgzbin0 -> 1716 bytes
-rw-r--r--IconThemes/mono/scalable/actions/circlebpd.svgzbin0 -> 1550 bytes
-rw-r--r--IconThemes/mono/scalable/actions/circlebps.svgzbin0 -> 1585 bytes
-rw-r--r--IconThemes/mono/scalable/actions/circlebtp.svgzbin0 -> 1949 bytes
-rw-r--r--IconThemes/mono/scalable/actions/circlelineintersection.svgzbin0 -> 2014 bytes
-rw-r--r--IconThemes/mono/scalable/actions/circumference.svgzbin0 -> 1893 bytes
-rw-r--r--IconThemes/mono/scalable/actions/clear_left.svgzbin0 -> 1959 bytes
-rw-r--r--IconThemes/mono/scalable/actions/clipart.svgzbin0 -> 2046 bytes
-rw-r--r--IconThemes/mono/scalable/actions/clipart_from_file.svgzbin0 -> 2424 bytes
-rw-r--r--IconThemes/mono/scalable/actions/close.svgzbin0 -> 1576 bytes
-rw-r--r--IconThemes/mono/scalable/actions/closed_cubicbeziercurve.svgzbin0 -> 2118 bytes
-rw-r--r--IconThemes/mono/scalable/actions/closed_freehand.svgzbin0 -> 2301 bytes
-rw-r--r--IconThemes/mono/scalable/actions/closed_polyline.svgzbin0 -> 2583 bytes
-rw-r--r--IconThemes/mono/scalable/actions/closed_quadricbeziercurve.svgzbin0 -> 1795 bytes
-rw-r--r--IconThemes/mono/scalable/actions/collection.svgzbin0 -> 1990 bytes
-rw-r--r--IconThemes/mono/scalable/actions/color_fill.svgzbin0 -> 2399 bytes
-rw-r--r--IconThemes/mono/scalable/actions/color_line.svgzbin0 -> 2308 bytes
-rw-r--r--IconThemes/mono/scalable/actions/colorize.svgzbin0 -> 2178 bytes
-rw-r--r--IconThemes/mono/scalable/actions/colorman.svgzbin0 -> 2178 bytes
-rw-r--r--IconThemes/mono/scalable/actions/colorpicker.svgzbin0 -> 1684 bytes
-rw-r--r--IconThemes/mono/scalable/actions/combo.svgzbin0 -> 1916 bytes
-rw-r--r--IconThemes/mono/scalable/actions/comment.svgzbin0 -> 1682 bytes
-rw-r--r--IconThemes/mono/scalable/actions/compfile.svgzbin0 -> 3766 bytes
-rw-r--r--IconThemes/mono/scalable/actions/completion.svgzbin0 -> 2999 bytes
-rw-r--r--IconThemes/mono/scalable/actions/configure.svgzbin0 -> 2034 bytes
-rw-r--r--IconThemes/mono/scalable/actions/configure_shortcuts.svgzbin0 -> 1754 bytes
-rw-r--r--IconThemes/mono/scalable/actions/configure_toolbars.svgzbin0 -> 3448 bytes
-rw-r--r--IconThemes/mono/scalable/actions/conicasymptotes.svgzbin0 -> 1454 bytes
-rw-r--r--IconThemes/mono/scalable/actions/conicb5p.svgzbin0 -> 2215 bytes
-rw-r--r--IconThemes/mono/scalable/actions/coniclineintersection.svgzbin0 -> 1961 bytes
-rw-r--r--IconThemes/mono/scalable/actions/conicsradicalline.svgzbin0 -> 1847 bytes
-rw-r--r--IconThemes/mono/scalable/actions/connect_creating.svgzbin0 -> 2761 bytes
-rw-r--r--IconThemes/mono/scalable/actions/connect_established.svgzbin0 -> 2595 bytes
-rw-r--r--IconThemes/mono/scalable/actions/connect_no.svgzbin0 -> 1853 bytes
-rw-r--r--IconThemes/mono/scalable/actions/contents.svgzbin0 -> 1921 bytes
-rw-r--r--IconThemes/mono/scalable/actions/contents2.svgzbin0 -> 1922 bytes
-rw-r--r--IconThemes/mono/scalable/actions/contexthelp.svgzbin0 -> 2489 bytes
-rw-r--r--IconThemes/mono/scalable/actions/contrast.svgzbin0 -> 1726 bytes
-rw-r--r--IconThemes/mono/scalable/actions/control.svgzbin0 -> 2032 bytes
-rw-r--r--IconThemes/mono/scalable/actions/convexhull.svgzbin0 -> 1964 bytes
-rw-r--r--IconThemes/mono/scalable/actions/coords.svgzbin0 -> 2084 bytes
-rw-r--r--IconThemes/mono/scalable/actions/copy.svgzbin0 -> 1736 bytes
-rw-r--r--IconThemes/mono/scalable/actions/copy_stencil.svgzbin0 -> 1744 bytes
-rw-r--r--IconThemes/mono/scalable/actions/covermanager.svgzbin0 -> 2293 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cpufreq_100.svgzbin0 -> 3925 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cpufreq_25.svgzbin0 -> 3845 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cpufreq_50.svgzbin0 -> 3861 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cpufreq_75.svgzbin0 -> 3905 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cpufreq_na.svgzbin0 -> 3678 bytes
-rw-r--r--IconThemes/mono/scalable/actions/crop.svgzbin0 -> 1569 bytes
-rw-r--r--IconThemes/mono/scalable/actions/css.svgzbin0 -> 4676 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cssvalidator.svgzbin0 -> 4676 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cubicbeziercurve.svgzbin0 -> 2072 bytes
-rw-r--r--IconThemes/mono/scalable/actions/curvelineintersection.svgzbin0 -> 1750 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cut.svgzbin0 -> 1542 bytes
-rw-r--r--IconThemes/mono/scalable/actions/cut_stencil.svgzbin0 -> 1550 bytes
-rw-r--r--IconThemes/mono/scalable/actions/data.svgzbin0 -> 2436 bytes
-rw-r--r--IconThemes/mono/scalable/actions/dateedit.svgzbin0 -> 3363 bytes
-rw-r--r--IconThemes/mono/scalable/actions/datetimeedit.svgzbin0 -> 2542 bytes
-rw-r--r--IconThemes/mono/scalable/actions/dayview.svgzbin0 -> 3362 bytes
-rw-r--r--IconThemes/mono/scalable/actions/db.svgzbin0 -> 1686 bytes
-rw-r--r--IconThemes/mono/scalable/actions/decrypted.svgzbin0 -> 1722 bytes
-rw-r--r--IconThemes/mono/scalable/actions/define_clip.svgzbin0 -> 2412 bytes
-rw-r--r--IconThemes/mono/scalable/actions/delete.svgzbin0 -> 1774 bytes
-rw-r--r--IconThemes/mono/scalable/actions/delete_group.svgzbin0 -> 1746 bytes
-rw-r--r--IconThemes/mono/scalable/actions/delete_table.svgzbin0 -> 1952 bytes
-rw-r--r--IconThemes/mono/scalable/actions/delete_table_col.svgzbin0 -> 2270 bytes
-rw-r--r--IconThemes/mono/scalable/actions/delete_table_row.svgzbin0 -> 2303 bytes
-rw-r--r--IconThemes/mono/scalable/actions/delete_user.svgzbin0 -> 1992 bytes
-rw-r--r--IconThemes/mono/scalable/actions/deletecell.svgzbin0 -> 1674 bytes
-rw-r--r--IconThemes/mono/scalable/actions/deletelayer.svgzbin0 -> 1788 bytes
-rw-r--r--IconThemes/mono/scalable/actions/delquestion.svgzbin0 -> 4610 bytes
-rw-r--r--IconThemes/mono/scalable/actions/delslide.svgzbin0 -> 2155 bytes
-rw-r--r--IconThemes/mono/scalable/actions/deriv_func.svgzbin0 -> 2326 bytes
-rw-r--r--IconThemes/mono/scalable/actions/diff.svgzbin0 -> 3546 bytes
-rw-r--r--IconThemes/mono/scalable/actions/digikamimageplugins.svgzbin0 -> 1952 bytes
-rw-r--r--IconThemes/mono/scalable/actions/digitalcam.svgzbin0 -> 1943 bytes
-rw-r--r--IconThemes/mono/scalable/actions/directrix.svgzbin0 -> 1483 bytes
-rw-r--r--IconThemes/mono/scalable/actions/dirsynch.svgzbin0 -> 1527 bytes
-rw-r--r--IconThemes/mono/scalable/actions/dirsynch_new.svgzbin0 -> 2128 bytes
-rw-r--r--IconThemes/mono/scalable/actions/dissociatecell.svgzbin0 -> 1729 bytes
-rw-r--r--IconThemes/mono/scalable/actions/distance.svgzbin0 -> 1498 bytes
-rw-r--r--IconThemes/mono/scalable/actions/div_center.svgzbin0 -> 1780 bytes
-rw-r--r--IconThemes/mono/scalable/actions/div_justify.svgzbin0 -> 1810 bytes
-rw-r--r--IconThemes/mono/scalable/actions/div_left.svgzbin0 -> 1766 bytes
-rw-r--r--IconThemes/mono/scalable/actions/div_right.svgzbin0 -> 1640 bytes
-rw-r--r--IconThemes/mono/scalable/actions/documentinfo.svgzbin0 -> 1819 bytes
-rw-r--r--IconThemes/mono/scalable/actions/domtreeviewer.svgzbin0 -> 4020 bytes
-rw-r--r--IconThemes/mono/scalable/actions/dontknow.svgzbin0 -> 3536 bytes
-rw-r--r--IconThemes/mono/scalable/actions/down.svgzbin0 -> 1541 bytes
-rw-r--r--IconThemes/mono/scalable/actions/duringbreaks.svgzbin0 -> 2114 bytes
-rw-r--r--IconThemes/mono/scalable/actions/dynamic.svgzbin0 -> 1446 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit.svgzbin0 -> 2398 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit_add.svgzbin0 -> 1851 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit_copy.svgzbin0 -> 1919 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit_group.svgzbin0 -> 2908 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit_picture.svgzbin0 -> 3232 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit_pie.svgzbin0 -> 2353 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit_polygon.svgzbin0 -> 1710 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit_remove.svgzbin0 -> 1649 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edit_user.svgzbin0 -> 3029 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editclear.svgzbin0 -> 1497 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editconstants.svgzbin0 -> 5610 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editcopy.svgzbin0 -> 1740 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editcut.svgzbin0 -> 1546 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editdelete.svgzbin0 -> 1778 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editimage.svgzbin0 -> 2126 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editor.svgzbin0 -> 2400 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editpaste.svgzbin0 -> 2240 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editplots.svgzbin0 -> 3477 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editquestion.svgzbin0 -> 4968 bytes
-rw-r--r--IconThemes/mono/scalable/actions/editshred.svgzbin0 -> 2184 bytes
-rw-r--r--IconThemes/mono/scalable/actions/edittrash.svgzbin0 -> 1490 bytes
-rw-r--r--IconThemes/mono/scalable/actions/effect.svgzbin0 -> 2250 bytes
-rw-r--r--IconThemes/mono/scalable/actions/elempic.svgzbin0 -> 2361 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ellipse.svgzbin0 -> 1396 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ellipsebffp.svgzbin0 -> 1920 bytes
-rw-r--r--IconThemes/mono/scalable/actions/emoticon.svgzbin0 -> 2080 bytes
-rw-r--r--IconThemes/mono/scalable/actions/emptybox.svgzbin0 -> 1658 bytes
-rw-r--r--IconThemes/mono/scalable/actions/emptytrash.svgzbin0 -> 1476 bytes
-rw-r--r--IconThemes/mono/scalable/actions/en.svgzbin0 -> 1966 bytes
-rw-r--r--IconThemes/mono/scalable/actions/encrypted.svgzbin0 -> 1779 bytes
-rw-r--r--IconThemes/mono/scalable/actions/endturn.svgzbin0 -> 1923 bytes
-rw-r--r--IconThemes/mono/scalable/actions/energies.svgzbin0 -> 3009 bytes
-rw-r--r--IconThemes/mono/scalable/actions/enumList.svgzbin0 -> 3813 bytes
-rw-r--r--IconThemes/mono/scalable/actions/enum_list.svgzbin0 -> 3814 bytes
-rw-r--r--IconThemes/mono/scalable/actions/eqchem.svgzbin0 -> 3916 bytes
-rw-r--r--IconThemes/mono/scalable/actions/equalizer.svgzbin0 -> 1797 bytes
-rw-r--r--IconThemes/mono/scalable/actions/equilateralhyperbolab4p.svgzbin0 -> 2243 bytes
-rw-r--r--IconThemes/mono/scalable/actions/equitriangle.svgzbin0 -> 1642 bytes
-rw-r--r--IconThemes/mono/scalable/actions/eraser.svgzbin0 -> 1428 bytes
-rw-r--r--IconThemes/mono/scalable/actions/error.svgzbin0 -> 2570 bytes
-rw-r--r--IconThemes/mono/scalable/actions/exclamation.svgzbin0 -> 2096 bytes
-rw-r--r--IconThemes/mono/scalable/actions/exec.svgzbin0 -> 1571 bytes
-rw-r--r--IconThemes/mono/scalable/actions/exifinfo.svgzbin0 -> 1815 bytes
-rw-r--r--IconThemes/mono/scalable/actions/exit.svgzbin0 -> 2284 bytes
-rw-r--r--IconThemes/mono/scalable/actions/favorites.svgzbin0 -> 1485 bytes
-rw-r--r--IconThemes/mono/scalable/actions/file.svgzbin0 -> 1971 bytes
-rw-r--r--IconThemes/mono/scalable/actions/file_transfer_section.svgzbin0 -> 1540 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fileblend.svgzbin0 -> 1528 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fileclose.svgzbin0 -> 1580 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fileexport.svgzbin0 -> 2673 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filefind.svgzbin0 -> 1920 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fileimport.svgzbin0 -> 2354 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filenew.svgzbin0 -> 2154 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fileopen.svgzbin0 -> 2021 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fileopenurl.svgzbin0 -> 2838 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fileprint.svgzbin0 -> 2022 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filequickprint.svgzbin0 -> 2459 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filereplace.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filesave.svgzbin0 -> 1707 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filesaveas.svgzbin0 -> 2672 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filesimulate.svgzbin0 -> 2156 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filestop.svgzbin0 -> 1889 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fill.svgzbin0 -> 2516 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fill_colour.svgzbin0 -> 2523 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filledcircle.svgzbin0 -> 2081 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filledellipse.svgzbin0 -> 2046 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filledrectangle.svgzbin0 -> 1962 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filter.svgzbin0 -> 1889 bytes
-rw-r--r--IconThemes/mono/scalable/actions/filterstop.svgzbin0 -> 2229 bytes
-rw-r--r--IconThemes/mono/scalable/actions/find.svgzbin0 -> 1916 bytes
-rw-r--r--IconThemes/mono/scalable/actions/findf.svgzbin0 -> 1917 bytes
-rw-r--r--IconThemes/mono/scalable/actions/finish.svgzbin0 -> 1708 bytes
-rw-r--r--IconThemes/mono/scalable/actions/first_letter_upper.svgzbin0 -> 3052 bytes
-rw-r--r--IconThemes/mono/scalable/actions/flag.svgzbin0 -> 2056 bytes
-rw-r--r--IconThemes/mono/scalable/actions/flash.svgzbin0 -> 2090 bytes
-rw-r--r--IconThemes/mono/scalable/actions/flightevaluation.svgzbin0 -> 1710 bytes
-rw-r--r--IconThemes/mono/scalable/actions/flip.svgzbin0 -> 1748 bytes
-rw-r--r--IconThemes/mono/scalable/actions/folder.svgzbin0 -> 1973 bytes
-rw-r--r--IconThemes/mono/scalable/actions/folder_closed.svgzbin0 -> 2331 bytes
-rw-r--r--IconThemes/mono/scalable/actions/folder_grey.svgzbin0 -> 2329 bytes
-rw-r--r--IconThemes/mono/scalable/actions/folder_new.svgzbin0 -> 2637 bytes
-rw-r--r--IconThemes/mono/scalable/actions/folder_open.svgzbin0 -> 2378 bytes
-rw-r--r--IconThemes/mono/scalable/actions/followmouse.svgzbin0 -> 1451 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fonts.svgzbin0 -> 3916 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fontsizedown.svgzbin0 -> 4214 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fontsizeup.svgzbin0 -> 4166 bytes
-rw-r--r--IconThemes/mono/scalable/actions/fork.svgzbin0 -> 3188 bytes
-rw-r--r--IconThemes/mono/scalable/actions/form.svgzbin0 -> 1829 bytes
-rw-r--r--IconThemes/mono/scalable/actions/form_edit.svgzbin0 -> 2622 bytes
-rw-r--r--IconThemes/mono/scalable/actions/form_newobj.svgzbin0 -> 1836 bytes
-rw-r--r--IconThemes/mono/scalable/actions/format_decreaseindent.svgzbin0 -> 2031 bytes
-rw-r--r--IconThemes/mono/scalable/actions/format_increaseindent.svgzbin0 -> 2019 bytes
-rw-r--r--IconThemes/mono/scalable/actions/forms.svgzbin0 -> 1830 bytes
-rw-r--r--IconThemes/mono/scalable/actions/forward.svgzbin0 -> 1547 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frac.svgzbin0 -> 3985 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame.svgzbin0 -> 1491 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame_chart.svgzbin0 -> 3167 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame_edit.svgzbin0 -> 2899 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame_field.svgzbin0 -> 2905 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame_formula.svgzbin0 -> 3629 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame_image.svgzbin0 -> 2845 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame_query.svgzbin0 -> 3000 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame_spreadsheet.svgzbin0 -> 3458 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frame_text.svgzbin0 -> 3459 bytes
-rw-r--r--IconThemes/mono/scalable/actions/frameprint.svgzbin0 -> 2124 bytes
-rw-r--r--IconThemes/mono/scalable/actions/freehand.svgzbin0 -> 2132 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ftin.svgzbin0 -> 2766 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ftout.svgzbin0 -> 2514 bytes
-rw-r--r--IconThemes/mono/scalable/actions/func.svgzbin0 -> 2024 bytes
-rw-r--r--IconThemes/mono/scalable/actions/funct.svgzbin0 -> 5397 bytes
-rw-r--r--IconThemes/mono/scalable/actions/functionhelp.svgzbin0 -> 2794 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gadu_protocol.svgzbin0 -> 3150 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gear.svgzbin0 -> 1571 bytes
-rw-r--r--IconThemes/mono/scalable/actions/genericaffinity.svgzbin0 -> 2233 bytes
-rw-r--r--IconThemes/mono/scalable/actions/genericprojectivity.svgzbin0 -> 2989 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gg_away.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gg_ignore.svgzbin0 -> 1925 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gg_invi.svgzbin0 -> 3303 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gg_offline.svgzbin0 -> 2947 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gg_online.svgzbin0 -> 3146 bytes
-rw-r--r--IconThemes/mono/scalable/actions/glossary.svgzbin0 -> 2290 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gnutelladown.svgzbin0 -> 1549 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gnutellaup.svgzbin0 -> 1548 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gohome.svgzbin0 -> 1901 bytes
-rw-r--r--IconThemes/mono/scalable/actions/goto.svgzbin0 -> 1321 bytes
-rw-r--r--IconThemes/mono/scalable/actions/grayscale.svgzbin0 -> 2179 bytes
-rw-r--r--IconThemes/mono/scalable/actions/green_ball.svgzbin0 -> 1347 bytes
-rw-r--r--IconThemes/mono/scalable/actions/grid.svgzbin0 -> 1623 bytes
-rw-r--r--IconThemes/mono/scalable/actions/group.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/group_stencils.svgzbin0 -> 1643 bytes
-rw-r--r--IconThemes/mono/scalable/actions/groupbox.svgzbin0 -> 3338 bytes
-rw-r--r--IconThemes/mono/scalable/actions/groupevent.svgzbin0 -> 2862 bytes
-rw-r--r--IconThemes/mono/scalable/actions/groupwise_online.svgzbin0 -> 2130 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gsub.svgzbin0 -> 3370 bytes
-rw-r--r--IconThemes/mono/scalable/actions/gsup.svgzbin0 -> 3371 bytes
-rw-r--r--IconThemes/mono/scalable/actions/guides_horizontal.svgzbin0 -> 1686 bytes
-rw-r--r--IconThemes/mono/scalable/actions/guides_vertical.svgzbin0 -> 1642 bytes
-rw-r--r--IconThemes/mono/scalable/actions/halfencrypted.svgzbin0 -> 1820 bytes
-rw-r--r--IconThemes/mono/scalable/actions/halflinebyvector.svgzbin0 -> 2034 bytes
-rw-r--r--IconThemes/mono/scalable/actions/harmonichomology.svgzbin0 -> 1758 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hdd.svgzbin0 -> 1464 bytes
-rw-r--r--IconThemes/mono/scalable/actions/help.svgzbin0 -> 2526 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hexagonbcv.svgzbin0 -> 1703 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hibernate.svgzbin0 -> 1126 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hide_table_column.svgzbin0 -> 2946 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hide_table_row.svgzbin0 -> 2938 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hidemouse.svgzbin0 -> 1430 bytes
-rw-r--r--IconThemes/mono/scalable/actions/highlighting.svgzbin0 -> 3981 bytes
-rw-r--r--IconThemes/mono/scalable/actions/highscore.svgzbin0 -> 10205 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hint.svgzbin0 -> 2543 bytes
-rw-r--r--IconThemes/mono/scalable/actions/history.svgzbin0 -> 1633 bytes
-rw-r--r--IconThemes/mono/scalable/actions/history_clear.svgzbin0 -> 1781 bytes
-rw-r--r--IconThemes/mono/scalable/actions/homepage.svgzbin0 -> 2568 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hotmail.svgzbin0 -> 1573 bytes
-rw-r--r--IconThemes/mono/scalable/actions/htmlvalidator.svgzbin0 -> 3110 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hue.svgzbin0 -> 3021 bytes
-rw-r--r--IconThemes/mono/scalable/actions/hyperbolabffp.svgzbin0 -> 2005 bytes
-rw-r--r--IconThemes/mono/scalable/actions/icq_away.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/icq_invisible.svgzbin0 -> 3208 bytes
-rw-r--r--IconThemes/mono/scalable/actions/icq_offline.svgzbin0 -> 2906 bytes
-rw-r--r--IconThemes/mono/scalable/actions/icq_online.svgzbin0 -> 3028 bytes
-rw-r--r--IconThemes/mono/scalable/actions/icq_protocol.svgzbin0 -> 3030 bytes
-rw-r--r--IconThemes/mono/scalable/actions/id.svgzbin0 -> 1458 bytes
-rw-r--r--IconThemes/mono/scalable/actions/idea.svgzbin0 -> 3743 bytes
-rw-r--r--IconThemes/mono/scalable/actions/identity.svgzbin0 -> 2085 bytes
-rw-r--r--IconThemes/mono/scalable/actions/idf.svgzbin0 -> 1745 bytes
-rw-r--r--IconThemes/mono/scalable/actions/idh.svgzbin0 -> 1753 bytes
-rw-r--r--IconThemes/mono/scalable/actions/imagecomment.svgzbin0 -> 2406 bytes
-rw-r--r--IconThemes/mono/scalable/actions/imagegallery.svgzbin0 -> 2226 bytes
-rw-r--r--IconThemes/mono/scalable/actions/images_display.svgzbin0 -> 2236 bytes
-rw-r--r--IconThemes/mono/scalable/actions/indent.svgzbin0 -> 2004 bytes
-rw-r--r--IconThemes/mono/scalable/actions/info.svgzbin0 -> 1811 bytes
-rw-r--r--IconThemes/mono/scalable/actions/inline_image.svgzbin0 -> 2338 bytes
-rw-r--r--IconThemes/mono/scalable/actions/inline_table.svgzbin0 -> 1958 bytes
-rw-r--r--IconThemes/mono/scalable/actions/inscol.svgzbin0 -> 2650 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insert_arg.svgzbin0 -> 3174 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insert_chart.svgzbin0 -> 2363 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insert_link.svgzbin0 -> 1921 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insert_table_col.svgzbin0 -> 2660 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insert_table_row.svgzbin0 -> 2723 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insert_tag.svgzbin0 -> 2198 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insertcell.svgzbin0 -> 2103 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insertcellcopy.svgzbin0 -> 2107 bytes
-rw-r--r--IconThemes/mono/scalable/actions/inserttable.svgzbin0 -> 1647 bytes
-rw-r--r--IconThemes/mono/scalable/actions/insrow.svgzbin0 -> 2713 bytes
-rw-r--r--IconThemes/mono/scalable/actions/int.svgzbin0 -> 3166 bytes
-rw-r--r--IconThemes/mono/scalable/actions/integral_func.svgzbin0 -> 2627 bytes
-rw-r--r--IconThemes/mono/scalable/actions/intersection.svgzbin0 -> 1665 bytes
-rw-r--r--IconThemes/mono/scalable/actions/inversion.svgzbin0 -> 1670 bytes
-rw-r--r--IconThemes/mono/scalable/actions/invert.svgzbin0 -> 1525 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ipf.svgzbin0 -> 1789 bytes
-rw-r--r--IconThemes/mono/scalable/actions/iph.svgzbin0 -> 1793 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irc_away.svgzbin0 -> 1925 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irc_normal.svgzbin0 -> 2570 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irc_online.svgzbin0 -> 4453 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irc_server.svgzbin0 -> 2570 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irc_voice.svgzbin0 -> 1708 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irf.svgzbin0 -> 1550 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irh.svgzbin0 -> 1583 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irkick.svgzbin0 -> 2169 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irkickflash.svgzbin0 -> 1934 bytes
-rw-r--r--IconThemes/mono/scalable/actions/irkickoff.svgzbin0 -> 1527 bytes
-rw-r--r--IconThemes/mono/scalable/actions/isotopemap.svgzbin0 -> 2757 bytes
-rw-r--r--IconThemes/mono/scalable/actions/italic.svgzbin0 -> 2178 bytes
-rw-r--r--IconThemes/mono/scalable/actions/item_add.svgzbin0 -> 1851 bytes
-rw-r--r--IconThemes/mono/scalable/actions/item_remove.svgzbin0 -> 1649 bytes
-rw-r--r--IconThemes/mono/scalable/actions/item_rename.svgzbin0 -> 2935 bytes
-rw-r--r--IconThemes/mono/scalable/actions/jabber_offline.svgzbin0 -> 3542 bytes
-rw-r--r--IconThemes/mono/scalable/actions/jabber_online.svgzbin0 -> 3752 bytes
-rw-r--r--IconThemes/mono/scalable/actions/jabber_protocol.svgzbin0 -> 3754 bytes
-rw-r--r--IconThemes/mono/scalable/actions/jail_pay.svgzbin0 -> 3459 bytes
-rw-r--r--IconThemes/mono/scalable/actions/join_bevel.svgzbin0 -> 1581 bytes
-rw-r--r--IconThemes/mono/scalable/actions/join_miter.svgzbin0 -> 1602 bytes
-rw-r--r--IconThemes/mono/scalable/actions/join_round.svgzbin0 -> 1576 bytes
-rw-r--r--IconThemes/mono/scalable/actions/journal.svgzbin0 -> 2219 bytes
-rw-r--r--IconThemes/mono/scalable/actions/juk_dock.svgzbin0 -> 1747 bytes
-rw-r--r--IconThemes/mono/scalable/actions/juk_time.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kaboodleloop.svgzbin0 -> 1780 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kalarm.svgzbin0 -> 2704 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kalarm_disabled.svgzbin0 -> 3113 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kanjidic.svgzbin0 -> 4109 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kazaadown.svgzbin0 -> 1546 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kazaaup.svgzbin0 -> 1545 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kbear-firewall.svgzbin0 -> 3044 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kbearsitemanager.svgzbin0 -> 3046 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kbearsitemanagerdb.svgzbin0 -> 3048 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kbruch_exercise_common.svgzbin0 -> 5615 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kbruch_exercise_compare.svgzbin0 -> 6251 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kbruch_exercise_conversion.svgzbin0 -> 7393 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kbruch_exercise_factorisation.svgzbin0 -> 4453 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdat.svgzbin0 -> 1980 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdb_form.svgzbin0 -> 2208 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdb_table.svgzbin0 -> 1645 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kde1.svgzbin0 -> 2322 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kde2.svgzbin0 -> 2371 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kde3.svgzbin0 -> 2322 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kde4.svgzbin0 -> 2371 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kde5.svgzbin0 -> 2322 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kde6.svgzbin0 -> 2371 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_addprinter.svgzbin0 -> 2983 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_addpseudo.svgzbin0 -> 2774 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_configmgr.svgzbin0 -> 2043 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_configsrv.svgzbin0 -> 2043 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_defaulthard.svgzbin0 -> 1835 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_defaultsoft.svgzbin0 -> 1732 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_printer_infos.svgzbin0 -> 1829 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_printstate.svgzbin0 -> 2584 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_queuestate.svgzbin0 -> 2636 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_report.svgzbin0 -> 2130 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_restartsrv.svgzbin0 -> 1559 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_stopprinter.svgzbin0 -> 2585 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_testprinter.svgzbin0 -> 4504 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdeprint_uploadsmb.svgzbin0 -> 2384 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdevelop_down.svgzbin0 -> 1550 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdissert_link.svgzbin0 -> 1662 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdissert_point.svgzbin0 -> 1367 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kdissert_sort.svgzbin0 -> 4679 bytes
-rw-r--r--IconThemes/mono/scalable/actions/key.svgzbin0 -> 2660 bytes
-rw-r--r--IconThemes/mono/scalable/actions/key_enter.svgzbin0 -> 1753 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kget_dock.svgzbin0 -> 2979 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kget_dock_download.svgzbin0 -> 1190 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_edit.svgzbin0 -> 2034 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_export.svgzbin0 -> 1698 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_gen.svgzbin0 -> 2665 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_identity.svgzbin0 -> 2085 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_import.svgzbin0 -> 1700 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_info.svgzbin0 -> 2403 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_photo.svgzbin0 -> 2049 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_show.svgzbin0 -> 2126 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_sign.svgzbin0 -> 3445 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kgpg_term.svgzbin0 -> 1601 bytes
-rw-r--r--IconThemes/mono/scalable/actions/khotkeys.svgzbin0 -> 5238 bytes
-rw-r--r--IconThemes/mono/scalable/actions/khtml_kget.svgzbin0 -> 2985 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kig_numbers.svgzbin0 -> 2832 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kig_polygon.svgzbin0 -> 1849 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kig_text.svgzbin0 -> 2938 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kiten.svgzbin0 -> 4106 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_arrow.svgzbin0 -> 1373 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_connector.svgzbin0 -> 2004 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_text.svgzbin0 -> 2934 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_zoom.svgzbin0 -> 1957 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_zoom_hand.svgzbin0 -> 1931 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_zoom_height.svgzbin0 -> 2156 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_zoom_minus.svgzbin0 -> 2207 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_zoom_page.svgzbin0 -> 1753 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_zoom_plus.svgzbin0 -> 2394 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kivio_zoom_width.svgzbin0 -> 2144 bytes
-rw-r--r--IconThemes/mono/scalable/actions/klettres_desert.svgzbin0 -> 1956 bytes
-rw-r--r--IconThemes/mono/scalable/actions/klettres_grownup.svgzbin0 -> 1991 bytes
-rw-r--r--IconThemes/mono/scalable/actions/klettres_kids.svgzbin0 -> 2054 bytes
-rw-r--r--IconThemes/mono/scalable/actions/klipper_doc.svgzbin0 -> 1726 bytes
-rw-r--r--IconThemes/mono/scalable/actions/klipper_dock.svgzbin0 -> 1727 bytes
-rw-r--r--IconThemes/mono/scalable/actions/klipper_dock2.svgzbin0 -> 2992 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmaway.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmback.svgzbin0 -> 2251 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmbsy.svgzbin0 -> 2075 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmlunch.svgzbin0 -> 2515 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgattachment.svgzbin0 -> 1430 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgflag.svgzbin0 -> 1544 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgforwarded.svgzbin0 -> 1686 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgignored.svgzbin0 -> 1583 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgnew.svgzbin0 -> 2665 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgread.svgzbin0 -> 1723 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgreplied.svgzbin0 -> 1700 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgtodo.svgzbin0 -> 2389 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgunseen.svgzbin0 -> 1574 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmmsgwatched.svgzbin0 -> 2129 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmoffline.svgzbin0 -> 2079 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmonline.svgzbin0 -> 2253 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmousetool_off.svgzbin0 -> 2034 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmousetool_on.svgzbin0 -> 2075 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kmphone.svgzbin0 -> 3297 bytes
-rw-r--r--IconThemes/mono/scalable/actions/knewstuff.svgzbin0 -> 1485 bytes
-rw-r--r--IconThemes/mono/scalable/actions/knotes_close.svgzbin0 -> 1583 bytes
-rw-r--r--IconThemes/mono/scalable/actions/knotes_date.svgzbin0 -> 3366 bytes
-rw-r--r--IconThemes/mono/scalable/actions/knotes_delete.svgzbin0 -> 1781 bytes
-rw-r--r--IconThemes/mono/scalable/actions/know.svgzbin0 -> 3743 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_contacts.svgzbin0 -> 2868 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_date.svgzbin0 -> 3367 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_journal.svgzbin0 -> 2227 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_mail.svgzbin0 -> 1578 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_news.svgzbin0 -> 3049 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_notes.svgzbin0 -> 2978 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_summary.svgzbin0 -> 3125 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_summary_green.svgzbin0 -> 3131 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kontact_todo.svgzbin0 -> 2403 bytes
-rw-r--r--IconThemes/mono/scalable/actions/konv_message.svgzbin0 -> 4336 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kopeteavailable.svgzbin0 -> 1727 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kopeteaway.svgzbin0 -> 1636 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kopeteeditstatusmessage.svgzbin0 -> 2398 bytes
-rw-r--r--IconThemes/mono/scalable/actions/korgac.svgzbin0 -> 2873 bytes
-rw-r--r--IconThemes/mono/scalable/actions/korgac_disabled.svgzbin0 -> 2366 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kpilotaddress.svgzbin0 -> 2237 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kpilotbhotsync.svgzbin0 -> 1528 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kpilotcalendar.svgzbin0 -> 2476 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kpilotdb.svgzbin0 -> 3115 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kpilotfileinstaller.svgzbin0 -> 1999 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kpilotknotes.svgzbin0 -> 2400 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kpilottodo.svgzbin0 -> 2389 bytes
-rw-r--r--IconThemes/mono/scalable/actions/krec_record.svgzbin0 -> 3670 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kroete.svgzbin0 -> 1825 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ksirc_dock.svgzbin0 -> 4453 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_advanced.svgzbin0 -> 2040 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_catalog.svgzbin0 -> 2072 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_cbound.svgzbin0 -> 1657 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_clines.svgzbin0 -> 1782 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_cnames.svgzbin0 -> 2785 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_colors.svgzbin0 -> 2183 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_deepsky.svgzbin0 -> 2055 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_geo.svgzbin0 -> 2565 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_grid.svgzbin0 -> 1739 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_guides.svgzbin0 -> 1473 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_horizon.svgzbin0 -> 2553 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_mw.svgzbin0 -> 2145 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_planets.svgzbin0 -> 2490 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_solarsystem.svgzbin0 -> 2494 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kstars_stars.svgzbin0 -> 1974 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ksys1.svgzbin0 -> 1715 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ksys2.svgzbin0 -> 1755 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ksys3.svgzbin0 -> 1770 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktinfowidget.svgzbin0 -> 2163 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktip.svgzbin0 -> 3743 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktnef_extract_all_to.svgzbin0 -> 2206 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktnef_extract_to.svgzbin0 -> 2235 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktplugins.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktqueuemanager.svgzbin0 -> 2622 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktremove.svgzbin0 -> 1620 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktstart.svgzbin0 -> 1530 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktstart_all.svgzbin0 -> 1749 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktstop.svgzbin0 -> 2501 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ktstop_all.svgzbin0 -> 2774 bytes
-rw-r--r--IconThemes/mono/scalable/actions/kverbosuser.svgzbin0 -> 1723 bytes
-rw-r--r--IconThemes/mono/scalable/actions/label.svgzbin0 -> 2465 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lan.svgzbin0 -> 2169 bytes
-rw-r--r--IconThemes/mono/scalable/actions/languages.svgzbin0 -> 2938 bytes
-rw-r--r--IconThemes/mono/scalable/actions/laptop_charge.svgzbin0 -> 2447 bytes
-rw-r--r--IconThemes/mono/scalable/actions/laptop_nobattery.svgzbin0 -> 1843 bytes
-rw-r--r--IconThemes/mono/scalable/actions/laptop_nocharge.svgzbin0 -> 1846 bytes
-rw-r--r--IconThemes/mono/scalable/actions/laptop_power.svgzbin0 -> 2172 bytes
-rw-r--r--IconThemes/mono/scalable/actions/laptoppower.svgzbin0 -> 2129 bytes
-rw-r--r--IconThemes/mono/scalable/actions/largethumbnails.svgzbin0 -> 1821 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lastmoves.svgzbin0 -> 1528 bytes
-rw-r--r--IconThemes/mono/scalable/actions/launch.svgzbin0 -> 3190 bytes
-rw-r--r--IconThemes/mono/scalable/actions/layer_editable.svgzbin0 -> 1831 bytes
-rw-r--r--IconThemes/mono/scalable/actions/layer_noeditable.svgzbin0 -> 1805 bytes
-rw-r--r--IconThemes/mono/scalable/actions/layer_noprint.svgzbin0 -> 1867 bytes
-rw-r--r--IconThemes/mono/scalable/actions/layer_print.svgzbin0 -> 2024 bytes
-rw-r--r--IconThemes/mono/scalable/actions/layer_visible.svgzbin0 -> 2989 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ldap_lookup.svgzbin0 -> 1923 bytes
-rw-r--r--IconThemes/mono/scalable/actions/leftjust.svgzbin0 -> 1766 bytes
-rw-r--r--IconThemes/mono/scalable/actions/legalmoves.svgzbin0 -> 1564 bytes
-rw-r--r--IconThemes/mono/scalable/actions/legend.svgzbin0 -> 1804 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lessen.svgzbin0 -> 2197 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line.svgzbin0 -> 1362 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_arrow_begin.svgzbin0 -> 1565 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_arrow_end.svgzbin0 -> 1552 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_begin.svgzbin0 -> 1588 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_circle_begin.svgzbin0 -> 1568 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_circle_end.svgzbin0 -> 1571 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_dimension_line_begin.svgzbin0 -> 1535 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_dimension_line_end.svgzbin0 -> 1538 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_double_arrow_begin.svgzbin0 -> 1729 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_double_arrow_end.svgzbin0 -> 1750 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_double_line_arrow_begin.svgzbin0 -> 1639 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_double_line_arrow_end.svgzbin0 -> 1666 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_end.svgzbin0 -> 1623 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_line_arrow_begin.svgzbin0 -> 1566 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_line_arrow_end.svgzbin0 -> 1588 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_normal_begin.svgzbin0 -> 1400 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_normal_end.svgzbin0 -> 1398 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_rect_begin.svgzbin0 -> 1618 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_rect_end.svgzbin0 -> 1621 bytes
-rw-r--r--IconThemes/mono/scalable/actions/line_width.svgzbin0 -> 1711 bytes
-rw-r--r--IconThemes/mono/scalable/actions/linebyvector.svgzbin0 -> 1867 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lineedit.svgzbin0 -> 1496 bytes
-rw-r--r--IconThemes/mono/scalable/actions/linewidth.svgzbin0 -> 1710 bytes
-rw-r--r--IconThemes/mono/scalable/actions/linked.svgzbin0 -> 1994 bytes
-rw-r--r--IconThemes/mono/scalable/actions/list.svgzbin0 -> 2232 bytes
-rw-r--r--IconThemes/mono/scalable/actions/listbox.svgzbin0 -> 1595 bytes
-rw-r--r--IconThemes/mono/scalable/actions/listview.svgzbin0 -> 1690 bytes
-rw-r--r--IconThemes/mono/scalable/actions/locationbar_erase.svgzbin0 -> 1975 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lock.svgzbin0 -> 1774 bytes
-rw-r--r--IconThemes/mono/scalable/actions/locked.svgzbin0 -> 1776 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lockzoom.svgzbin0 -> 1778 bytes
-rw-r--r--IconThemes/mono/scalable/actions/locus.svgzbin0 -> 1943 bytes
-rw-r--r--IconThemes/mono/scalable/actions/loop.svgzbin0 -> 1772 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lower.svgzbin0 -> 1697 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lowerlayer.svgzbin0 -> 1438 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lsub.svgzbin0 -> 3364 bytes
-rw-r--r--IconThemes/mono/scalable/actions/lsup.svgzbin0 -> 3369 bytes
-rw-r--r--IconThemes/mono/scalable/actions/magnify.svgzbin0 -> 2386 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_delete.svgzbin0 -> 1930 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_find.svgzbin0 -> 1956 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_flag.svgzbin0 -> 1544 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_forward.svgzbin0 -> 2111 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_generic.svgzbin0 -> 1578 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_get.svgzbin0 -> 1955 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_ham.svgzbin0 -> 1430 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_ignore.svgzbin0 -> 1583 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_new.svgzbin0 -> 2203 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_new3.svgzbin0 -> 2204 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_post_to.svgzbin0 -> 1944 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_post_to3.svgzbin0 -> 1945 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_reply.svgzbin0 -> 2112 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_replyall.svgzbin0 -> 2291 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_replylist.svgzbin0 -> 2403 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_send.svgzbin0 -> 1941 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_send_via.svgzbin0 -> 1941 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_spam.svgzbin0 -> 1991 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mail_todo.svgzbin0 -> 2389 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mailappt.svgzbin0 -> 1574 bytes
-rw-r--r--IconThemes/mono/scalable/actions/make.svgzbin0 -> 13358 bytes
-rw-r--r--IconThemes/mono/scalable/actions/make_kdevelop.svgzbin0 -> 13367 bytes
-rw-r--r--IconThemes/mono/scalable/actions/markasblank.svgzbin0 -> 1661 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_abs.svgzbin0 -> 3247 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_brace.svgzbin0 -> 4180 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_brackets.svgzbin0 -> 2939 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_frac.svgzbin0 -> 3990 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_int.svgzbin0 -> 3171 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_lsub.svgzbin0 -> 3369 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_lsup.svgzbin0 -> 3374 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_matrix.svgzbin0 -> 2251 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_onetwomatrix.svgzbin0 -> 3870 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_paren.svgzbin0 -> 3456 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_prod.svgzbin0 -> 1611 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_rsub.svgzbin0 -> 3388 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_rsup.svgzbin0 -> 3379 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_sqrt.svgzbin0 -> 3207 bytes
-rw-r--r--IconThemes/mono/scalable/actions/math_sum.svgzbin0 -> 1308 bytes
-rw-r--r--IconThemes/mono/scalable/actions/matrix.svgzbin0 -> 2246 bytes
-rw-r--r--IconThemes/mono/scalable/actions/maximum.svgzbin0 -> 2024 bytes
-rw-r--r--IconThemes/mono/scalable/actions/medthumbnails.svgzbin0 -> 2117 bytes
-rw-r--r--IconThemes/mono/scalable/actions/menu_new.svgzbin0 -> 2409 bytes
-rw-r--r--IconThemes/mono/scalable/actions/menu_new_sep.svgzbin0 -> 1390 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mergecell.svgzbin0 -> 1764 bytes
-rw-r--r--IconThemes/mono/scalable/actions/message.svgzbin0 -> 3728 bytes
-rw-r--r--IconThemes/mono/scalable/actions/message_reply.svgzbin0 -> 2166 bytes
-rw-r--r--IconThemes/mono/scalable/actions/messagebox_critical.svgzbin0 -> 1590 bytes
-rw-r--r--IconThemes/mono/scalable/actions/messagebox_info.svgzbin0 -> 1822 bytes
-rw-r--r--IconThemes/mono/scalable/actions/messagebox_warning.svgzbin0 -> 2103 bytes
-rw-r--r--IconThemes/mono/scalable/actions/metacontact_away.svgzbin0 -> 1438 bytes
-rw-r--r--IconThemes/mono/scalable/actions/metacontact_offline.svgzbin0 -> 1153 bytes
-rw-r--r--IconThemes/mono/scalable/actions/metacontact_online.svgzbin0 -> 2675 bytes
-rw-r--r--IconThemes/mono/scalable/actions/metacontact_unknown.svgzbin0 -> 2497 bytes
-rw-r--r--IconThemes/mono/scalable/actions/middle.svgzbin0 -> 1674 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mini_autoform.svgzbin0 -> 1465 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mini_circle.svgzbin0 -> 1474 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mini_clipart.svgzbin0 -> 2051 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mini_dock.svgzbin0 -> 1418 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mini_line.svgzbin0 -> 1367 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mini_pie.svgzbin0 -> 1509 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mini_polygon.svgzbin0 -> 1479 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mini_rect.svgzbin0 -> 1523 bytes
-rw-r--r--IconThemes/mono/scalable/actions/minimum.svgzbin0 -> 2008 bytes
-rw-r--r--IconThemes/mono/scalable/actions/minitools.svgzbin0 -> 1458 bytes
-rw-r--r--IconThemes/mono/scalable/actions/miror.svgzbin0 -> 1746 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mirror-both.svgzbin0 -> 1766 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mirror-horiz.svgzbin0 -> 1753 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mirror-vert.svgzbin0 -> 1755 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mirror.svgzbin0 -> 1747 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mirrorpoint.svgzbin0 -> 1626 bytes
-rw-r--r--IconThemes/mono/scalable/actions/misc.svgzbin0 -> 1571 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mode1.svgzbin0 -> 1653 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mode2.svgzbin0 -> 1678 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mode3.svgzbin0 -> 1626 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mode4.svgzbin0 -> 1644 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mode5.svgzbin0 -> 1707 bytes
-rw-r--r--IconThemes/mono/scalable/actions/modified.svgzbin0 -> 2665 bytes
-rw-r--r--IconThemes/mono/scalable/actions/money.svgzbin0 -> 2695 bytes
-rw-r--r--IconThemes/mono/scalable/actions/monop_board.svgzbin0 -> 3063 bytes
-rw-r--r--IconThemes/mono/scalable/actions/month.svgzbin0 -> 2504 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mouse.svgzbin0 -> 2056 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mouse_pointer.svgzbin0 -> 1367 bytes
-rw-r--r--IconThemes/mono/scalable/actions/move.svgzbin0 -> 1571 bytes
-rw-r--r--IconThemes/mono/scalable/actions/msgid2msgstr.svgzbin0 -> 1867 bytes
-rw-r--r--IconThemes/mono/scalable/actions/msn_away.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/msn_blocked.svgzbin0 -> 1927 bytes
-rw-r--r--IconThemes/mono/scalable/actions/msn_invisible.svgzbin0 -> 2478 bytes
-rw-r--r--IconThemes/mono/scalable/actions/msn_offline.svgzbin0 -> 2366 bytes
-rw-r--r--IconThemes/mono/scalable/actions/msn_online.svgzbin0 -> 2293 bytes
-rw-r--r--IconThemes/mono/scalable/actions/msn_phone.svgzbin0 -> 3294 bytes
-rw-r--r--IconThemes/mono/scalable/actions/msn_protocol.svgzbin0 -> 2295 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mug.svgzbin0 -> 3140 bytes
-rw-r--r--IconThemes/mono/scalable/actions/multiline.svgzbin0 -> 2445 bytes
-rw-r--r--IconThemes/mono/scalable/actions/multiple.svgzbin0 -> 2562 bytes
-rw-r--r--IconThemes/mono/scalable/actions/multirow.svgzbin0 -> 1803 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_32ndnote.svgzbin0 -> 2382 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_cleficon.svgzbin0 -> 1855 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_cross.svgzbin0 -> 1540 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_dottednote.svgzbin0 -> 1732 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_eightnote.svgzbin0 -> 1817 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_fermatenote.svgzbin0 -> 1680 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_flat.svgzbin0 -> 1502 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_fullnote.svgzbin0 -> 1379 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_halfnote.svgzbin0 -> 1553 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_natur.svgzbin0 -> 1576 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_quarternote.svgzbin0 -> 1486 bytes
-rw-r--r--IconThemes/mono/scalable/actions/music_sixteenthnote.svgzbin0 -> 2042 bytes
-rw-r--r--IconThemes/mono/scalable/actions/mute.svgzbin0 -> 1736 bytes
-rw-r--r--IconThemes/mono/scalable/actions/napsterdown.svgzbin0 -> 1643 bytes
-rw-r--r--IconThemes/mono/scalable/actions/napsterup.svgzbin0 -> 1628 bytes
-rw-r--r--IconThemes/mono/scalable/actions/navigator_first.svgzbin0 -> 1462 bytes
-rw-r--r--IconThemes/mono/scalable/actions/navigator_last.svgzbin0 -> 1485 bytes
-rw-r--r--IconThemes/mono/scalable/actions/navigator_new.svgzbin0 -> 1843 bytes
-rw-r--r--IconThemes/mono/scalable/actions/navigator_next.svgzbin0 -> 1295 bytes
-rw-r--r--IconThemes/mono/scalable/actions/navigator_prev.svgzbin0 -> 1302 bytes
-rw-r--r--IconThemes/mono/scalable/actions/neonpen.svgzbin0 -> 2311 bytes
-rw-r--r--IconThemes/mono/scalable/actions/netactivity_full.svgzbin0 -> 2540 bytes
-rw-r--r--IconThemes/mono/scalable/actions/netactivity_none.svgzbin0 -> 2592 bytes
-rw-r--r--IconThemes/mono/scalable/actions/netactivity_off.svgzbin0 -> 1858 bytes
-rw-r--r--IconThemes/mono/scalable/actions/netactivity_rx.svgzbin0 -> 2539 bytes
-rw-r--r--IconThemes/mono/scalable/actions/netactivity_tx.svgzbin0 -> 2541 bytes
-rw-r--r--IconThemes/mono/scalable/actions/network.svgzbin0 -> 1638 bytes
-rw-r--r--IconThemes/mono/scalable/actions/network_connected.svgzbin0 -> 2593 bytes
-rw-r--r--IconThemes/mono/scalable/actions/network_disconnected.svgzbin0 -> 1863 bytes
-rw-r--r--IconThemes/mono/scalable/actions/network_incoming.svgzbin0 -> 2541 bytes
-rw-r--r--IconThemes/mono/scalable/actions/network_outgoing.svgzbin0 -> 2543 bytes
-rw-r--r--IconThemes/mono/scalable/actions/network_traffic.svgzbin0 -> 2539 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newfont.svgzbin0 -> 4423 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newfunction.svgzbin0 -> 2053 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newlayer.svgzbin0 -> 1860 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newmsg.svgzbin0 -> 2201 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newnum.svgzbin0 -> 2720 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newparametric.svgzbin0 -> 2085 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newpolar.svgzbin0 -> 2324 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newrecurevent.svgzbin0 -> 3052 bytes
-rw-r--r--IconThemes/mono/scalable/actions/news_subscribe.svgzbin0 -> 3051 bytes
-rw-r--r--IconThemes/mono/scalable/actions/news_unsubscribe.svgzbin0 -> 3190 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newslide.svgzbin0 -> 2469 bytes
-rw-r--r--IconThemes/mono/scalable/actions/newtodo.svgzbin0 -> 2154 bytes
-rw-r--r--IconThemes/mono/scalable/actions/next.svgzbin0 -> 1544 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nexterror.svgzbin0 -> 2225 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nextfuzzy.svgzbin0 -> 4894 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nextfuzzyuntrans.svgzbin0 -> 5869 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nextmarked.svgzbin0 -> 2230 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nextpo.svgzbin0 -> 1609 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nexttemplate.svgzbin0 -> 2820 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nextuntranslated.svgzbin0 -> 2656 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nm_device_wired.svgzbin0 -> 2531 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nm_no_connection.svgzbin0 -> 1832 bytes
-rw-r--r--IconThemes/mono/scalable/actions/no.svgzbin0 -> 2567 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunback.svgzbin0 -> 1716 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunfback.svgzbin0 -> 1564 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunfforward.svgzbin0 -> 1565 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunforward.svgzbin0 -> 1715 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunloopnone.svgzbin0 -> 1499 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunloopplaylist.svgzbin0 -> 1786 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunlooprandom.svgzbin0 -> 1958 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunloopsong.svgzbin0 -> 1782 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunpause.svgzbin0 -> 1712 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunplay.svgzbin0 -> 1550 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunplaylist.svgzbin0 -> 1812 bytes
-rw-r--r--IconThemes/mono/scalable/actions/noatunstop.svgzbin0 -> 1569 bytes
-rw-r--r--IconThemes/mono/scalable/actions/nomailappt.svgzbin0 -> 1738 bytes
-rw-r--r--IconThemes/mono/scalable/actions/novisible.svgzbin0 -> 3029 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ocr-select.svgzbin0 -> 4133 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ocr.svgzbin0 -> 3902 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ocrImage.svgzbin0 -> 3311 bytes
-rw-r--r--IconThemes/mono/scalable/actions/oilpaint.svgzbin0 -> 2178 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ok.svgzbin0 -> 1421 bytes
-rw-r--r--IconThemes/mono/scalable/actions/onetwomatrix.svgzbin0 -> 3865 bytes
-rw-r--r--IconThemes/mono/scalable/actions/online_status.svgzbin0 -> 1638 bytes
-rw-r--r--IconThemes/mono/scalable/actions/open_stencilset.svgzbin0 -> 1653 bytes
-rw-r--r--IconThemes/mono/scalable/actions/openftdown.svgzbin0 -> 1547 bytes
-rw-r--r--IconThemes/mono/scalable/actions/openftup.svgzbin0 -> 1546 bytes
-rw-r--r--IconThemes/mono/scalable/actions/openterm.svgzbin0 -> 1600 bytes
-rw-r--r--IconThemes/mono/scalable/actions/opentermblue.svgzbin0 -> 1604 bytes
-rw-r--r--IconThemes/mono/scalable/actions/opentermred.svgzbin0 -> 1781 bytes
-rw-r--r--IconThemes/mono/scalable/actions/options.svgzbin0 -> 2032 bytes
-rw-r--r--IconThemes/mono/scalable/actions/optvar.svgzbin0 -> 2953 bytes
-rw-r--r--IconThemes/mono/scalable/actions/optwildcards.svgzbin0 -> 2858 bytes
-rw-r--r--IconThemes/mono/scalable/actions/orbits.svgzbin0 -> 2595 bytes
-rw-r--r--IconThemes/mono/scalable/actions/organizer.svgzbin0 -> 3500 bytes
-rw-r--r--IconThemes/mono/scalable/actions/oscilloscope.svgzbin0 -> 2007 bytes
-rw-r--r--IconThemes/mono/scalable/actions/over.svgzbin0 -> 3155 bytes
-rw-r--r--IconThemes/mono/scalable/actions/overview.svgzbin0 -> 2355 bytes
-rw-r--r--IconThemes/mono/scalable/actions/page.svgzbin0 -> 1493 bytes
-rw-r--r--IconThemes/mono/scalable/actions/paint.svgzbin0 -> 2110 bytes
-rw-r--r--IconThemes/mono/scalable/actions/paintbrush.svgzbin0 -> 2110 bytes
-rw-r--r--IconThemes/mono/scalable/actions/palette_color.svgzbin0 -> 2183 bytes
-rw-r--r--IconThemes/mono/scalable/actions/palette_gray.svgzbin0 -> 2182 bytes
-rw-r--r--IconThemes/mono/scalable/actions/palette_halftone.svgzbin0 -> 2186 bytes
-rw-r--r--IconThemes/mono/scalable/actions/palette_lineart.svgzbin0 -> 2185 bytes
-rw-r--r--IconThemes/mono/scalable/actions/parabolabtp.svgzbin0 -> 1698 bytes
-rw-r--r--IconThemes/mono/scalable/actions/parallel.svgzbin0 -> 1549 bytes
-rw-r--r--IconThemes/mono/scalable/actions/paren.svgzbin0 -> 3451 bytes
-rw-r--r--IconThemes/mono/scalable/actions/party.svgzbin0 -> 2785 bytes
-rw-r--r--IconThemes/mono/scalable/actions/paste.svgzbin0 -> 2236 bytes
-rw-r--r--IconThemes/mono/scalable/actions/paste_stencil.svgzbin0 -> 2244 bytes
-rw-r--r--IconThemes/mono/scalable/actions/patch.svgzbin0 -> 1391 bytes
-rw-r--r--IconThemes/mono/scalable/actions/path.svgzbin0 -> 2166 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_style.svgzbin0 -> 2742 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_style_dash.svgzbin0 -> 1496 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_style_dashdot.svgzbin0 -> 1643 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_style_dashdotdot.svgzbin0 -> 1670 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_style_dot.svgzbin0 -> 2066 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_style_nopen.svgzbin0 -> 1804 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_style_solid.svgzbin0 -> 1413 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width.svgzbin0 -> 1710 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width1.svgzbin0 -> 1389 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width10.svgzbin0 -> 1372 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width2.svgzbin0 -> 1377 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width3.svgzbin0 -> 1402 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width4.svgzbin0 -> 1387 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width5.svgzbin0 -> 1377 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width6.svgzbin0 -> 1376 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width7.svgzbin0 -> 1377 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width8.svgzbin0 -> 1375 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pen_width9.svgzbin0 -> 1378 bytes
-rw-r--r--IconThemes/mono/scalable/actions/penbrush.svgzbin0 -> 2264 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pencil.svgzbin0 -> 1823 bytes
-rw-r--r--IconThemes/mono/scalable/actions/percent.svgzbin0 -> 3265 bytes
-rw-r--r--IconThemes/mono/scalable/actions/perpendicular.svgzbin0 -> 1716 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pgnum.svgzbin0 -> 2719 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pgp-keys.svgzbin0 -> 1778 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrase.svgzbin0 -> 1783 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrase_new.svgzbin0 -> 2315 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrase_open.svgzbin0 -> 2550 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrase_save.svgzbin0 -> 2431 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrasebook.svgzbin0 -> 2200 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrasebook_closed.svgzbin0 -> 2442 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrasebook_new.svgzbin0 -> 2972 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrasebook_open.svgzbin0 -> 2905 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrasebook_save.svgzbin0 -> 2789 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrasehistory_open.svgzbin0 -> 2031 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrasehistory_print.svgzbin0 -> 2032 bytes
-rw-r--r--IconThemes/mono/scalable/actions/phrasehistory_save.svgzbin0 -> 1717 bytes
-rw-r--r--IconThemes/mono/scalable/actions/piano.svgzbin0 -> 2379 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pixmaplabel.svgzbin0 -> 2050 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_eject.svgzbin0 -> 1718 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_end.svgzbin0 -> 1712 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_fwd.svgzbin0 -> 1561 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_mute.svgzbin0 -> 1743 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_pause.svgzbin0 -> 1713 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_play.svgzbin0 -> 1551 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_playlist.svgzbin0 -> 1813 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_playlist_2.svgzbin0 -> 1815 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_record.svgzbin0 -> 3672 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_rew.svgzbin0 -> 1563 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_start.svgzbin0 -> 1718 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_stop.svgzbin0 -> 1570 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_time.svgzbin0 -> 1714 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_volume.svgzbin0 -> 1463 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_volume_down.svgzbin0 -> 1310 bytes
-rw-r--r--IconThemes/mono/scalable/actions/player_volume_up.svgzbin0 -> 1314 bytes
-rw-r--r--IconThemes/mono/scalable/actions/playlist.svgzbin0 -> 1806 bytes
-rw-r--r--IconThemes/mono/scalable/actions/playsound.svgzbin0 -> 1774 bytes
-rw-r--r--IconThemes/mono/scalable/actions/plot.svgzbin0 -> 2026 bytes
-rw-r--r--IconThemes/mono/scalable/actions/podcast.svgzbin0 -> 1903 bytes
-rw-r--r--IconThemes/mono/scalable/actions/podcast_new.svgzbin0 -> 2587 bytes
-rw-r--r--IconThemes/mono/scalable/actions/point.svgzbin0 -> 1361 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pointOnLine.svgzbin0 -> 1555 bytes
-rw-r--r--IconThemes/mono/scalable/actions/pointxy.svgzbin0 -> 3228 bytes
-rw-r--r--IconThemes/mono/scalable/actions/polygon.svgzbin0 -> 1459 bytes
-rw-r--r--IconThemes/mono/scalable/actions/polygonsides.svgzbin0 -> 1349 bytes
-rw-r--r--IconThemes/mono/scalable/actions/polygonvertices.svgzbin0 -> 1896 bytes
-rw-r--r--IconThemes/mono/scalable/actions/polyline.svgzbin0 -> 2520 bytes
-rw-r--r--IconThemes/mono/scalable/actions/power.svgzbin0 -> 1994 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prec_minus.svgzbin0 -> 4755 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prec_plus.svgzbin0 -> 3931 bytes
-rw-r--r--IconThemes/mono/scalable/actions/precminus.svgzbin0 -> 4754 bytes
-rw-r--r--IconThemes/mono/scalable/actions/precplus.svgzbin0 -> 3930 bytes
-rw-r--r--IconThemes/mono/scalable/actions/preverror.svgzbin0 -> 2204 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prevfuzzy.svgzbin0 -> 4926 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prevfuzzyuntrans.svgzbin0 -> 5921 bytes
-rw-r--r--IconThemes/mono/scalable/actions/previewprint.svgzbin0 -> 2832 bytes
-rw-r--r--IconThemes/mono/scalable/actions/previous.svgzbin0 -> 1549 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prevmarked.svgzbin0 -> 2198 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prevpo.svgzbin0 -> 1629 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prevtemplate.svgzbin0 -> 2837 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prevuntranslated.svgzbin0 -> 2662 bytes
-rw-r--r--IconThemes/mono/scalable/actions/processor.svgzbin0 -> 4079 bytes
-rw-r--r--IconThemes/mono/scalable/actions/prod.svgzbin0 -> 1606 bytes
-rw-r--r--IconThemes/mono/scalable/actions/progress.svgzbin0 -> 1591 bytes
-rw-r--r--IconThemes/mono/scalable/actions/project_open.svgzbin0 -> 2627 bytes
-rw-r--r--IconThemes/mono/scalable/actions/properties.svgzbin0 -> 1980 bytes
-rw-r--r--IconThemes/mono/scalable/actions/python.svgzbin0 -> 2671 bytes
-rw-r--r--IconThemes/mono/scalable/actions/qa.svgzbin0 -> 4240 bytes
-rw-r--r--IconThemes/mono/scalable/actions/quadricbeziercurve.svgzbin0 -> 1791 bytes
-rw-r--r--IconThemes/mono/scalable/actions/queries.svgzbin0 -> 1919 bytes
-rw-r--r--IconThemes/mono/scalable/actions/query.svgzbin0 -> 1917 bytes
-rw-r--r--IconThemes/mono/scalable/actions/query_erase.svgzbin0 -> 1969 bytes
-rw-r--r--IconThemes/mono/scalable/actions/query_newobj.svgzbin0 -> 1924 bytes
-rw-r--r--IconThemes/mono/scalable/actions/question.svgzbin0 -> 3357 bytes
-rw-r--r--IconThemes/mono/scalable/actions/question_mark.svgzbin0 -> 2540 bytes
-rw-r--r--IconThemes/mono/scalable/actions/queue.svgzbin0 -> 2622 bytes
-rw-r--r--IconThemes/mono/scalable/actions/quick_start.svgzbin0 -> 2250 bytes
-rw-r--r--IconThemes/mono/scalable/actions/quiz.svgzbin0 -> 4242 bytes
-rw-r--r--IconThemes/mono/scalable/actions/radicalline.svgzbin0 -> 1657 bytes
-rw-r--r--IconThemes/mono/scalable/actions/radio.svgzbin0 -> 1704 bytes
-rw-r--r--IconThemes/mono/scalable/actions/raise.svgzbin0 -> 1692 bytes
-rw-r--r--IconThemes/mono/scalable/actions/raiselayer.svgzbin0 -> 1441 bytes
-rw-r--r--IconThemes/mono/scalable/actions/random.svgzbin0 -> 1958 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ray.svgzbin0 -> 1499 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rebuild.svgzbin0 -> 2764 bytes
-rw-r--r--IconThemes/mono/scalable/actions/reconcile.svgzbin0 -> 1428 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rectangle.svgzbin0 -> 1519 bytes
-rw-r--r--IconThemes/mono/scalable/actions/recur.svgzbin0 -> 1928 bytes
-rw-r--r--IconThemes/mono/scalable/actions/recursive.svgzbin0 -> 2040 bytes
-rw-r--r--IconThemes/mono/scalable/actions/red_ball.svgzbin0 -> 1336 bytes
-rw-r--r--IconThemes/mono/scalable/actions/redeyes.svgzbin0 -> 2983 bytes
-rw-r--r--IconThemes/mono/scalable/actions/redo.svgzbin0 -> 1495 bytes
-rw-r--r--IconThemes/mono/scalable/actions/relation.svgzbin0 -> 2282 bytes
-rw-r--r--IconThemes/mono/scalable/actions/reload.svgzbin0 -> 1948 bytes
-rw-r--r--IconThemes/mono/scalable/actions/reload3.svgzbin0 -> 1930 bytes
-rw-r--r--IconThemes/mono/scalable/actions/reload_all_tabs.svgzbin0 -> 1938 bytes
-rw-r--r--IconThemes/mono/scalable/actions/reload_page.svgzbin0 -> 2301 bytes
-rw-r--r--IconThemes/mono/scalable/actions/remcol.svgzbin0 -> 2260 bytes
-rw-r--r--IconThemes/mono/scalable/actions/remove.svgzbin0 -> 1577 bytes
-rw-r--r--IconThemes/mono/scalable/actions/removecell.svgzbin0 -> 1978 bytes
-rw-r--r--IconThemes/mono/scalable/actions/removecomment.svgzbin0 -> 2010 bytes
-rw-r--r--IconThemes/mono/scalable/actions/removepoint.svgzbin0 -> 2730 bytes
-rw-r--r--IconThemes/mono/scalable/actions/remrow.svgzbin0 -> 2293 bytes
-rw-r--r--IconThemes/mono/scalable/actions/repeat.svgzbin0 -> 2296 bytes
-rw-r--r--IconThemes/mono/scalable/actions/repeat_playlist.svgzbin0 -> 1786 bytes
-rw-r--r--IconThemes/mono/scalable/actions/repeat_track.svgzbin0 -> 1782 bytes
-rw-r--r--IconThemes/mono/scalable/actions/report.svgzbin0 -> 1919 bytes
-rw-r--r--IconThemes/mono/scalable/actions/report_newobj.svgzbin0 -> 1926 bytes
-rw-r--r--IconThemes/mono/scalable/actions/reports.svgzbin0 -> 1920 bytes
-rw-r--r--IconThemes/mono/scalable/actions/resdiropen.svgzbin0 -> 1977 bytes
-rw-r--r--IconThemes/mono/scalable/actions/reset.svgzbin0 -> 1584 bytes
-rw-r--r--IconThemes/mono/scalable/actions/resfiledel.svgzbin0 -> 1778 bytes
-rw-r--r--IconThemes/mono/scalable/actions/resfileedit.svgzbin0 -> 2405 bytes
-rw-r--r--IconThemes/mono/scalable/actions/resfileinfo.svgzbin0 -> 1818 bytes
-rw-r--r--IconThemes/mono/scalable/actions/resfileopen.svgzbin0 -> 2355 bytes
-rw-r--r--IconThemes/mono/scalable/actions/resize_image.svgzbin0 -> 1905 bytes
-rw-r--r--IconThemes/mono/scalable/actions/resizecol.svgzbin0 -> 1854 bytes
-rw-r--r--IconThemes/mono/scalable/actions/resizerow.svgzbin0 -> 1880 bytes
-rw-r--r--IconThemes/mono/scalable/actions/restart.svgzbin0 -> 1949 bytes
-rw-r--r--IconThemes/mono/scalable/actions/restore.svgzbin0 -> 1925 bytes
-rw-r--r--IconThemes/mono/scalable/actions/revert.svgzbin0 -> 2302 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rightjust.svgzbin0 -> 1640 bytes
-rw-r--r--IconThemes/mono/scalable/actions/roll.svgzbin0 -> 2221 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rotate.svgzbin0 -> 1534 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rotate_ccw.svgzbin0 -> 1570 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rotate_cw.svgzbin0 -> 1597 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rotate_left.svgzbin0 -> 1571 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rotate_right.svgzbin0 -> 1600 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rotation.svgzbin0 -> 2194 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rotation_acw.svgzbin0 -> 1572 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rotation_cw.svgzbin0 -> 1599 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rowcol.svgzbin0 -> 2720 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rsibreak0.svgzbin0 -> 1463 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rsibreak1.svgzbin0 -> 1566 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rsibreak2.svgzbin0 -> 1595 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rsibreak3.svgzbin0 -> 1592 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rsibreak4.svgzbin0 -> 1477 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rsibreakx.svgzbin0 -> 1555 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rss_tag.svgzbin0 -> 2087 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rsub.svgzbin0 -> 3383 bytes
-rw-r--r--IconThemes/mono/scalable/actions/rsup.svgzbin0 -> 3374 bytes
-rw-r--r--IconThemes/mono/scalable/actions/run.svgzbin0 -> 1570 bytes
-rw-r--r--IconThemes/mono/scalable/actions/run_bounding.svgzbin0 -> 1717 bytes
-rw-r--r--IconThemes/mono/scalable/actions/run_not.svgzbin0 -> 1671 bytes
-rw-r--r--IconThemes/mono/scalable/actions/run_skip.svgzbin0 -> 1811 bytes
-rw-r--r--IconThemes/mono/scalable/actions/runprog.svgzbin0 -> 1574 bytes
-rw-r--r--IconThemes/mono/scalable/actions/saturation.svgzbin0 -> 2297 bytes
-rw-r--r--IconThemes/mono/scalable/actions/save.svgzbin0 -> 1703 bytes
-rw-r--r--IconThemes/mono/scalable/actions/save_all.svgzbin0 -> 2186 bytes
-rw-r--r--IconThemes/mono/scalable/actions/saveall.svgzbin0 -> 2185 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scale.svgzbin0 -> 1624 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scaleorig.svgzbin0 -> 2908 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scaletoheight.svgzbin0 -> 2152 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scaletowidth.svgzbin0 -> 2140 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scaling.svgzbin0 -> 1848 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scheme_acoustic.svgzbin0 -> 2426 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scheme_advanced_powersave.svgzbin0 -> 3603 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scheme_power.svgzbin0 -> 1947 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scheme_powersave.svgzbin0 -> 2061 bytes
-rw-r--r--IconThemes/mono/scalable/actions/scheme_presentation.svgzbin0 -> 1963 bytes
-rw-r--r--IconThemes/mono/scalable/actions/search.svgzbin0 -> 1918 bytes
-rw-r--r--IconThemes/mono/scalable/actions/search2msgstr.svgzbin0 -> 2405 bytes
-rw-r--r--IconThemes/mono/scalable/actions/segment.svgzbin0 -> 1683 bytes
-rw-r--r--IconThemes/mono/scalable/actions/segment_midpoint.svgzbin0 -> 1876 bytes
-rw-r--r--IconThemes/mono/scalable/actions/segmentaxis.svgzbin0 -> 1775 bytes
-rw-r--r--IconThemes/mono/scalable/actions/select.svgzbin0 -> 1368 bytes
-rw-r--r--IconThemes/mono/scalable/actions/select_item.svgzbin0 -> 2900 bytes
-rw-r--r--IconThemes/mono/scalable/actions/selectcircle.svgzbin0 -> 1376 bytes
-rw-r--r--IconThemes/mono/scalable/actions/selectrect.svgzbin0 -> 1522 bytes
-rw-r--r--IconThemes/mono/scalable/actions/send_backward.svgzbin0 -> 1643 bytes
-rw-r--r--IconThemes/mono/scalable/actions/send_stencil_to_back.svgzbin0 -> 1650 bytes
-rw-r--r--IconThemes/mono/scalable/actions/series.svgzbin0 -> 3894 bytes
-rw-r--r--IconThemes/mono/scalable/actions/server.svgzbin0 -> 1644 bytes
-rw-r--r--IconThemes/mono/scalable/actions/services.svgzbin0 -> 2108 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadow.svgzbin0 -> 1455 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadowB.svgzbin0 -> 1433 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadowL.svgzbin0 -> 1431 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadowLB.svgzbin0 -> 1456 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadowLU.svgzbin0 -> 1460 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadowR.svgzbin0 -> 1428 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadowRB.svgzbin0 -> 1457 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadowRU.svgzbin0 -> 1457 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shadowU.svgzbin0 -> 1434 bytes
-rw-r--r--IconThemes/mono/scalable/actions/share.svgzbin0 -> 2750 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shear.svgzbin0 -> 1581 bytes
-rw-r--r--IconThemes/mono/scalable/actions/show_offliners.svgzbin0 -> 1962 bytes
-rw-r--r--IconThemes/mono/scalable/actions/show_table_column.svgzbin0 -> 2951 bytes
-rw-r--r--IconThemes/mono/scalable/actions/show_table_row.svgzbin0 -> 2955 bytes
-rw-r--r--IconThemes/mono/scalable/actions/showmenu.svgzbin0 -> 3438 bytes
-rw-r--r--IconThemes/mono/scalable/actions/shuffle.svgzbin0 -> 3921 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sidebar.svgzbin0 -> 1696 bytes
-rw-r--r--IconThemes/mono/scalable/actions/signalslot.svgzbin0 -> 1446 bytes
-rw-r--r--IconThemes/mono/scalable/actions/signature.svgzbin0 -> 3445 bytes
-rw-r--r--IconThemes/mono/scalable/actions/similitude.svgzbin0 -> 1930 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sizer.svgzbin0 -> 1591 bytes
-rw-r--r--IconThemes/mono/scalable/actions/slide.svgzbin0 -> 1874 bytes
-rw-r--r--IconThemes/mono/scalable/actions/slider.svgzbin0 -> 1731 bytes
-rw-r--r--IconThemes/mono/scalable/actions/slideshow.svgzbin0 -> 2201 bytes
-rw-r--r--IconThemes/mono/scalable/actions/slope.svgzbin0 -> 1394 bytes
-rw-r--r--IconThemes/mono/scalable/actions/smallcal.svgzbin0 -> 2264 bytes
-rw-r--r--IconThemes/mono/scalable/actions/smallclock.svgzbin0 -> 1636 bytes
-rw-r--r--IconThemes/mono/scalable/actions/smallthumbnails.svgzbin0 -> 2065 bytes
-rw-r--r--IconThemes/mono/scalable/actions/solarizetool.svgzbin0 -> 1931 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sort_az.svgzbin0 -> 4354 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sort_decrease.svgzbin0 -> 4187 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sort_incr.svgzbin0 -> 4356 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sort_za.svgzbin0 -> 4181 bytes
-rw-r--r--IconThemes/mono/scalable/actions/soulseekdown.svgzbin0 -> 1549 bytes
-rw-r--r--IconThemes/mono/scalable/actions/soulseekup.svgzbin0 -> 1548 bytes
-rw-r--r--IconThemes/mono/scalable/actions/speak.svgzbin0 -> 1704 bytes
-rw-r--r--IconThemes/mono/scalable/actions/speaker.svgzbin0 -> 1706 bytes
-rw-r--r--IconThemes/mono/scalable/actions/special_paste.svgzbin0 -> 2244 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spectrum.svgzbin0 -> 2536 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spellcheck.svgzbin0 -> 4170 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spellcheck_actual.svgzbin0 -> 4177 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spellcheck_from_cursor.svgzbin0 -> 4071 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spellcheck_selected.svgzbin0 -> 4143 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spin.svgzbin0 -> 2859 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spnewgame.svgzbin0 -> 2156 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spnewround.svgzbin0 -> 1874 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sppausegame.svgzbin0 -> 1712 bytes
-rw-r--r--IconThemes/mono/scalable/actions/spring.svgzbin0 -> 2845 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sqrt.svgzbin0 -> 3202 bytes
-rw-r--r--IconThemes/mono/scalable/actions/square.svgzbin0 -> 1555 bytes
-rw-r--r--IconThemes/mono/scalable/actions/stamp.svgzbin0 -> 1947 bytes
-rw-r--r--IconThemes/mono/scalable/actions/stand_by.svgzbin0 -> 4260 bytes
-rw-r--r--IconThemes/mono/scalable/actions/start.svgzbin0 -> 1711 bytes
-rw-r--r--IconThemes/mono/scalable/actions/state_data.svgzbin0 -> 2107 bytes
-rw-r--r--IconThemes/mono/scalable/actions/state_edit.svgzbin0 -> 2623 bytes
-rw-r--r--IconThemes/mono/scalable/actions/state_sql.svgzbin0 -> 4471 bytes
-rw-r--r--IconThemes/mono/scalable/actions/state_text.svgzbin0 -> 1787 bytes
-rw-r--r--IconThemes/mono/scalable/actions/statematter.svgzbin0 -> 2185 bytes
-rw-r--r--IconThemes/mono/scalable/actions/statistics.svgzbin0 -> 1846 bytes
-rw-r--r--IconThemes/mono/scalable/actions/step.svgzbin0 -> 1704 bytes
-rw-r--r--IconThemes/mono/scalable/actions/stop.svgzbin0 -> 2569 bytes
-rw-r--r--IconThemes/mono/scalable/actions/strempty.svgzbin0 -> 1658 bytes
-rw-r--r--IconThemes/mono/scalable/actions/stretch.svgzbin0 -> 1825 bytes
-rw-r--r--IconThemes/mono/scalable/actions/strikethrough.svgzbin0 -> 2243 bytes
-rw-r--r--IconThemes/mono/scalable/actions/strokedocker.svgzbin0 -> 1560 bytes
-rw-r--r--IconThemes/mono/scalable/actions/styledocker.svgzbin0 -> 2018 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sub.svgzbin0 -> 2194 bytes
-rw-r--r--IconThemes/mono/scalable/actions/submit.svgzbin0 -> 1428 bytes
-rw-r--r--IconThemes/mono/scalable/actions/sum.svgzbin0 -> 1303 bytes
-rw-r--r--IconThemes/mono/scalable/actions/super.svgzbin0 -> 2188 bytes
-rw-r--r--IconThemes/mono/scalable/actions/superimpose.svgzbin0 -> 1556 bytes
-rw-r--r--IconThemes/mono/scalable/actions/suspend.svgzbin0 -> 1249 bytes
-rw-r--r--IconThemes/mono/scalable/actions/suspend_to_disk.svgzbin0 -> 1126 bytes
-rw-r--r--IconThemes/mono/scalable/actions/suspend_to_ram.svgzbin0 -> 1249 bytes
-rw-r--r--IconThemes/mono/scalable/actions/svn_add.svgzbin0 -> 1850 bytes
-rw-r--r--IconThemes/mono/scalable/actions/svn_branch.svgzbin0 -> 2124 bytes
-rw-r--r--IconThemes/mono/scalable/actions/svn_merge.svgzbin0 -> 1380 bytes
-rw-r--r--IconThemes/mono/scalable/actions/svn_remove.svgzbin0 -> 1648 bytes
-rw-r--r--IconThemes/mono/scalable/actions/svn_status.svgzbin0 -> 1817 bytes
-rw-r--r--IconThemes/mono/scalable/actions/svn_switch.svgzbin0 -> 1395 bytes
-rw-r--r--IconThemes/mono/scalable/actions/switchuser.svgzbin0 -> 1719 bytes
-rw-r--r--IconThemes/mono/scalable/actions/syntax.svgzbin0 -> 1978 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_breakoff.svgzbin0 -> 1686 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_duplicate.svgzbin0 -> 1441 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_first.svgzbin0 -> 1456 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_last.svgzbin0 -> 1479 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_left.svgzbin0 -> 1296 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_new.svgzbin0 -> 1850 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_new_raised.svgzbin0 -> 2025 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_remove.svgzbin0 -> 1673 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tab_right.svgzbin0 -> 1290 bytes
-rw-r--r--IconThemes/mono/scalable/actions/table.svgzbin0 -> 1745 bytes
-rw-r--r--IconThemes/mono/scalable/actions/table_newobj.svgzbin0 -> 1752 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tables.svgzbin0 -> 1746 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tabwidget.svgzbin0 -> 1766 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag-folder.svgzbin0 -> 2466 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_a.svgzbin0 -> 1743 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_bold.svgzbin0 -> 2166 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_br.svgzbin0 -> 1753 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_i.svgzbin0 -> 2178 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_image.svgzbin0 -> 2352 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_li.svgzbin0 -> 3814 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_mail.svgzbin0 -> 1574 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_ol.svgzbin0 -> 3814 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_sub.svgzbin0 -> 2194 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_sup.svgzbin0 -> 2188 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_u.svgzbin0 -> 2255 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_ul.svgzbin0 -> 2335 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tag_ulink.svgzbin0 -> 1921 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tangent.svgzbin0 -> 1487 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tea_anim1.svgzbin0 -> 3132 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tea_anim2.svgzbin0 -> 3972 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tea_not_ready.svgzbin0 -> 2790 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_a4.svgzbin0 -> 1610 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_balancesheet.svgzbin0 -> 1789 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_barchart.svgzbin0 -> 1954 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_basicworkflow.svgzbin0 -> 1778 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_bmi.svgzbin0 -> 1785 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_businesscards10.svgzbin0 -> 1555 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_businesscards16.svgzbin0 -> 1593 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_cmyk_empty.svgzbin0 -> 4569 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_creditcardtracker.svgzbin0 -> 3718 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_empty.svgzbin0 -> 1426 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_emptylandscape.svgzbin0 -> 1403 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_emptyportrait.svgzbin0 -> 1420 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_envelopec6.svgzbin0 -> 1487 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_envelopedl.svgzbin0 -> 1500 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_expensereport.svgzbin0 -> 2795 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_fax.svgzbin0 -> 1876 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_gray_empty.svgzbin0 -> 1545 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_invoice.svgzbin0 -> 1796 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_iso.svgzbin0 -> 1627 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_letter.svgzbin0 -> 1639 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_memo.svgzbin0 -> 2127 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_menuplan.svgzbin0 -> 2191 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_onecolumnlandscape.svgzbin0 -> 1804 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_onecolumnportrait.svgzbin0 -> 1818 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_packingslip.svgzbin0 -> 2018 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_plaintext.svgzbin0 -> 1599 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_pricequotation.svgzbin0 -> 2648 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_rgb_empty.svgzbin0 -> 4417 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_simplelayout.svgzbin0 -> 1660 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_studentidcard.svgzbin0 -> 1975 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_timechart.svgzbin0 -> 1842 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_titlelandscape.svgzbin0 -> 1569 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_titleportrait.svgzbin0 -> 1583 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_twocolumnlandscape.svgzbin0 -> 1877 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_twocolumnportrait.svgzbin0 -> 1898 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_twocolumns.svgzbin0 -> 1705 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_us.svgzbin0 -> 1628 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_vacationchecklist.svgzbin0 -> 2280 bytes
-rw-r--r--IconThemes/mono/scalable/actions/template_worksheet.svgzbin0 -> 1446 bytes
-rw-r--r--IconThemes/mono/scalable/actions/test.svgzbin0 -> 2715 bytes
-rw-r--r--IconThemes/mono/scalable/actions/test_it.svgzbin0 -> 3064 bytes
-rw-r--r--IconThemes/mono/scalable/actions/testcollinear.svgzbin0 -> 2766 bytes
-rw-r--r--IconThemes/mono/scalable/actions/testcontains.svgzbin0 -> 2830 bytes
-rw-r--r--IconThemes/mono/scalable/actions/testdistance.svgzbin0 -> 3425 bytes
-rw-r--r--IconThemes/mono/scalable/actions/testorthogonal.svgzbin0 -> 2652 bytes
-rw-r--r--IconThemes/mono/scalable/actions/testparallel.svgzbin0 -> 2492 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text.svgzbin0 -> 3725 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_block.svgzbin0 -> 1810 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_bold.svgzbin0 -> 2171 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_bottom.svgzbin0 -> 1688 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_center.svgzbin0 -> 1780 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_italic.svgzbin0 -> 2183 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_left.svgzbin0 -> 1767 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_right.svgzbin0 -> 1641 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_strike.svgzbin0 -> 2241 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_sub.svgzbin0 -> 2199 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_super.svgzbin0 -> 2193 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_top.svgzbin0 -> 1696 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_under.svgzbin0 -> 2256 bytes
-rw-r--r--IconThemes/mono/scalable/actions/text_underline.svgzbin0 -> 2260 bytes
-rw-r--r--IconThemes/mono/scalable/actions/textcolor.svgzbin0 -> 2623 bytes
-rw-r--r--IconThemes/mono/scalable/actions/textedit.svgzbin0 -> 2351 bytes
-rw-r--r--IconThemes/mono/scalable/actions/textwaterfall.svgzbin0 -> 1561 bytes
-rw-r--r--IconThemes/mono/scalable/actions/thumbnail.svgzbin0 -> 2200 bytes
-rw-r--r--IconThemes/mono/scalable/actions/timeedit.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/timeline.svgzbin0 -> 1925 bytes
-rw-r--r--IconThemes/mono/scalable/actions/timespan.svgzbin0 -> 2438 bytes
-rw-r--r--IconThemes/mono/scalable/actions/timings.svgzbin0 -> 1685 bytes
-rw-r--r--IconThemes/mono/scalable/actions/today.svgzbin0 -> 3360 bytes
-rw-r--r--IconThemes/mono/scalable/actions/todo.svgzbin0 -> 2389 bytes
-rw-r--r--IconThemes/mono/scalable/actions/toggle_log.svgzbin0 -> 2762 bytes
-rw-r--r--IconThemes/mono/scalable/actions/togglefuzzy.svgzbin0 -> 3632 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_brush.svgzbin0 -> 2121 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_brush_selection.svgzbin0 -> 1892 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_clipboard.svgzbin0 -> 1729 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_color_picker.svgzbin0 -> 1690 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_color_washer.svgzbin0 -> 1680 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_curve.svgzbin0 -> 2105 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_delay.svgzbin0 -> 2704 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_delete.svgzbin0 -> 1778 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_disconnect.svgzbin0 -> 2079 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_dock.svgzbin0 -> 1546 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_drop_target.svgzbin0 -> 1662 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_ellipse.svgzbin0 -> 1401 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_elliptical_selection.svgzbin0 -> 1369 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_eraser.svgzbin0 -> 1433 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_eraser_selection.svgzbin0 -> 1684 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_expert.svgzbin0 -> 2099 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_flood_fill.svgzbin0 -> 2527 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_free_form_selection.svgzbin0 -> 1468 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_freehand.svgzbin0 -> 1823 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_line.svgzbin0 -> 1367 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_logwindow.svgzbin0 -> 3464 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_normal.svgzbin0 -> 2013 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_offline_mode_off.svgzbin0 -> 1864 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_offline_mode_on.svgzbin0 -> 2596 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_pan.svgzbin0 -> 1924 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_paste.svgzbin0 -> 2241 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_pause.svgzbin0 -> 1711 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_pen.svgzbin0 -> 2312 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_picker_selection.svgzbin0 -> 1562 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_polygon.svgzbin0 -> 1464 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_polygonal_selection.svgzbin0 -> 1439 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_polyline.svgzbin0 -> 2525 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_preferences.svgzbin0 -> 2041 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_queue.svgzbin0 -> 2627 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_rect_selection.svgzbin0 -> 1492 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_rectangle.svgzbin0 -> 1524 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_restart.svgzbin0 -> 1935 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_resume.svgzbin0 -> 1551 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_rounded_rectangle.svgzbin0 -> 1532 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_shutdown.svgzbin0 -> 2293 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_spraycan.svgzbin0 -> 3451 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_star.svgzbin0 -> 1483 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_text.svgzbin0 -> 2938 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_timer.svgzbin0 -> 1636 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_uselastdir.svgzbin0 -> 2173 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tool_wizard_selection.svgzbin0 -> 1970 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tooltip.svgzbin0 -> 2348 bytes
-rw-r--r--IconThemes/mono/scalable/actions/top.svgzbin0 -> 1541 bytes
-rw-r--r--IconThemes/mono/scalable/actions/transaction_export.svgzbin0 -> 2681 bytes
-rw-r--r--IconThemes/mono/scalable/actions/transaction_find.svgzbin0 -> 1928 bytes
-rw-r--r--IconThemes/mono/scalable/actions/transaction_import.svgzbin0 -> 2362 bytes
-rw-r--r--IconThemes/mono/scalable/actions/transform.svgzbin0 -> 1576 bytes
-rw-r--r--IconThemes/mono/scalable/actions/translate.svgzbin0 -> 2880 bytes
-rw-r--r--IconThemes/mono/scalable/actions/translation.svgzbin0 -> 1801 bytes
-rw-r--r--IconThemes/mono/scalable/actions/transsearch.svgzbin0 -> 1923 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tree_arrange.svgzbin0 -> 1449 bytes
-rw-r--r--IconThemes/mono/scalable/actions/triangle.svgzbin0 -> 1739 bytes
-rw-r--r--IconThemes/mono/scalable/actions/tux.svgzbin0 -> 2248 bytes
-rw-r--r--IconThemes/mono/scalable/actions/under.svgzbin0 -> 3154 bytes
-rw-r--r--IconThemes/mono/scalable/actions/underline.svgzbin0 -> 2255 bytes
-rw-r--r--IconThemes/mono/scalable/actions/undo.svgzbin0 -> 1469 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ungroup.svgzbin0 -> 1476 bytes
-rw-r--r--IconThemes/mono/scalable/actions/ungroup_stencils.svgzbin0 -> 1485 bytes
-rw-r--r--IconThemes/mono/scalable/actions/unindent.svgzbin0 -> 2018 bytes
-rw-r--r--IconThemes/mono/scalable/actions/unlinked.svgzbin0 -> 1645 bytes
-rw-r--r--IconThemes/mono/scalable/actions/unlock.svgzbin0 -> 1719 bytes
-rw-r--r--IconThemes/mono/scalable/actions/unlocked.svgzbin0 -> 1721 bytes
-rw-r--r--IconThemes/mono/scalable/actions/unmarkasblank.svgzbin0 -> 1727 bytes
-rw-r--r--IconThemes/mono/scalable/actions/unsortedList.svgzbin0 -> 2335 bytes
-rw-r--r--IconThemes/mono/scalable/actions/up.svgzbin0 -> 1540 bytes
-rw-r--r--IconThemes/mono/scalable/actions/urlrequest.svgzbin0 -> 1920 bytes
-rw-r--r--IconThemes/mono/scalable/actions/validators.svgzbin0 -> 1982 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vcs_add.svgzbin0 -> 1850 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vcs_commit.svgzbin0 -> 1380 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vcs_diff.svgzbin0 -> 1395 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vcs_remove.svgzbin0 -> 1648 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vcs_status.svgzbin0 -> 1817 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vcs_update.svgzbin0 -> 1952 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vector.svgzbin0 -> 1873 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vectordifference.svgzbin0 -> 2348 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vectorsum.svgzbin0 -> 2144 bytes
-rw-r--r--IconThemes/mono/scalable/actions/vertical_text.svgzbin0 -> 4439 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_bottom.svgzbin0 -> 2148 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_choose.svgzbin0 -> 3142 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_detailed.svgzbin0 -> 2380 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_grid.svgzbin0 -> 1628 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_guides.svgzbin0 -> 1471 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_icon.svgzbin0 -> 2323 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_left_right.svgzbin0 -> 2134 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_margins.svgzbin0 -> 1740 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_multicolumn.svgzbin0 -> 2303 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_orientation.svgzbin0 -> 2183 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_pageborder.svgzbin0 -> 1646 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_remove.svgzbin0 -> 2016 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_right.svgzbin0 -> 2145 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_ruler.svgzbin0 -> 1990 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_sidetree.svgzbin0 -> 2410 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_split.svgzbin0 -> 2153 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_text.svgzbin0 -> 2237 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_top_bottom.svgzbin0 -> 2080 bytes
-rw-r--r--IconThemes/mono/scalable/actions/view_tree.svgzbin0 -> 2357 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag+.svgzbin0 -> 2387 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag-.svgzbin0 -> 2199 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag.svgzbin0 -> 1954 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag1.svgzbin0 -> 2907 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_bis+.svgzbin0 -> 2391 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_bis-.svgzbin0 -> 2203 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_enlarge.svgzbin0 -> 2824 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_factor.svgzbin0 -> 2983 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_full.svgzbin0 -> 1750 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_h.svgzbin0 -> 2148 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_lock.svgzbin0 -> 2487 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_no.svgzbin0 -> 2909 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_shrink.svgzbin0 -> 3297 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmag_w.svgzbin0 -> 2137 bytes
-rw-r--r--IconThemes/mono/scalable/actions/viewmagfit.svgzbin0 -> 1748 bytes
-rw-r--r--IconThemes/mono/scalable/actions/visible.svgzbin0 -> 2992 bytes
-rw-r--r--IconThemes/mono/scalable/actions/visualizations.svgzbin0 -> 1910 bytes
-rw-r--r--IconThemes/mono/scalable/actions/voicecall.svgzbin0 -> 1980 bytes
-rw-r--r--IconThemes/mono/scalable/actions/volume.svgzbin0 -> 1456 bytes
-rw-r--r--IconThemes/mono/scalable/actions/w.svgzbin0 -> 2297 bytes
-rw-r--r--IconThemes/mono/scalable/actions/wallet_closed.svgzbin0 -> 3402 bytes
-rw-r--r--IconThemes/mono/scalable/actions/wallet_open.svgzbin0 -> 9774 bytes
-rw-r--r--IconThemes/mono/scalable/actions/warning.svgzbin0 -> 2092 bytes
-rw-r--r--IconThemes/mono/scalable/actions/webarchiver.svgzbin0 -> 3100 bytes
-rw-r--r--IconThemes/mono/scalable/actions/webcamreceive.svgzbin0 -> 1310 bytes
-rw-r--r--IconThemes/mono/scalable/actions/webcamsend.svgzbin0 -> 1314 bytes
-rw-r--r--IconThemes/mono/scalable/actions/webexport.svgzbin0 -> 2991 bytes
-rw-r--r--IconThemes/mono/scalable/actions/webpres.svgzbin0 -> 2567 bytes
-rw-r--r--IconThemes/mono/scalable/actions/whatsnext.svgzbin0 -> 2305 bytes
-rw-r--r--IconThemes/mono/scalable/actions/widgetstack.svgzbin0 -> 1578 bytes
-rw-r--r--IconThemes/mono/scalable/actions/wiki.svgzbin0 -> 2297 bytes
-rw-r--r--IconThemes/mono/scalable/actions/window.svgzbin0 -> 1098 bytes
-rw-r--r--IconThemes/mono/scalable/actions/window_duplicate.svgzbin0 -> 2420 bytes
-rw-r--r--IconThemes/mono/scalable/actions/window_fullscreen.svgzbin0 -> 2156 bytes
-rw-r--r--IconThemes/mono/scalable/actions/window_new.svgzbin0 -> 2521 bytes
-rw-r--r--IconThemes/mono/scalable/actions/window_nofullscreen.svgzbin0 -> 2184 bytes
-rw-r--r--IconThemes/mono/scalable/actions/window_suppressed.svgzbin0 -> 2151 bytes
-rw-r--r--IconThemes/mono/scalable/actions/wired.svgzbin0 -> 2348 bytes
-rw-r--r--IconThemes/mono/scalable/actions/wireless.svgzbin0 -> 2122 bytes
-rw-r--r--IconThemes/mono/scalable/actions/wizard.svgzbin0 -> 2250 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xdays.svgzbin0 -> 2465 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_break.svgzbin0 -> 1431 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_data.svgzbin0 -> 3537 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_delete.svgzbin0 -> 1781 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_enable.svgzbin0 -> 3047 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_output.svgzbin0 -> 1820 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_refresh.svgzbin0 -> 1937 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_source.svgzbin0 -> 3894 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_stepdown.svgzbin0 -> 1722 bytes
-rw-r--r--IconThemes/mono/scalable/actions/xsldbg_stepup.svgzbin0 -> 1750 bytes
-rw-r--r--IconThemes/mono/scalable/actions/yahoo_away.svgzbin0 -> 1634 bytes
-rw-r--r--IconThemes/mono/scalable/actions/yahoo_mobile.svgzbin0 -> 3297 bytes
-rw-r--r--IconThemes/mono/scalable/actions/yahoo_protocol.svgzbin0 -> 3013 bytes
-rw-r--r--IconThemes/mono/scalable/actions/yellow_ball.svgzbin0 -> 1356 bytes
-rw-r--r--IconThemes/mono/scalable/actions/yellowinfo.svgzbin0 -> 1960 bytes
-rw-r--r--IconThemes/mono/scalable/actions/yesno.svgzbin0 -> 3175 bytes
-rw-r--r--IconThemes/mono/scalable/actions/zoom_disabled.svgzbin0 -> 2145 bytes
-rw-r--r--IconThemes/mono/scalable/actions/zoom_enabled.svgzbin0 -> 1959 bytes
-rw-r--r--IconThemes/mono/scalable/apps/001_star_butterfly.svgzbin0 -> 2865 bytes
-rw-r--r--IconThemes/mono/scalable/apps/002_text_document.svgzbin0 -> 2164 bytes
-rw-r--r--IconThemes/mono/scalable/apps/005_spreadsheet_document.svgzbin0 -> 3178 bytes
-rw-r--r--IconThemes/mono/scalable/apps/006_drawing_document.svgzbin0 -> 2453 bytes
-rw-r--r--IconThemes/mono/scalable/apps/008_presentation_document.svgzbin0 -> 2777 bytes
-rw-r--r--IconThemes/mono/scalable/apps/009_presentation_document.svgzbin0 -> 2777 bytes
-rw-r--r--IconThemes/mono/scalable/apps/010_presentation_compressed.svgzbin0 -> 2742 bytes
-rw-r--r--IconThemes/mono/scalable/apps/012_html_document.svgzbin0 -> 3327 bytes
-rw-r--r--IconThemes/mono/scalable/apps/015_math_document.svgzbin0 -> 2909 bytes
-rw-r--r--IconThemes/mono/scalable/apps/016_template.svgzbin0 -> 3287 bytes
-rw-r--r--IconThemes/mono/scalable/apps/500_setup.svgzbin0 -> 2446 bytes
-rw-r--r--IconThemes/mono/scalable/apps/501_printeradmin.svgzbin0 -> 2487 bytes
-rw-r--r--IconThemes/mono/scalable/apps/CD-Rom.svgzbin0 -> 1767 bytes
-rw-r--r--IconThemes/mono/scalable/apps/FaxRecieving.svgzbin0 -> 5094 bytes
-rw-r--r--IconThemes/mono/scalable/apps/LabPlot.svgzbin0 -> 1701 bytes
-rw-r--r--IconThemes/mono/scalable/apps/YaST.svgzbin0 -> 1823 bytes
-rw-r--r--IconThemes/mono/scalable/apps/Ym.svgzbin0 -> 3001 bytes
-rw-r--r--IconThemes/mono/scalable/apps/abakus.svgzbin0 -> 2973 bytes
-rw-r--r--IconThemes/mono/scalable/apps/abiword.svgzbin0 -> 1308 bytes
-rw-r--r--IconThemes/mono/scalable/apps/access.svgzbin0 -> 2145 bytes
-rw-r--r--IconThemes/mono/scalable/apps/accessibility_section.svgzbin0 -> 2160 bytes
-rw-r--r--IconThemes/mono/scalable/apps/acroread.svgzbin0 -> 2094 bytes
-rw-r--r--IconThemes/mono/scalable/apps/addressbook.svgzbin0 -> 1924 bytes
-rw-r--r--IconThemes/mono/scalable/apps/agent.svgzbin0 -> 2637 bytes
-rw-r--r--IconThemes/mono/scalable/apps/aim.svgzbin0 -> 2164 bytes
-rw-r--r--IconThemes/mono/scalable/apps/aim_protocol.svgzbin0 -> 2173 bytes
-rw-r--r--IconThemes/mono/scalable/apps/akregator.svgzbin0 -> 4283 bytes
-rw-r--r--IconThemes/mono/scalable/apps/akregator_empty.svgzbin0 -> 1641 bytes
-rw-r--r--IconThemes/mono/scalable/apps/aktion.svgzbin0 -> 2198 bytes
-rw-r--r--IconThemes/mono/scalable/apps/alevt.svgzbin0 -> 1597 bytes
-rw-r--r--IconThemes/mono/scalable/apps/amarok.svgzbin0 -> 2337 bytes
-rw-r--r--IconThemes/mono/scalable/apps/amor.svgzbin0 -> 2796 bytes
-rw-r--r--IconThemes/mono/scalable/apps/antivirus.svgzbin0 -> 3034 bytes
-rw-r--r--IconThemes/mono/scalable/apps/apollon.svgzbin0 -> 1994 bytes
-rw-r--r--IconThemes/mono/scalable/apps/applixware.svgzbin0 -> 2140 bytes
-rw-r--r--IconThemes/mono/scalable/apps/apport.svgzbin0 -> 2092 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ark.svgzbin0 -> 2038 bytes
-rw-r--r--IconThemes/mono/scalable/apps/arts.svgzbin0 -> 2512 bytes
-rw-r--r--IconThemes/mono/scalable/apps/artsbuilder.svgzbin0 -> 2519 bytes
-rw-r--r--IconThemes/mono/scalable/apps/artscontrol.svgzbin0 -> 1799 bytes
-rw-r--r--IconThemes/mono/scalable/apps/assistant.svgzbin0 -> 1443 bytes
-rw-r--r--IconThemes/mono/scalable/apps/atlantik.svgzbin0 -> 3060 bytes
-rw-r--r--IconThemes/mono/scalable/apps/atlantikdesigner.svgzbin0 -> 3068 bytes
-rw-r--r--IconThemes/mono/scalable/apps/audacity.svgzbin0 -> 2321 bytes
-rw-r--r--IconThemes/mono/scalable/apps/background.svgzbin0 -> 2414 bytes
-rw-r--r--IconThemes/mono/scalable/apps/basket.svgzbin0 -> 4940 bytes
-rw-r--r--IconThemes/mono/scalable/apps/bell.svgzbin0 -> 2003 bytes
-rw-r--r--IconThemes/mono/scalable/apps/blender.svgzbin0 -> 2837 bytes
-rw-r--r--IconThemes/mono/scalable/apps/blinken.svgzbin0 -> 5588 bytes
-rw-r--r--IconThemes/mono/scalable/apps/bluefish.svgzbin0 -> 2879 bytes
-rw-r--r--IconThemes/mono/scalable/apps/bookcase.svgzbin0 -> 3541 bytes
-rw-r--r--IconThemes/mono/scalable/apps/browser.svgzbin0 -> 2567 bytes
-rw-r--r--IconThemes/mono/scalable/apps/bug.svgzbin0 -> 2488 bytes
-rw-r--r--IconThemes/mono/scalable/apps/bzflag.svgzbin0 -> 3753 bytes
-rw-r--r--IconThemes/mono/scalable/apps/cache.svgzbin0 -> 1911 bytes
-rw-r--r--IconThemes/mono/scalable/apps/calc.svgzbin0 -> 1796 bytes
-rw-r--r--IconThemes/mono/scalable/apps/camera.svgzbin0 -> 1939 bytes
-rw-r--r--IconThemes/mono/scalable/apps/catalogmanager.svgzbin0 -> 2903 bytes
-rw-r--r--IconThemes/mono/scalable/apps/categories.svgzbin0 -> 3558 bytes
-rw-r--r--IconThemes/mono/scalable/apps/celestia.svgzbin0 -> 2484 bytes
-rw-r--r--IconThemes/mono/scalable/apps/cervisia.svgzbin0 -> 1711 bytes
-rw-r--r--IconThemes/mono/scalable/apps/charselect.svgzbin0 -> 5240 bytes
-rw-r--r--IconThemes/mono/scalable/apps/chat_section.svgzbin0 -> 4501 bytes
-rw-r--r--IconThemes/mono/scalable/apps/civworld.svgzbin0 -> 2348 bytes
-rw-r--r--IconThemes/mono/scalable/apps/clanbomber.svgzbin0 -> 2454 bytes
-rw-r--r--IconThemes/mono/scalable/apps/clock.svgzbin0 -> 1708 bytes
-rw-r--r--IconThemes/mono/scalable/apps/codeine.svgzbin0 -> 2845 bytes
-rw-r--r--IconThemes/mono/scalable/apps/colorpicker.svgzbin0 -> 1684 bytes
-rw-r--r--IconThemes/mono/scalable/apps/colors.svgzbin0 -> 2176 bytes
-rw-r--r--IconThemes/mono/scalable/apps/computer.svgzbin0 -> 1572 bytes
-rw-r--r--IconThemes/mono/scalable/apps/cookie.svgzbin0 -> 3287 bytes
-rw-r--r--IconThemes/mono/scalable/apps/core.svgzbin0 -> 2448 bytes
-rw-r--r--IconThemes/mono/scalable/apps/cpufreq_applet.svgzbin0 -> 4254 bytes
-rw-r--r--IconThemes/mono/scalable/apps/daemon.svgzbin0 -> 1443 bytes
-rw-r--r--IconThemes/mono/scalable/apps/daemons.svgzbin0 -> 1443 bytes
-rw-r--r--IconThemes/mono/scalable/apps/date.svgzbin0 -> 3359 bytes
-rw-r--r--IconThemes/mono/scalable/apps/dcgui-qt.svgzbin0 -> 3290 bytes
-rw-r--r--IconThemes/mono/scalable/apps/default-applications-capplet.svgzbin0 -> 2019 bytes
-rw-r--r--IconThemes/mono/scalable/apps/designer.svgzbin0 -> 2556 bytes
-rw-r--r--IconThemes/mono/scalable/apps/dia.svgzbin0 -> 2115 bytes
-rw-r--r--IconThemes/mono/scalable/apps/dia_gnome_icon.svgzbin0 -> 2126 bytes
-rw-r--r--IconThemes/mono/scalable/apps/digikam.svgzbin0 -> 1940 bytes
-rw-r--r--IconThemes/mono/scalable/apps/digikamcameraclient.svgzbin0 -> 1952 bytes
-rw-r--r--IconThemes/mono/scalable/apps/digikamimageplugins.svgzbin0 -> 1952 bytes
-rw-r--r--IconThemes/mono/scalable/apps/display.svgzbin0 -> 1793 bytes
-rw-r--r--IconThemes/mono/scalable/apps/displayconfig.svgzbin0 -> 1710 bytes
-rw-r--r--IconThemes/mono/scalable/apps/dlgedit.svgzbin0 -> 4190 bytes
-rw-r--r--IconThemes/mono/scalable/apps/dopewars-pill.svgzbin0 -> 1756 bytes
-rw-r--r--IconThemes/mono/scalable/apps/download_manager.svgzbin0 -> 2991 bytes
-rw-r--r--IconThemes/mono/scalable/apps/dsl.svgzbin0 -> 2999 bytes
-rw-r--r--IconThemes/mono/scalable/apps/eclipse.svgzbin0 -> 2495 bytes
-rw-r--r--IconThemes/mono/scalable/apps/edu_languages.svgzbin0 -> 4502 bytes
-rw-r--r--IconThemes/mono/scalable/apps/edu_mathematics.svgzbin0 -> 3219 bytes
-rw-r--r--IconThemes/mono/scalable/apps/edu_miscellaneous.svgzbin0 -> 2984 bytes
-rw-r--r--IconThemes/mono/scalable/apps/edu_science.svgzbin0 -> 2243 bytes
-rw-r--r--IconThemes/mono/scalable/apps/emacs.svgzbin0 -> 2814 bytes
-rw-r--r--IconThemes/mono/scalable/apps/email.svgzbin0 -> 1571 bytes
-rw-r--r--IconThemes/mono/scalable/apps/energy.svgzbin0 -> 2237 bytes
-rw-r--r--IconThemes/mono/scalable/apps/energy_star.svgzbin0 -> 2111 bytes
-rw-r--r--IconThemes/mono/scalable/apps/enhanced_browsing.svgzbin0 -> 3103 bytes
-rw-r--r--IconThemes/mono/scalable/apps/enigma.svgzbin0 -> 1292 bytes
-rw-r--r--IconThemes/mono/scalable/apps/eog.svgzbin0 -> 2984 bytes
-rw-r--r--IconThemes/mono/scalable/apps/error.svgzbin0 -> 1674 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ethereal.svgzbin0 -> 1436 bytes
-rw-r--r--IconThemes/mono/scalable/apps/eventwatcher.svgzbin0 -> 1808 bytes
-rw-r--r--IconThemes/mono/scalable/apps/evolution.svgzbin0 -> 1376 bytes
-rw-r--r--IconThemes/mono/scalable/apps/exec_wine.svgzbin0 -> 3236 bytes
-rw-r--r--IconThemes/mono/scalable/apps/exit.svgzbin0 -> 2284 bytes
-rw-r--r--IconThemes/mono/scalable/apps/falconseye.svgzbin0 -> 2350 bytes
-rw-r--r--IconThemes/mono/scalable/apps/fax.svgzbin0 -> 5085 bytes
-rw-r--r--IconThemes/mono/scalable/apps/fifteenpieces.svgzbin0 -> 1745 bytes
-rw-r--r--IconThemes/mono/scalable/apps/filelight.svgzbin0 -> 2139 bytes
-rw-r--r--IconThemes/mono/scalable/apps/fileshare.svgzbin0 -> 2754 bytes
-rw-r--r--IconThemes/mono/scalable/apps/filetypes.svgzbin0 -> 2848 bytes
-rw-r--r--IconThemes/mono/scalable/apps/finances_section.svgzbin0 -> 2706 bytes
-rw-r--r--IconThemes/mono/scalable/apps/firefox.svgzbin0 -> 5299 bytes
-rw-r--r--IconThemes/mono/scalable/apps/flashkard.svgzbin0 -> 3004 bytes
-rw-r--r--IconThemes/mono/scalable/apps/fonts.svgzbin0 -> 3916 bytes
-rw-r--r--IconThemes/mono/scalable/apps/fsview.svgzbin0 -> 1958 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gabber.svgzbin0 -> 3745 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gaim.svgzbin0 -> 2462 bytes
-rw-r--r--IconThemes/mono/scalable/apps/galeon.svgzbin0 -> 2566 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gfloppy.svgzbin0 -> 1706 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gimp.svgzbin0 -> 3093 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gkrellm.svgzbin0 -> 3337 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gksu.svgzbin0 -> 2085 bytes
-rw-r--r--IconThemes/mono/scalable/apps/glade.svgzbin0 -> 2565 bytes
-rw-r--r--IconThemes/mono/scalable/apps/globe.svgzbin0 -> 2565 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome-about-logo.svgzbin0 -> 2515 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome-error.svgzbin0 -> 1680 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome-starthere.svgzbin0 -> 3185 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome-terminal.svgzbin0 -> 1606 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome-warning.svgzbin0 -> 2098 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome.svgzbin0 -> 2504 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome2.svgzbin0 -> 2505 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome_apps.svgzbin0 -> 2509 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome_info.svgzbin0 -> 1817 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnome_question.svgzbin0 -> 2536 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnomemeeting.svgzbin0 -> 2172 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnucash.svgzbin0 -> 7548 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnumeric.svgzbin0 -> 4406 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gnutella.svgzbin0 -> 4008 bytes
-rw-r--r--IconThemes/mono/scalable/apps/go.svgzbin0 -> 2561 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gpg.svgzbin0 -> 1773 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gpgsm.svgzbin0 -> 1775 bytes
-rw-r--r--IconThemes/mono/scalable/apps/groupwise_protocol.svgzbin0 -> 2132 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gsnes9x-icon.svgzbin0 -> 6248 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gtk_camera.svgzbin0 -> 1943 bytes
-rw-r--r--IconThemes/mono/scalable/apps/guarddog.svgzbin0 -> 3038 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gv.svgzbin0 -> 3253 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gvdirpart.svgzbin0 -> 2194 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gvim.svgzbin0 -> 5364 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gwenview.svgzbin0 -> 3161 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gxmame.svgzbin0 -> 2838 bytes
-rw-r--r--IconThemes/mono/scalable/apps/gxmessage.svgzbin0 -> 1539 bytes
-rw-r--r--IconThemes/mono/scalable/apps/harddrive.svgzbin0 -> 1470 bytes
-rw-r--r--IconThemes/mono/scalable/apps/hardware.svgzbin0 -> 3050 bytes
-rw-r--r--IconThemes/mono/scalable/apps/hardware_info.svgzbin0 -> 3312 bytes
-rw-r--r--IconThemes/mono/scalable/apps/hd.svgzbin0 -> 1463 bytes
-rw-r--r--IconThemes/mono/scalable/apps/help.svgzbin0 -> 5121 bytes
-rw-r--r--IconThemes/mono/scalable/apps/help_index.svgzbin0 -> 3768 bytes
-rw-r--r--IconThemes/mono/scalable/apps/highlight.svgzbin0 -> 3978 bytes
-rw-r--r--IconThemes/mono/scalable/apps/home.svgzbin0 -> 1899 bytes
-rw-r--r--IconThemes/mono/scalable/apps/hw_unknown.svgzbin0 -> 4636 bytes
-rw-r--r--IconThemes/mono/scalable/apps/hwinfo.svgzbin0 -> 3305 bytes
-rw-r--r--IconThemes/mono/scalable/apps/icewm.svgzbin0 -> 2554 bytes
-rw-r--r--IconThemes/mono/scalable/apps/icons.svgzbin0 -> 2943 bytes
-rw-r--r--IconThemes/mono/scalable/apps/iconthemes.svgzbin0 -> 2948 bytes
-rw-r--r--IconThemes/mono/scalable/apps/icq_protocol.svgzbin0 -> 3030 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ieee1394.svgzbin0 -> 2835 bytes
-rw-r--r--IconThemes/mono/scalable/apps/im-aim.svgzbin0 -> 2167 bytes
-rw-r--r--IconThemes/mono/scalable/apps/im-icq.svgzbin0 -> 3024 bytes
-rw-r--r--IconThemes/mono/scalable/apps/im-jabber.svgzbin0 -> 3748 bytes
-rw-r--r--IconThemes/mono/scalable/apps/im-msn.svgzbin0 -> 2289 bytes
-rw-r--r--IconThemes/mono/scalable/apps/im-yahoo.svgzbin0 -> 3007 bytes
-rw-r--r--IconThemes/mono/scalable/apps/imagegallery.svgzbin0 -> 2226 bytes
-rw-r--r--IconThemes/mono/scalable/apps/inetd.svgzbin0 -> 1466 bytes
-rw-r--r--IconThemes/mono/scalable/apps/inkscape.svgzbin0 -> 3150 bytes
-rw-r--r--IconThemes/mono/scalable/apps/input_devices_settings.svgzbin0 -> 3277 bytes
-rw-r--r--IconThemes/mono/scalable/apps/irc_protocol.svgzbin0 -> 4455 bytes
-rw-r--r--IconThemes/mono/scalable/apps/irkick.svgzbin0 -> 2169 bytes
-rw-r--r--IconThemes/mono/scalable/apps/isdn-config.svgzbin0 -> 7285 bytes
-rw-r--r--IconThemes/mono/scalable/apps/isp-disabled.svgzbin0 -> 1545 bytes
-rw-r--r--IconThemes/mono/scalable/apps/isp.svgzbin0 -> 1638 bytes
-rw-r--r--IconThemes/mono/scalable/apps/jabber_protocol.svgzbin0 -> 3754 bytes
-rw-r--r--IconThemes/mono/scalable/apps/joystick.svgzbin0 -> 2204 bytes
-rw-r--r--IconThemes/mono/scalable/apps/juk.svgzbin0 -> 1738 bytes
-rw-r--r--IconThemes/mono/scalable/apps/k3b.svgzbin0 -> 3101 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kaboodle.svgzbin0 -> 3884 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kaddressbook.svgzbin0 -> 1925 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kaffeine-pause.svgzbin0 -> 3242 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kaffeine-play.svgzbin0 -> 3183 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kaffeine-record.svgzbin0 -> 5136 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kaffeine.svgzbin0 -> 2713 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kalarm.svgzbin0 -> 2704 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kalzium.svgzbin0 -> 3084 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kamix.svgzbin0 -> 1793 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kanagram.svgzbin0 -> 5879 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kappfinder.svgzbin0 -> 2675 bytes
-rw-r--r--IconThemes/mono/scalable/apps/karbon.svgzbin0 -> 1722 bytes
-rw-r--r--IconThemes/mono/scalable/apps/karchiver.svgzbin0 -> 2044 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kard.svgzbin0 -> 2876 bytes
-rw-r--r--IconThemes/mono/scalable/apps/karm.svgzbin0 -> 2175 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kasteroids.svgzbin0 -> 1956 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kate.svgzbin0 -> 2398 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kate2.svgzbin0 -> 2398 bytes
-rw-r--r--IconThemes/mono/scalable/apps/katomic.svgzbin0 -> 3084 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kaudiocreator.svgzbin0 -> 2094 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kazaa.svgzbin0 -> 2406 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbabel.svgzbin0 -> 2238 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbabeldict.svgzbin0 -> 2061 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbackgammon.svgzbin0 -> 2329 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbackgammon_engine.svgzbin0 -> 2369 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbatterymonitor.svgzbin0 -> 2957 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbattleship.svgzbin0 -> 2273 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbear.svgzbin0 -> 3750 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbiff.svgzbin0 -> 6348 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbinaryclock.svgzbin0 -> 2933 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kblackbox.svgzbin0 -> 1565 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbluetoothd.svgzbin0 -> 1839 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbounce.svgzbin0 -> 3202 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbruch.svgzbin0 -> 5599 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbtobexclient.svgzbin0 -> 1839 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbtserialchat.svgzbin0 -> 1839 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kbugbuster.svgzbin0 -> 3530 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcachegrind.svgzbin0 -> 2644 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcalc.svgzbin0 -> 1797 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcdlabel.svgzbin0 -> 2580 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcfgcreator.svgzbin0 -> 1923 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcharselect.svgzbin0 -> 5241 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kchart.svgzbin0 -> 1842 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmdevices.svgzbin0 -> 1842 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmdf.svgzbin0 -> 1998 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmdrkonqi.svgzbin0 -> 1895 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmfontinst.svgzbin0 -> 3922 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmkicker.svgzbin0 -> 2771 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmkwm.svgzbin0 -> 2420 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmmemory.svgzbin0 -> 2356 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmmidi.svgzbin0 -> 2381 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmopengl.svgzbin0 -> 9787 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmpartitions.svgzbin0 -> 1956 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmpci.svgzbin0 -> 3048 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmprocessor.svgzbin0 -> 4254 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmsambaconf.svgzbin0 -> 2193 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmscsi.svgzbin0 -> 1649 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmsound.svgzbin0 -> 2516 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmsystem.svgzbin0 -> 2360 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcmx.svgzbin0 -> 1742 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcolorchooser.svgzbin0 -> 1686 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcoloredit.svgzbin0 -> 2180 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kconfigure.svgzbin0 -> 7967 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcontrol.svgzbin0 -> 2034 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcpuload.svgzbin0 -> 1785 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kcron.svgzbin0 -> 2333 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdat.svgzbin0 -> 1868 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdbg.svgzbin0 -> 3524 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdeapp.svgzbin0 -> 2489 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdebluetooth.svgzbin0 -> 1839 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdenlive.svgzbin0 -> 2845 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdeprint_printer.svgzbin0 -> 2029 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdeprint_printer_class.svgzbin0 -> 2527 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdeprintfax.svgzbin0 -> 5093 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdesvn.svgzbin0 -> 1711 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdetv.svgzbin0 -> 2726 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdevassistant.svgzbin0 -> 3037 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdevdesigner.svgzbin0 -> 2698 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdevelop.svgzbin0 -> 2496 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdevelop3.svgzbin0 -> 2497 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdf.svgzbin0 -> 1996 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdict.svgzbin0 -> 2734 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdiff3.svgzbin0 -> 3572 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdisknav.svgzbin0 -> 2326 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdmconfig.svgzbin0 -> 1721 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kdvi.svgzbin0 -> 2733 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kedit.svgzbin0 -> 2585 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keditbookmarks.svgzbin0 -> 2840 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keduca.svgzbin0 -> 2784 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keep.svgzbin0 -> 1997 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kenolaba.svgzbin0 -> 1675 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kerberos-client.svgzbin0 -> 1785 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kernel.svgzbin0 -> 2262 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keurocalc.svgzbin0 -> 2013 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kexi.svgzbin0 -> 3676 bytes
-rw-r--r--IconThemes/mono/scalable/apps/key_bindings.svgzbin0 -> 5242 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keyboard-capplet.svgzbin0 -> 2459 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keyboard-shortcut.svgzbin0 -> 5247 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keyboard.svgzbin0 -> 2451 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keyboard_layout.svgzbin0 -> 2458 bytes
-rw-r--r--IconThemes/mono/scalable/apps/keyboardlayout.svgzbin0 -> 2457 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfax.svgzbin0 -> 5086 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfaxview.svgzbin0 -> 5085 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfilereplace.svgzbin0 -> 2946 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfind.svgzbin0 -> 1917 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kflog.svgzbin0 -> 1299 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfloppy.svgzbin0 -> 1706 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfm.svgzbin0 -> 1859 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfm_home.svgzbin0 -> 1903 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfocus.svgzbin0 -> 2420 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfontview.svgzbin0 -> 3920 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kformdesigner.svgzbin0 -> 2143 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kformula.svgzbin0 -> 3212 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kfouleggs.svgzbin0 -> 2615 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kftpgrabber.svgzbin0 -> 2660 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kgamma.svgzbin0 -> 1654 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kgeo.svgzbin0 -> 5002 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kgeography.svgzbin0 -> 2570 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kget.svgzbin0 -> 2979 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kggz.svgzbin0 -> 2935 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kghostview.svgzbin0 -> 3891 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kgoldrunner.svgzbin0 -> 3224 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kgpg.svgzbin0 -> 1774 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kgpg_docked.svgzbin0 -> 1781 bytes
-rw-r--r--IconThemes/mono/scalable/apps/khangman.svgzbin0 -> 3598 bytes
-rw-r--r--IconThemes/mono/scalable/apps/khelpcenter.svgzbin0 -> 5128 bytes
-rw-r--r--IconThemes/mono/scalable/apps/khexedit.svgzbin0 -> 12219 bytes
-rw-r--r--IconThemes/mono/scalable/apps/khotkeys.svgzbin0 -> 5238 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kicker.svgzbin0 -> 2768 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kiconedit.svgzbin0 -> 3555 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kid3.svgzbin0 -> 2694 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kig.svgzbin0 -> 3137 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kile.svgzbin0 -> 3559 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kimagemapeditor.svgzbin0 -> 10112 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kimdaba.svgzbin0 -> 3239 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kinternet.svgzbin0 -> 3396 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kio_uiserver.svgzbin0 -> 1709 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kiosktool.svgzbin0 -> 1750 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kipi.svgzbin0 -> 4407 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kitchensync.svgzbin0 -> 1530 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kiten.svgzbin0 -> 4106 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kivio.svgzbin0 -> 1650 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kjobviewer.svgzbin0 -> 2023 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kjots.svgzbin0 -> 2970 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kjumpingcube.svgzbin0 -> 2315 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klaptopdaemon.svgzbin0 -> 2957 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klatin.svgzbin0 -> 1993 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klettres.svgzbin0 -> 2010 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klickety.svgzbin0 -> 2523 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klines.svgzbin0 -> 2186 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klinkstatus.svgzbin0 -> 3171 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klipper.svgzbin0 -> 1722 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klipper_doc.svgzbin0 -> 1726 bytes
-rw-r--r--IconThemes/mono/scalable/apps/klpq.svgzbin0 -> 2017 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmag.svgzbin0 -> 1916 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmahjongg.svgzbin0 -> 2527 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmail.svgzbin0 -> 3148 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmailcvt.svgzbin0 -> 2348 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmaillight.svgzbin0 -> 3153 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmameleon.svgzbin0 -> 2993 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmathtool.svgzbin0 -> 3143 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmdr-editor.svgzbin0 -> 3490 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmdr_editor.svgzbin0 -> 3490 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmdr_executor.svgzbin0 -> 3201 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmenu.svgzbin0 -> 2561 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmenuedit.svgzbin0 -> 3266 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmerlin.svgzbin0 -> 2255 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmid.svgzbin0 -> 2378 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmidi.svgzbin0 -> 2379 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmines.svgzbin0 -> 3900 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmix.svgzbin0 -> 1792 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmixdocked.svgzbin0 -> 1798 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmixdocked_error.svgzbin0 -> 1674 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmixdocked_mute.svgzbin0 -> 1747 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmldonkey.svgzbin0 -> 2530 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmoon.svgzbin0 -> 2668 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmousetool.svgzbin0 -> 2072 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmouth.svgzbin0 -> 1705 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmplayer.svgzbin0 -> 2845 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmplot.svgzbin0 -> 2026 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmyfirewall.svgzbin0 -> 3041 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kmymoney2.svgzbin0 -> 2699 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knetattach.svgzbin0 -> 2851 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knetload.svgzbin0 -> 1785 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knetwalk.svgzbin0 -> 1850 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knetworkconf.svgzbin0 -> 1638 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knetworkmanager.svgzbin0 -> 1608 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knewsticker.svgzbin0 -> 3048 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knoda.svgzbin0 -> 3115 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knode.svgzbin0 -> 3042 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knode2.svgzbin0 -> 3043 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knoppix-penguin.svgzbin0 -> 2542 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knotes.svgzbin0 -> 2971 bytes
-rw-r--r--IconThemes/mono/scalable/apps/knotify.svgzbin0 -> 2014 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kodo.svgzbin0 -> 5368 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kolf.svgzbin0 -> 1444 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kolourpaint.svgzbin0 -> 2181 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kommander.svgzbin0 -> 3192 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kommando.svgzbin0 -> 2701 bytes
-rw-r--r--IconThemes/mono/scalable/apps/komparator.svgzbin0 -> 3549 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kompare.svgzbin0 -> 3549 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kompose.svgzbin0 -> 2790 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konqsidebar_mediaplayer.svgzbin0 -> 2215 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konqsidebar_news.svgzbin0 -> 3048 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konqueror.svgzbin0 -> 2984 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konquest.svgzbin0 -> 2484 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konserve.svgzbin0 -> 1978 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konsole.svgzbin0 -> 1599 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konsolekalendar.svgzbin0 -> 3349 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kontact.svgzbin0 -> 3436 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konversation.svgzbin0 -> 4455 bytes
-rw-r--r--IconThemes/mono/scalable/apps/konverter.svgzbin0 -> 2109 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kooka.svgzbin0 -> 2432 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kopete.svgzbin0 -> 4495 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kopete2.svgzbin0 -> 4495 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kopete_all_away.svgzbin0 -> 1222 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kopete_avdevice.svgzbin0 -> 2633 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kopete_offline.svgzbin0 -> 1442 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kopete_some_away.svgzbin0 -> 3647 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kopete_some_online.svgzbin0 -> 1754 bytes
-rw-r--r--IconThemes/mono/scalable/apps/korganizer.svgzbin0 -> 3501 bytes
-rw-r--r--IconThemes/mono/scalable/apps/korganizer_todo.svgzbin0 -> 3506 bytes
-rw-r--r--IconThemes/mono/scalable/apps/korn.svgzbin0 -> 6347 bytes
-rw-r--r--IconThemes/mono/scalable/apps/koshell.svgzbin0 -> 2287 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpackage.svgzbin0 -> 1999 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpager.svgzbin0 -> 2990 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpaint.svgzbin0 -> 2181 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpalmdoc.svgzbin0 -> 2678 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpat.svgzbin0 -> 2364 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpdf.svgzbin0 -> 2983 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpercentage.svgzbin0 -> 3269 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpersonalizer.svgzbin0 -> 2319 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpf.svgzbin0 -> 2563 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpilot.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpilotDaemon.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kplato.svgzbin0 -> 1615 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kplayer.svgzbin0 -> 2844 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpoker.svgzbin0 -> 2366 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpovmodeler.svgzbin0 -> 3022 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpowersave.svgzbin0 -> 2241 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kppp.svgzbin0 -> 3391 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kpresenter.svgzbin0 -> 3566 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kprintfax.svgzbin0 -> 5091 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kprof.svgzbin0 -> 2176 bytes
-rw-r--r--IconThemes/mono/scalable/apps/krdc.svgzbin0 -> 1850 bytes
-rw-r--r--IconThemes/mono/scalable/apps/krec.svgzbin0 -> 1817 bytes
-rw-r--r--IconThemes/mono/scalable/apps/krecipes.svgzbin0 -> 2515 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kregexpeditor.svgzbin0 -> 2220 bytes
-rw-r--r--IconThemes/mono/scalable/apps/krename.svgzbin0 -> 2503 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kreversi.svgzbin0 -> 2188 bytes
-rw-r--r--IconThemes/mono/scalable/apps/krfb.svgzbin0 -> 1850 bytes
-rw-r--r--IconThemes/mono/scalable/apps/krita.svgzbin0 -> 4330 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kruler.svgzbin0 -> 2685 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksame.svgzbin0 -> 2157 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksayit.svgzbin0 -> 1705 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksayit_clipempty.svgzbin0 -> 1897 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksayit_talking.svgzbin0 -> 4708 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kscd.svgzbin0 -> 2157 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kscreensaver.svgzbin0 -> 1719 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksensors.svgzbin0 -> 4250 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kservices.svgzbin0 -> 1576 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kshisen.svgzbin0 -> 2525 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kshutdown.svgzbin0 -> 2284 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksig.svgzbin0 -> 3440 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksim.svgzbin0 -> 1465 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksirc.svgzbin0 -> 4448 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksirtet.svgzbin0 -> 2522 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksmiletris.svgzbin0 -> 2099 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksnake.svgzbin0 -> 3077 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksnapshot.svgzbin0 -> 2143 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksokoban.svgzbin0 -> 1981 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kspaceduel.svgzbin0 -> 2388 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksplash.svgzbin0 -> 4225 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kspread.svgzbin0 -> 4136 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kstars.svgzbin0 -> 2482 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kstreamripper.svgzbin0 -> 2988 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksysguard.svgzbin0 -> 2551 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksysguardd.svgzbin0 -> 2479 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ksysv.svgzbin0 -> 1466 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktalkd.svgzbin0 -> 1705 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kteatime.svgzbin0 -> 3131 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktechlab.svgzbin0 -> 3528 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kthememgr.svgzbin0 -> 2107 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kthesaurus.svgzbin0 -> 2234 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktimemon.svgzbin0 -> 1773 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktimer.svgzbin0 -> 1709 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktip.svgzbin0 -> 3743 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktnef.svgzbin0 -> 1571 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktorrent.svgzbin0 -> 11461 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktouch.svgzbin0 -> 2449 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktron.svgzbin0 -> 1725 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kttsd.svgzbin0 -> 2321 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktuberling.svgzbin0 -> 2531 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kturtle.svgzbin0 -> 3744 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ktux.svgzbin0 -> 2248 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kudesigner.svgzbin0 -> 2210 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kugar.svgzbin0 -> 2118 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kuickshow.svgzbin0 -> 3779 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kuiviewer.svgzbin0 -> 2360 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kuser.svgzbin0 -> 1717 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kverbos.svgzbin0 -> 1968 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kview.svgzbin0 -> 3449 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kviewshell.svgzbin0 -> 3454 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kvim.svgzbin0 -> 5957 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kvirc.svgzbin0 -> 2089 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kvoctrain.svgzbin0 -> 2752 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwallet.svgzbin0 -> 9774 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwalletmanager.svgzbin0 -> 9774 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwave.svgzbin0 -> 2742 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwavecontrol.svgzbin0 -> 2175 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kweather.svgzbin0 -> 2704 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwifimanager.svgzbin0 -> 2175 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwikdisk.svgzbin0 -> 2001 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwin.svgzbin0 -> 3211 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwin4.svgzbin0 -> 2157 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kword.svgzbin0 -> 2700 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwordquiz.svgzbin0 -> 6129 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kworldclock.svgzbin0 -> 2751 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwrite.svgzbin0 -> 2400 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kwrite2.svgzbin0 -> 2400 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kxconfig.svgzbin0 -> 1746 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kxkb.svgzbin0 -> 2447 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kxsldbg.svgzbin0 -> 7655 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kynaptic.svgzbin0 -> 1999 bytes
-rw-r--r--IconThemes/mono/scalable/apps/kzenexplorer.svgzbin0 -> 2503 bytes
-rw-r--r--IconThemes/mono/scalable/apps/laptop_battery.svgzbin0 -> 2958 bytes
-rw-r--r--IconThemes/mono/scalable/apps/laptop_pcmcia.svgzbin0 -> 2954 bytes
-rw-r--r--IconThemes/mono/scalable/apps/lbreakout.svgzbin0 -> 2557 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ldap_client.svgzbin0 -> 2171 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ledger.svgzbin0 -> 3884 bytes
-rw-r--r--IconThemes/mono/scalable/apps/licq.svgzbin0 -> 3022 bytes
-rw-r--r--IconThemes/mono/scalable/apps/limewire.svgzbin0 -> 3166 bytes
-rw-r--r--IconThemes/mono/scalable/apps/linguist.svgzbin0 -> 2054 bytes
-rw-r--r--IconThemes/mono/scalable/apps/linuxconf.svgzbin0 -> 3035 bytes
-rw-r--r--IconThemes/mono/scalable/apps/locale.svgzbin0 -> 2057 bytes
-rw-r--r--IconThemes/mono/scalable/apps/lockscreen.svgzbin0 -> 1780 bytes
-rw-r--r--IconThemes/mono/scalable/apps/logjam.svgzbin0 -> 3300 bytes
-rw-r--r--IconThemes/mono/scalable/apps/logout.svgzbin0 -> 2286 bytes
-rw-r--r--IconThemes/mono/scalable/apps/looknfeel.svgzbin0 -> 2176 bytes
-rw-r--r--IconThemes/mono/scalable/apps/lskat.svgzbin0 -> 2365 bytes
-rw-r--r--IconThemes/mono/scalable/apps/lvm.svgzbin0 -> 1946 bytes
-rw-r--r--IconThemes/mono/scalable/apps/lyx.svgzbin0 -> 4804 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mac.svgzbin0 -> 2239 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mail.svgzbin0 -> 1570 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mail_section.svgzbin0 -> 1578 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mathematica.svgzbin0 -> 3215 bytes
-rw-r--r--IconThemes/mono/scalable/apps/media-player-48.svgzbin0 -> 2074 bytes
-rw-r--r--IconThemes/mono/scalable/apps/megami.svgzbin0 -> 2366 bytes
-rw-r--r--IconThemes/mono/scalable/apps/menubar.svgzbin0 -> 3399 bytes
-rw-r--r--IconThemes/mono/scalable/apps/misc2.svgzbin0 -> 1824 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mldonkey.svgzbin0 -> 2199 bytes
-rw-r--r--IconThemes/mono/scalable/apps/modem.svgzbin0 -> 3001 bytes
-rw-r--r--IconThemes/mono/scalable/apps/monop_board.svgzbin0 -> 3063 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mouse-capplet.svgzbin0 -> 2064 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mouse.svgzbin0 -> 2056 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mozilla-firefox.svgzbin0 -> 5259 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mozilla-navigator.svgzbin0 -> 1882 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mozilla-thunderbird.svgzbin0 -> 3152 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mozilla.svgzbin0 -> 1872 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mozilla_m.svgzbin0 -> 1874 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mozilla_mail.svgzbin0 -> 2210 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mozilla_mailnews.svgzbin0 -> 2214 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mplayer.svgzbin0 -> 2199 bytes
-rw-r--r--IconThemes/mono/scalable/apps/msn.svgzbin0 -> 2286 bytes
-rw-r--r--IconThemes/mono/scalable/apps/msn_protocol.svgzbin0 -> 2295 bytes
-rw-r--r--IconThemes/mono/scalable/apps/multihead.svgzbin0 -> 2536 bytes
-rw-r--r--IconThemes/mono/scalable/apps/multimedia.svgzbin0 -> 2202 bytes
-rw-r--r--IconThemes/mono/scalable/apps/multisynk.svgzbin0 -> 1528 bytes
-rw-r--r--IconThemes/mono/scalable/apps/my_mac.svgzbin0 -> 2348 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mycomp.svgzbin0 -> 2840 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mycomputer.svgzbin0 -> 2844 bytes
-rw-r--r--IconThemes/mono/scalable/apps/mymac.svgzbin0 -> 2347 bytes
-rw-r--r--IconThemes/mono/scalable/apps/napster.svgzbin0 -> 2466 bytes
-rw-r--r--IconThemes/mono/scalable/apps/nedit.svgzbin0 -> 2824 bytes
-rw-r--r--IconThemes/mono/scalable/apps/netscape.svgzbin0 -> 2475 bytes
-rw-r--r--IconThemes/mono/scalable/apps/network.svgzbin0 -> 1638 bytes
-rw-r--r--IconThemes/mono/scalable/apps/network_advanced.svgzbin0 -> 1691 bytes
-rw-r--r--IconThemes/mono/scalable/apps/nfs.svgzbin0 -> 1849 bytes
-rw-r--r--IconThemes/mono/scalable/apps/noatun.svgzbin0 -> 1666 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ntp-client.svgzbin0 -> 2109 bytes
-rw-r--r--IconThemes/mono/scalable/apps/nvu.svgzbin0 -> 3684 bytes
-rw-r--r--IconThemes/mono/scalable/apps/okle.svgzbin0 -> 2072 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_calc.svgzbin0 -> 3197 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_calc_tpl.svgzbin0 -> 3201 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_chart.svgzbin0 -> 3198 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_draw.svgzbin0 -> 2555 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_gulls.svgzbin0 -> 2355 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_impress.svgzbin0 -> 3153 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_impress_tpl.svgzbin0 -> 3157 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_math.svgzbin0 -> 3148 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_printeradmin.svgzbin0 -> 2598 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_setup.svgzbin0 -> 3123 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_template.svgzbin0 -> 3712 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_web.svgzbin0 -> 3642 bytes
-rw-r--r--IconThemes/mono/scalable/apps/ooo_writer.svgzbin0 -> 2727 bytes
-rw-r--r--IconThemes/mono/scalable/apps/openft.svgzbin0 -> 2785 bytes
-rw-r--r--IconThemes/mono/scalable/apps/openoffice.svgzbin0 -> 2356 bytes
-rw-r--r--IconThemes/mono/scalable/apps/openoffice1.svgzbin0 -> 2357 bytes
-rw-r--r--IconThemes/mono/scalable/apps/opera.svgzbin0 -> 2303 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package.svgzbin0 -> 1913 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_application.svgzbin0 -> 2370 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_applications.svgzbin0 -> 2371 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_development.svgzbin0 -> 2433 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_editors.svgzbin0 -> 2409 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_edutainment.svgzbin0 -> 2986 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_favourite.svgzbin0 -> 1493 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_games.svgzbin0 -> 2944 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_games_arcade.svgzbin0 -> 1966 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_games_board.svgzbin0 -> 3071 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_games_card.svgzbin0 -> 2378 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_games_cards.svgzbin0 -> 2379 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_games_kids.svgzbin0 -> 4075 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_games_strategy.svgzbin0 -> 2425 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_graphics.svgzbin0 -> 2186 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_multimedia.svgzbin0 -> 2210 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_network.svgzbin0 -> 1638 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_settings.svgzbin0 -> 2041 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_system.svgzbin0 -> 2848 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_toys.svgzbin0 -> 4075 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_utilities.svgzbin0 -> 2042 bytes
-rw-r--r--IconThemes/mono/scalable/apps/package_wordprocessing.svgzbin0 -> 2602 bytes
-rw-r--r--IconThemes/mono/scalable/apps/palm-pilot.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/apps/pan.svgzbin0 -> 3216 bytes
-rw-r--r--IconThemes/mono/scalable/apps/panel.svgzbin0 -> 2767 bytes
-rw-r--r--IconThemes/mono/scalable/apps/panel_settings.svgzbin0 -> 2776 bytes
-rw-r--r--IconThemes/mono/scalable/apps/partitioner.svgzbin0 -> 1954 bytes
-rw-r--r--IconThemes/mono/scalable/apps/password.svgzbin0 -> 3547 bytes
-rw-r--r--IconThemes/mono/scalable/apps/payee.svgzbin0 -> 2857 bytes
-rw-r--r--IconThemes/mono/scalable/apps/pcmcia.svgzbin0 -> 2947 bytes
-rw-r--r--IconThemes/mono/scalable/apps/penguin.svgzbin0 -> 2252 bytes
-rw-r--r--IconThemes/mono/scalable/apps/personal.svgzbin0 -> 1720 bytes
-rw-r--r--IconThemes/mono/scalable/apps/photobook.svgzbin0 -> 2194 bytes
-rw-r--r--IconThemes/mono/scalable/apps/phppg.svgzbin0 -> 4616 bytes
-rw-r--r--IconThemes/mono/scalable/apps/plan.svgzbin0 -> 2483 bytes
-rw-r--r--IconThemes/mono/scalable/apps/planner.svgzbin0 -> 2486 bytes
-rw-r--r--IconThemes/mono/scalable/apps/playing.svgzbin0 -> 1552 bytes
-rw-r--r--IconThemes/mono/scalable/apps/potracegui.svgzbin0 -> 2212 bytes
-rw-r--r--IconThemes/mono/scalable/apps/power-management.svgzbin0 -> 2247 bytes
-rw-r--r--IconThemes/mono/scalable/apps/power-manager.svgzbin0 -> 1994 bytes
-rw-r--r--IconThemes/mono/scalable/apps/powertweak.svgzbin0 -> 2035 bytes
-rw-r--r--IconThemes/mono/scalable/apps/printer.svgzbin0 -> 2020 bytes
-rw-r--r--IconThemes/mono/scalable/apps/printer2.svgzbin0 -> 2021 bytes
-rw-r--r--IconThemes/mono/scalable/apps/printing_section.svgzbin0 -> 2029 bytes
-rw-r--r--IconThemes/mono/scalable/apps/printmgr.svgzbin0 -> 2021 bytes
-rw-r--r--IconThemes/mono/scalable/apps/proxy.svgzbin0 -> 1836 bytes
-rw-r--r--IconThemes/mono/scalable/apps/psi.svgzbin0 -> 2126 bytes
-rw-r--r--IconThemes/mono/scalable/apps/pwmanager.svgzbin0 -> 3548 bytes
-rw-r--r--IconThemes/mono/scalable/apps/pybliographic.svgzbin0 -> 1721 bytes
-rw-r--r--IconThemes/mono/scalable/apps/pysol.svgzbin0 -> 1769 bytes
-rw-r--r--IconThemes/mono/scalable/apps/qt.svgzbin0 -> 2550 bytes
-rw-r--r--IconThemes/mono/scalable/apps/qtella.svgzbin0 -> 3341 bytes
-rw-r--r--IconThemes/mono/scalable/apps/quanta.svgzbin0 -> 4011 bytes
-rw-r--r--IconThemes/mono/scalable/apps/quanta_be.svgzbin0 -> 4014 bytes
-rw-r--r--IconThemes/mono/scalable/apps/quicktime.svgzbin0 -> 2634 bytes
-rw-r--r--IconThemes/mono/scalable/apps/randr.svgzbin0 -> 2204 bytes
-rw-r--r--IconThemes/mono/scalable/apps/realplay.svgzbin0 -> 3970 bytes
-rw-r--r--IconThemes/mono/scalable/apps/realplayer.svgzbin0 -> 3970 bytes
-rw-r--r--IconThemes/mono/scalable/apps/relokate.svgzbin0 -> 2218 bytes
-rw-r--r--IconThemes/mono/scalable/apps/remote.svgzbin0 -> 2169 bytes
-rw-r--r--IconThemes/mono/scalable/apps/rsibreak.svgzbin0 -> 1708 bytes
-rw-r--r--IconThemes/mono/scalable/apps/running.svgzbin0 -> 1409 bytes
-rw-r--r--IconThemes/mono/scalable/apps/runprocesscatcher.svgzbin0 -> 2027 bytes
-rw-r--r--IconThemes/mono/scalable/apps/samba-client.svgzbin0 -> 2193 bytes
-rw-r--r--IconThemes/mono/scalable/apps/samba-server.svgzbin0 -> 2193 bytes
-rw-r--r--IconThemes/mono/scalable/apps/samba.svgzbin0 -> 2442 bytes
-rw-r--r--IconThemes/mono/scalable/apps/samba_client.svgzbin0 -> 2193 bytes
-rw-r--r--IconThemes/mono/scalable/apps/samba_server.svgzbin0 -> 2193 bytes
-rw-r--r--IconThemes/mono/scalable/apps/samba_setup.svgzbin0 -> 2448 bytes
-rw-r--r--IconThemes/mono/scalable/apps/scanner.svgzbin0 -> 2434 bytes
-rw-r--r--IconThemes/mono/scalable/apps/schedule.svgzbin0 -> 2479 bytes
-rw-r--r--IconThemes/mono/scalable/apps/screensaver.svgzbin0 -> 1718 bytes
-rw-r--r--IconThemes/mono/scalable/apps/scribus.svgzbin0 -> 1715 bytes
-rw-r--r--IconThemes/mono/scalable/apps/searchtool.svgzbin0 -> 1922 bytes
-rw-r--r--IconThemes/mono/scalable/apps/settings-sound.svgzbin0 -> 2522 bytes
-rw-r--r--IconThemes/mono/scalable/apps/shell.svgzbin0 -> 1572 bytes
-rw-r--r--IconThemes/mono/scalable/apps/shells_section.svgzbin0 -> 1606 bytes
-rw-r--r--IconThemes/mono/scalable/apps/showfoto.svgzbin0 -> 2194 bytes
-rw-r--r--IconThemes/mono/scalable/apps/showimg.svgzbin0 -> 2362 bytes
-rw-r--r--IconThemes/mono/scalable/apps/shredder.svgzbin0 -> 2183 bytes
-rw-r--r--IconThemes/mono/scalable/apps/sim.svgzbin0 -> 3021 bytes
-rw-r--r--IconThemes/mono/scalable/apps/slp.svgzbin0 -> 1678 bytes
-rw-r--r--IconThemes/mono/scalable/apps/smb4k.svgzbin0 -> 2442 bytes
-rw-r--r--IconThemes/mono/scalable/apps/sms_protocol.svgzbin0 -> 8407 bytes
-rw-r--r--IconThemes/mono/scalable/apps/sodipodi.svgzbin0 -> 2255 bytes
-rw-r--r--IconThemes/mono/scalable/apps/soffice.svgzbin0 -> 2980 bytes
-rw-r--r--IconThemes/mono/scalable/apps/software.svgzbin0 -> 1914 bytes
-rw-r--r--IconThemes/mono/scalable/apps/software2.svgzbin0 -> 1915 bytes
-rw-r--r--IconThemes/mono/scalable/apps/soulseek.svgzbin0 -> 2535 bytes
-rw-r--r--IconThemes/mono/scalable/apps/soundcard.svgzbin0 -> 2499 bytes
-rw-r--r--IconThemes/mono/scalable/apps/source.svgzbin0 -> 5375 bytes
-rw-r--r--IconThemes/mono/scalable/apps/staroffice.svgzbin0 -> 3034 bytes
-rw-r--r--IconThemes/mono/scalable/apps/style.svgzbin0 -> 2093 bytes
-rw-r--r--IconThemes/mono/scalable/apps/stylesheet.svgzbin0 -> 4674 bytes
-rw-r--r--IconThemes/mono/scalable/apps/superkaramba.svgzbin0 -> 2448 bytes
-rw-r--r--IconThemes/mono/scalable/apps/support.svgzbin0 -> 5124 bytes
-rw-r--r--IconThemes/mono/scalable/apps/suse.svgzbin0 -> 1823 bytes
-rw-r--r--IconThemes/mono/scalable/apps/synaescope.svgzbin0 -> 2465 bytes
-rw-r--r--IconThemes/mono/scalable/apps/synaptic.svgzbin0 -> 1999 bytes
-rw-r--r--IconThemes/mono/scalable/apps/sysadmin.svgzbin0 -> 2085 bytes
-rw-r--r--IconThemes/mono/scalable/apps/system-floppy.svgzbin0 -> 1712 bytes
-rw-r--r--IconThemes/mono/scalable/apps/system.svgzbin0 -> 1598 bytes
-rw-r--r--IconThemes/mono/scalable/apps/systemprotocol.svgzbin0 -> 1606 bytes
-rw-r--r--IconThemes/mono/scalable/apps/systemsettings.svgzbin0 -> 1989 bytes
-rw-r--r--IconThemes/mono/scalable/apps/systemtray.svgzbin0 -> 1555 bytes
-rw-r--r--IconThemes/mono/scalable/apps/taskbar.svgzbin0 -> 1805 bytes
-rw-r--r--IconThemes/mono/scalable/apps/tdsl.svgzbin0 -> 3000 bytes
-rw-r--r--IconThemes/mono/scalable/apps/tellico.svgzbin0 -> 2629 bytes
-rw-r--r--IconThemes/mono/scalable/apps/telnet.svgzbin0 -> 1598 bytes
-rw-r--r--IconThemes/mono/scalable/apps/terminal.svgzbin0 -> 1600 bytes
-rw-r--r--IconThemes/mono/scalable/apps/terminals_section.svgzbin0 -> 1609 bytes
-rw-r--r--IconThemes/mono/scalable/apps/thunderbird.svgzbin0 -> 3144 bytes
-rw-r--r--IconThemes/mono/scalable/apps/timezone.svgzbin0 -> 1711 bytes
-rw-r--r--IconThemes/mono/scalable/apps/timezone2.svgzbin0 -> 1712 bytes
-rw-r--r--IconThemes/mono/scalable/apps/tux.svgzbin0 -> 2248 bytes
-rw-r--r--IconThemes/mono/scalable/apps/tv.svgzbin0 -> 2726 bytes
-rw-r--r--IconThemes/mono/scalable/apps/tvtime.svgzbin0 -> 2726 bytes
-rw-r--r--IconThemes/mono/scalable/apps/umbrello.svgzbin0 -> 2120 bytes
-rw-r--r--IconThemes/mono/scalable/apps/unknownapp.svgzbin0 -> 1547 bytes
-rw-r--r--IconThemes/mono/scalable/apps/usb.svgzbin0 -> 2047 bytes
-rw-r--r--IconThemes/mono/scalable/apps/user-info.svgzbin0 -> 2115 bytes
-rw-r--r--IconThemes/mono/scalable/apps/userconfig.svgzbin0 -> 1685 bytes
-rw-r--r--IconThemes/mono/scalable/apps/visor.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/apps/vnc.svgzbin0 -> 5336 bytes
-rw-r--r--IconThemes/mono/scalable/apps/wabi.svgzbin0 -> 2842 bytes
-rw-r--r--IconThemes/mono/scalable/apps/waiting.svgzbin0 -> 1555 bytes
-rw-r--r--IconThemes/mono/scalable/apps/wallpaper.svgzbin0 -> 2413 bytes
-rw-r--r--IconThemes/mono/scalable/apps/warning.svgzbin0 -> 2092 bytes
-rw-r--r--IconThemes/mono/scalable/apps/web-browser.svgzbin0 -> 2571 bytes
-rw-r--r--IconThemes/mono/scalable/apps/wilber.svgzbin0 -> 3095 bytes
-rw-r--r--IconThemes/mono/scalable/apps/win_apps.svgzbin0 -> 2846 bytes
-rw-r--r--IconThemes/mono/scalable/apps/window-capplet.svgzbin0 -> 2428 bytes
-rw-r--r--IconThemes/mono/scalable/apps/window_list.svgzbin0 -> 2425 bytes
-rw-r--r--IconThemes/mono/scalable/apps/wine.svgzbin0 -> 3231 bytes
-rw-r--r--IconThemes/mono/scalable/apps/wineconfig.svgzbin0 -> 3231 bytes
-rw-r--r--IconThemes/mono/scalable/apps/winprops.svgzbin0 -> 2359 bytes
-rw-r--r--IconThemes/mono/scalable/apps/wmaker_apps.svgzbin0 -> 1884 bytes
-rw-r--r--IconThemes/mono/scalable/apps/wp.svgzbin0 -> 3678 bytes
-rw-r--r--IconThemes/mono/scalable/apps/www.svgzbin0 -> 2563 bytes
-rw-r--r--IconThemes/mono/scalable/apps/x.svgzbin0 -> 1739 bytes
-rw-r--r--IconThemes/mono/scalable/apps/x11.svgzbin0 -> 1595 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xapp.svgzbin0 -> 1742 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xawtv.svgzbin0 -> 2726 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xcalc.svgzbin0 -> 1797 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xcdroast.svgzbin0 -> 2580 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xchat.svgzbin0 -> 4494 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xclipboard.svgzbin0 -> 1725 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xclock.svgzbin0 -> 1709 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xconsole.svgzbin0 -> 1600 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xedit.svgzbin0 -> 2399 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xemacs.svgzbin0 -> 2815 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xeyes.svgzbin0 -> 2122 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xfig.svgzbin0 -> 2301 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xfmail.svgzbin0 -> 1572 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xine.svgzbin0 -> 2013 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xload.svgzbin0 -> 1782 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xmag.svgzbin0 -> 1916 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xmms.svgzbin0 -> 2512 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xosview.svgzbin0 -> 1784 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xpaint.svgzbin0 -> 2176 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xsane.svgzbin0 -> 2432 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xterm-terminal.svgzbin0 -> 1606 bytes
-rw-r--r--IconThemes/mono/scalable/apps/xv.svgzbin0 -> 2809 bytes
-rw-r--r--IconThemes/mono/scalable/apps/yahoo_protocol.svgzbin0 -> 3013 bytes
-rw-r--r--IconThemes/mono/scalable/apps/yakuake.svgzbin0 -> 1599 bytes
-rw-r--r--IconThemes/mono/scalable/apps/zip.svgzbin0 -> 2016 bytes
-rw-r--r--IconThemes/mono/scalable/devices/3floppy_mount.svgzbin0 -> 1712 bytes
-rw-r--r--IconThemes/mono/scalable/devices/3floppy_unmount.svgzbin0 -> 1660 bytes
-rw-r--r--IconThemes/mono/scalable/devices/5floppy_mount.svgzbin0 -> 2036 bytes
-rw-r--r--IconThemes/mono/scalable/devices/5floppy_unmount.svgzbin0 -> 2176 bytes
-rw-r--r--IconThemes/mono/scalable/devices/blockdevice.svgzbin0 -> 2052 bytes
-rw-r--r--IconThemes/mono/scalable/devices/cam.svgzbin0 -> 1936 bytes
-rw-r--r--IconThemes/mono/scalable/devices/camera.svgzbin0 -> 1939 bytes
-rw-r--r--IconThemes/mono/scalable/devices/camera_mount.svgzbin0 -> 1945 bytes
-rw-r--r--IconThemes/mono/scalable/devices/camera_unmount.svgzbin0 -> 2423 bytes
-rw-r--r--IconThemes/mono/scalable/devices/cdaudio_mount.svgzbin0 -> 1884 bytes
-rw-r--r--IconThemes/mono/scalable/devices/cdaudio_unmount.svgzbin0 -> 2917 bytes
-rw-r--r--IconThemes/mono/scalable/devices/cdrom_audio.svgzbin0 -> 1882 bytes
-rw-r--r--IconThemes/mono/scalable/devices/cdrom_mount.svgzbin0 -> 1772 bytes
-rw-r--r--IconThemes/mono/scalable/devices/cdrom_unmount.svgzbin0 -> 3308 bytes
-rw-r--r--IconThemes/mono/scalable/devices/cdwriter_mount.svgzbin0 -> 2834 bytes
-rw-r--r--IconThemes/mono/scalable/devices/cdwriter_unmount.svgzbin0 -> 5426 bytes
-rw-r--r--IconThemes/mono/scalable/devices/chardevice.svgzbin0 -> 1602 bytes
-rw-r--r--IconThemes/mono/scalable/devices/compact_flash_mount.svgzbin0 -> 2842 bytes
-rw-r--r--IconThemes/mono/scalable/devices/compact_flash_unmount.svgzbin0 -> 2206 bytes
-rw-r--r--IconThemes/mono/scalable/devices/dvd_mount.svgzbin0 -> 2077 bytes
-rw-r--r--IconThemes/mono/scalable/devices/dvd_unmount.svgzbin0 -> 2340 bytes
-rw-r--r--IconThemes/mono/scalable/devices/firewire_mount.svgzbin0 -> 2099 bytes
-rw-r--r--IconThemes/mono/scalable/devices/firewire_unmount.svgzbin0 -> 2229 bytes
-rw-r--r--IconThemes/mono/scalable/devices/handheld.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/devices/hdd_mount.svgzbin0 -> 1470 bytes
-rw-r--r--IconThemes/mono/scalable/devices/hdd_unmount.svgzbin0 -> 1682 bytes
-rw-r--r--IconThemes/mono/scalable/devices/hdd_usb.svgzbin0 -> 2141 bytes
-rw-r--r--IconThemes/mono/scalable/devices/hdd_win_mount.svgzbin0 -> 2311 bytes
-rw-r--r--IconThemes/mono/scalable/devices/hdd_win_unmount.svgzbin0 -> 2266 bytes
-rw-r--r--IconThemes/mono/scalable/devices/ipod_mount.svgzbin0 -> 1850 bytes
-rw-r--r--IconThemes/mono/scalable/devices/ipod_unmount.svgzbin0 -> 1874 bytes
-rw-r--r--IconThemes/mono/scalable/devices/joystick.svgzbin0 -> 2204 bytes
-rw-r--r--IconThemes/mono/scalable/devices/ksim_cpu.svgzbin0 -> 4250 bytes
-rw-r--r--IconThemes/mono/scalable/devices/kxkb.svgzbin0 -> 2447 bytes
-rw-r--r--IconThemes/mono/scalable/devices/laptop.svgzbin0 -> 1826 bytes
-rw-r--r--IconThemes/mono/scalable/devices/linux_hdd_mount.svgzbin0 -> 2423 bytes
-rw-r--r--IconThemes/mono/scalable/devices/linux_hdd_unmount.svgzbin0 -> 2414 bytes
-rw-r--r--IconThemes/mono/scalable/devices/memory.svgzbin0 -> 2353 bytes
-rw-r--r--IconThemes/mono/scalable/devices/memory_stick_mount.svgzbin0 -> 3458 bytes
-rw-r--r--IconThemes/mono/scalable/devices/memory_stick_unmount.svgzbin0 -> 2966 bytes
-rw-r--r--IconThemes/mono/scalable/devices/mo_mount.svgzbin0 -> 2085 bytes
-rw-r--r--IconThemes/mono/scalable/devices/mo_unmount.svgzbin0 -> 2325 bytes
-rw-r--r--IconThemes/mono/scalable/devices/modem.svgzbin0 -> 3001 bytes
-rw-r--r--IconThemes/mono/scalable/devices/mouse.svgzbin0 -> 2067 bytes
-rw-r--r--IconThemes/mono/scalable/devices/nfs_mount.svgzbin0 -> 1671 bytes
-rw-r--r--IconThemes/mono/scalable/devices/nfs_unmount.svgzbin0 -> 1688 bytes
-rw-r--r--IconThemes/mono/scalable/devices/pda.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/devices/pda_black.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/devices/pda_blue.svgzbin0 -> 1827 bytes
-rw-r--r--IconThemes/mono/scalable/devices/print_class.svgzbin0 -> 2516 bytes
-rw-r--r--IconThemes/mono/scalable/devices/print_printer.svgzbin0 -> 2026 bytes
-rw-r--r--IconThemes/mono/scalable/devices/printer1.svgzbin0 -> 2021 bytes
-rw-r--r--IconThemes/mono/scalable/devices/printer2.svgzbin0 -> 2021 bytes
-rw-r--r--IconThemes/mono/scalable/devices/scanner.svgzbin0 -> 2434 bytes
-rw-r--r--IconThemes/mono/scalable/devices/sd_mmc_mount.svgzbin0 -> 3628 bytes
-rw-r--r--IconThemes/mono/scalable/devices/sd_mmc_unmount.svgzbin0 -> 3387 bytes
-rw-r--r--IconThemes/mono/scalable/devices/smart_media_mount.svgzbin0 -> 4518 bytes
-rw-r--r--IconThemes/mono/scalable/devices/smart_media_unmount.svgzbin0 -> 4458 bytes
-rw-r--r--IconThemes/mono/scalable/devices/system.svgzbin0 -> 2840 bytes
-rw-r--r--IconThemes/mono/scalable/devices/tablet.svgzbin0 -> 2585 bytes
-rw-r--r--IconThemes/mono/scalable/devices/tv.svgzbin0 -> 2726 bytes
-rw-r--r--IconThemes/mono/scalable/devices/usb_mount.svgzbin0 -> 2143 bytes
-rw-r--r--IconThemes/mono/scalable/devices/usb_unmount.svgzbin0 -> 2408 bytes
-rw-r--r--IconThemes/mono/scalable/devices/usbdisk_mount.svgzbin0 -> 2147 bytes
-rw-r--r--IconThemes/mono/scalable/devices/usbdisk_unmount.svgzbin0 -> 2412 bytes
-rw-r--r--IconThemes/mono/scalable/devices/usbpendrive_mount.svgzbin0 -> 2151 bytes
-rw-r--r--IconThemes/mono/scalable/devices/usbpendrive_unmount.svgzbin0 -> 2416 bytes
-rw-r--r--IconThemes/mono/scalable/devices/zip_external_mount.svgzbin0 -> 1850 bytes
-rw-r--r--IconThemes/mono/scalable/devices/zip_external_unmount.svgzbin0 -> 1966 bytes
-rw-r--r--IconThemes/mono/scalable/devices/zip_mount.svgzbin0 -> 2022 bytes
-rw-r--r--IconThemes/mono/scalable/devices/zip_unmount.svgzbin0 -> 2153 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/blockdevice.svgzbin0 -> 2052 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/camera.svgzbin0 -> 1939 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/chardevice.svgzbin0 -> 2354 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/connect_to_network.svgzbin0 -> 1649 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/desktop.svgzbin0 -> 2287 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/exec.svgzbin0 -> 1731 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/exec_wine.svgzbin0 -> 3236 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/file_broken.svgzbin0 -> 1633 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/file_important.svgzbin0 -> 2275 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/file_locked.svgzbin0 -> 1940 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/file_temporary.svgzbin0 -> 1847 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder.svgzbin0 -> 2324 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_apollon.svgzbin0 -> 2763 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_binary.svgzbin0 -> 11679 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_bomb.svgzbin0 -> 2753 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_cd.svgzbin0 -> 2369 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_crystal.svgzbin0 -> 2381 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_cyan.svgzbin0 -> 2329 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_cyan_open.svgzbin0 -> 2383 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_deb.svgzbin0 -> 1947 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_documents.svgzbin0 -> 2372 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_download.svgzbin0 -> 2089 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_favorite.svgzbin0 -> 2168 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_fonts.svgzbin0 -> 4315 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_games.svgzbin0 -> 2828 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_green.svgzbin0 -> 2330 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_green_open.svgzbin0 -> 2384 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_grey.svgzbin0 -> 2329 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_grey_open.svgzbin0 -> 2383 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_home.svgzbin0 -> 1753 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_home2.svgzbin0 -> 2318 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_html.svgzbin0 -> 3323 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_image.svgzbin0 -> 2748 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_important.svgzbin0 -> 2788 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_inbox.svgzbin0 -> 1477 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_locked.svgzbin0 -> 2347 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_mail.svgzbin0 -> 2158 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_man.svgzbin0 -> 2366 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_midi.svgzbin0 -> 2775 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_music.svgzbin0 -> 2405 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_open.svgzbin0 -> 2378 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_orange.svgzbin0 -> 2331 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_orange_open.svgzbin0 -> 2385 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_outbox.svgzbin0 -> 1504 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_print.svgzbin0 -> 2374 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_print2.svgzbin0 -> 2375 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_red.svgzbin0 -> 2328 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_red_open.svgzbin0 -> 2382 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_rpm.svgzbin0 -> 4475 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_sent_mail.svgzbin0 -> 1507 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_sound.svgzbin0 -> 2405 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_synch.svgzbin0 -> 2225 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_tar.svgzbin0 -> 2475 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_txt.svgzbin0 -> 2403 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_video.svgzbin0 -> 3057 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_violet.svgzbin0 -> 2331 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_violet_open.svgzbin0 -> 2385 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_wine.svgzbin0 -> 2785 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_yellow.svgzbin0 -> 2331 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/folder_yellow_open.svgzbin0 -> 2385 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/ftp.svgzbin0 -> 2748 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/link_overlay.svgzbin0 -> 1813 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/lock_overlay.svgzbin0 -> 1917 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/mycomp.svgzbin0 -> 2840 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/mycomputer.svgzbin0 -> 2844 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/network.svgzbin0 -> 1638 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/network_local.svgzbin0 -> 1859 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/pipe.svgzbin0 -> 2283 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/server.svgzbin0 -> 1958 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/services.svgzbin0 -> 2108 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/socket.svgzbin0 -> 2428 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/trashcan_empty.svgzbin0 -> 1495 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/trashcan_full.svgzbin0 -> 1971 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/www.svgzbin0 -> 2830 bytes
-rw-r--r--IconThemes/mono/scalable/filesystems/zip_overlay.svgzbin0 -> 1741 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/applix.svgzbin0 -> 2271 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/ascii.svgzbin0 -> 4608 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/backup.svgzbin0 -> 2333 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/binary.svgzbin0 -> 8183 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/blender3d.svgzbin0 -> 2394 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/bt.svgzbin0 -> 9415 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/cdbo_list.svgzbin0 -> 2029 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/cdimage.svgzbin0 -> 1929 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/cdr.svgzbin0 -> 2193 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/cdtrack.svgzbin0 -> 2200 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/chart.svgzbin0 -> 2126 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/colorscm.svgzbin0 -> 2143 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/colorset.svgzbin0 -> 2143 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/configure.svgzbin0 -> 1923 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/core.svgzbin0 -> 2346 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/database.svgzbin0 -> 2607 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/deb.svgzbin0 -> 3599 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/djvu.svgzbin0 -> 3926 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/document.svgzbin0 -> 1978 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/document2.svgzbin0 -> 1979 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/drawing.svgzbin0 -> 2045 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/dvi.svgzbin0 -> 3118 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/empty.svgzbin0 -> 1593 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/encrypted.svgzbin0 -> 1938 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/exec_wine.svgzbin0 -> 2355 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/executable.svgzbin0 -> 1856 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/file_locked.svgzbin0 -> 1940 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/file_temporary.svgzbin0 -> 1891 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/font.svgzbin0 -> 3915 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/font_bitmap.svgzbin0 -> 3922 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/font_truetype.svgzbin0 -> 3924 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/font_type1.svgzbin0 -> 3921 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/formula.svgzbin0 -> 2562 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/gettext.svgzbin0 -> 3918 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/gf.svgzbin0 -> 3170 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/gnome-library.svgzbin0 -> 3644 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/gnome_app_info.svgzbin0 -> 2762 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/graphic.svgzbin0 -> 2407 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/html.svgzbin0 -> 2831 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/igc.svgzbin0 -> 1877 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/image.svgzbin0 -> 2352 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/images.svgzbin0 -> 2349 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/info.svgzbin0 -> 2131 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/ipod.svgzbin0 -> 2165 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/java_jar.svgzbin0 -> 1977 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/javascript.svgzbin0 -> 3411 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/karbon_karbon.svgzbin0 -> 2024 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kchart_chrt.svgzbin0 -> 2132 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kdevelop_project.svgzbin0 -> 2358 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kexi.svgzbin0 -> 2826 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kexi_kexi.svgzbin0 -> 2836 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kexiproject_shortcut.svgzbin0 -> 3248 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kexiproject_sqlite.svgzbin0 -> 2853 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kexiproject_sqlite2.svgzbin0 -> 2855 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kformula_kfo.svgzbin0 -> 2567 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kget_list.svgzbin0 -> 2911 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kig_doc.svgzbin0 -> 3395 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kivio_flw.svgzbin0 -> 2030 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kmultiple.svgzbin0 -> 2797 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kmy.svgzbin0 -> 3036 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/koffice.svgzbin0 -> 3951 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kopete_emoticons.svgzbin0 -> 1993 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kpovmodeler_doc.svgzbin0 -> 2516 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kpresenter_kpr.svgzbin0 -> 3344 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/krita_kra.svgzbin0 -> 2407 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kspread_ksp.svgzbin0 -> 2466 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kugar_kud.svgzbin0 -> 2209 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kugardata.svgzbin0 -> 2209 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kword_kwd.svgzbin0 -> 2541 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/kwordquiz_doc.svgzbin0 -> 3882 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/log.svgzbin0 -> 3048 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/lpl.svgzbin0 -> 1920 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/make.svgzbin0 -> 1856 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/man.svgzbin0 -> 2290 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/message.svgzbin0 -> 3728 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/metafont.svgzbin0 -> 3919 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/midi.svgzbin0 -> 2363 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/mime.svgzbin0 -> 1589 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/mime_kaffeine.svgzbin0 -> 2387 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/mime_lyx.svgzbin0 -> 3354 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/mime_video.svgzbin0 -> 2658 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/misc.svgzbin0 -> 1590 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/misc_doc.svgzbin0 -> 1599 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/moc_src.svgzbin0 -> 3848 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/money.svgzbin0 -> 2837 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/mozilla_doc.svgzbin0 -> 1857 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/netscape.svgzbin0 -> 2394 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/netscape_doc.svgzbin0 -> 2398 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/news.svgzbin0 -> 3170 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/pdf.svgzbin0 -> 1913 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/php.svgzbin0 -> 2934 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/pk.svgzbin0 -> 2057 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/postscript.svgzbin0 -> 3446 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/presentation.svgzbin0 -> 2311 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/printer.svgzbin0 -> 1921 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/psd.svgzbin0 -> 3688 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/quicktime.svgzbin0 -> 2430 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/readme.svgzbin0 -> 2133 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/real.svgzbin0 -> 3706 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/real_doc.svgzbin0 -> 3714 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/recycled.svgzbin0 -> 2122 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/reject.svgzbin0 -> 1651 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/resource.svgzbin0 -> 2211 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/rpm.svgzbin0 -> 3973 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/shellscript.svgzbin0 -> 1710 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/soffice.svgzbin0 -> 2955 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/sound.svgzbin0 -> 1950 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source.svgzbin0 -> 5375 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_c.svgzbin0 -> 2489 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_cpp.svgzbin0 -> 3323 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_f.svgzbin0 -> 2026 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_h.svgzbin0 -> 1999 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_j.svgzbin0 -> 2179 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_java.svgzbin0 -> 1977 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_l.svgzbin0 -> 1913 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_moc.svgzbin0 -> 3848 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_mono.svgzbin0 -> 3588 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_o.svgzbin0 -> 2318 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_p.svgzbin0 -> 2142 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_php.svgzbin0 -> 2934 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_pl.svgzbin0 -> 2488 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_py.svgzbin0 -> 2671 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_s.svgzbin0 -> 2731 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_xml.svgzbin0 -> 3363 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/source_y.svgzbin0 -> 2143 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/spreadsheet.svgzbin0 -> 2466 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/sql.svgzbin0 -> 3816 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/superkaramba_theme.svgzbin0 -> 2346 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/swf.svgzbin0 -> 3463 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/tar.svgzbin0 -> 3553 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/tellico.svgzbin0 -> 2639 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/template.svgzbin0 -> 2799 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/template_source.svgzbin0 -> 2799 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/tex.svgzbin0 -> 2998 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/text.svgzbin0 -> 2432 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/tgz.svgzbin0 -> 4056 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/torrent.svgzbin0 -> 9415 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/trash.svgzbin0 -> 2119 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/txt.svgzbin0 -> 1780 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/txt2.svgzbin0 -> 1781 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/umbrellofile.svgzbin0 -> 2044 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/unknown.svgzbin0 -> 2546 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/vcalendar.svgzbin0 -> 2489 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/vcard.svgzbin0 -> 5286 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/vectorgfx.svgzbin0 -> 2047 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/video.svgzbin0 -> 2658 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/widget_doc.svgzbin0 -> 2140 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/wordprocessing.svgzbin0 -> 2546 bytes
-rw-r--r--IconThemes/mono/scalable/mimetypes/zip.svgzbin0 -> 3434 bytes
-rw-r--r--Makefile.am.in9
-rw-r--r--Makefile.cvs15
-rw-r--r--configure.in.in51
-rw-r--r--doc/Makefile.am5
-rw-r--r--doc/kmag/Makefile.am4
-rw-r--r--doc/kmag/index.docbook647
-rw-r--r--doc/kmag/man-kmag.1.docbook64
-rw-r--r--doc/kmag/screenshot.pngbin0 -> 192028 bytes
-rw-r--r--doc/kmousetool/Makefile.am4
-rw-r--r--doc/kmousetool/index.docbook449
-rw-r--r--doc/kmousetool/man-kmousetool.1.docbook63
-rw-r--r--doc/kmouth/Makefile.am4
-rw-r--r--doc/kmouth/index.docbook1122
-rw-r--r--doc/kmouth/kmouthcpref.eps3026
-rw-r--r--doc/kmouth/kmouthcpref.pngbin0 -> 24491 bytes
-rw-r--r--doc/kmouth/kmouthctts.eps2856
-rw-r--r--doc/kmouth/kmouthctts.pngbin0 -> 24949 bytes
-rw-r--r--doc/kmouth/kmouthcwcp.eps3136
-rw-r--r--doc/kmouth/kmouthcwcp.pngbin0 -> 28450 bytes
-rw-r--r--doc/kmouth/kmouthedit.eps2637
-rw-r--r--doc/kmouth/kmouthedit.pngbin0 -> 23646 bytes
-rw-r--r--doc/kmouth/kmouthmain.eps2284
-rw-r--r--doc/kmouth/kmouthmain.pngbin0 -> 18825 bytes
-rw-r--r--doc/kmouth/kmouthwizard.eps4821
-rw-r--r--doc/kmouth/kmouthwizard.pngbin0 -> 23735 bytes
-rw-r--r--doc/kmouth/man-kmouth.1.docbook78
-rw-r--r--doc/kttsd/Makefile.am3
-rw-r--r--doc/kttsd/addtalker.pngbin0 -> 74936 bytes
-rw-r--r--doc/kttsd/audio.pngbin0 -> 81665 bytes
-rw-r--r--doc/kttsd/festivalintconf.pngbin0 -> 90661 bytes
-rw-r--r--doc/kttsd/filters.pngbin0 -> 40562 bytes
-rw-r--r--doc/kttsd/general.pngbin0 -> 93998 bytes
-rw-r--r--doc/kttsd/index.docbook2834
-rw-r--r--doc/kttsd/interruption.pngbin0 -> 29528 bytes
-rw-r--r--doc/kttsd/jobs.pngbin0 -> 134666 bytes
-rw-r--r--doc/kttsd/notifications.pngbin0 -> 152284 bytes
-rw-r--r--doc/kttsd/selecttalker.pngbin0 -> 94783 bytes
-rw-r--r--doc/kttsd/stringreplacer.pngbin0 -> 33895 bytes
-rw-r--r--doc/kttsd/talkerchooser.pngbin0 -> 79740 bytes
-rw-r--r--doc/kttsd/talkers.pngbin0 -> 108124 bytes
-rw-r--r--doc/kttsd/xmltransformer.pngbin0 -> 83431 bytes
-rw-r--r--kbstateapplet/Makefile.am24
-rw-r--r--kbstateapplet/configure.in.in23
-rw-r--r--kbstateapplet/images/Makefile.am2
-rw-r--r--kbstateapplet/images/cr16-action-altkey.pngbin0 -> 150 bytes
-rw-r--r--kbstateapplet/images/cr16-action-capskey.pngbin0 -> 206 bytes
-rw-r--r--kbstateapplet/images/cr16-action-controlkey.pngbin0 -> 191 bytes
-rw-r--r--kbstateapplet/images/cr16-action-hyperkey.pngbin0 -> 152 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_mouse.pngbin0 -> 223 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_mouse_left.pngbin0 -> 117 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_mouse_left_selected.pngbin0 -> 142 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_mouse_mid.pngbin0 -> 104 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_mouse_mid_selected.pngbin0 -> 128 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_mouse_right.pngbin0 -> 111 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_mouse_right_selected.pngbin0 -> 141 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_slowkeys.pngbin0 -> 226 bytes
-rw-r--r--kbstateapplet/images/cr16-action-kbstate_stickykeys.pngbin0 -> 188 bytes
-rw-r--r--kbstateapplet/images/cr16-action-key.pngbin0 -> 75 bytes
-rw-r--r--kbstateapplet/images/cr16-action-keypressno.pngbin0 -> 233 bytes
-rw-r--r--kbstateapplet/images/cr16-action-keypressok.pngbin0 -> 256 bytes
-rw-r--r--kbstateapplet/images/cr16-action-lockkey.pngbin0 -> 193 bytes
-rw-r--r--kbstateapplet/images/cr16-action-metakey.pngbin0 -> 180 bytes
-rw-r--r--kbstateapplet/images/cr16-action-shiftkey.pngbin0 -> 210 bytes
-rw-r--r--kbstateapplet/images/cr16-action-superkey.pngbin0 -> 183 bytes
-rw-r--r--kbstateapplet/images/cr16-action-unlatched.pngbin0 -> 75 bytes
-rw-r--r--kbstateapplet/images/cr22-action-altkey.pngbin0 -> 153 bytes
-rw-r--r--kbstateapplet/images/cr22-action-capskey.pngbin0 -> 216 bytes
-rw-r--r--kbstateapplet/images/cr22-action-controlkey.pngbin0 -> 205 bytes
-rw-r--r--kbstateapplet/images/cr22-action-hyperkey.pngbin0 -> 161 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_mouse.pngbin0 -> 334 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_mouse_left.pngbin0 -> 121 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_mouse_left_selected.pngbin0 -> 166 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_mouse_mid.pngbin0 -> 119 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_mouse_mid_selected.pngbin0 -> 143 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_mouse_right.pngbin0 -> 115 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_mouse_right_selected.pngbin0 -> 175 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_slowkeys.pngbin0 -> 271 bytes
-rw-r--r--kbstateapplet/images/cr22-action-kbstate_stickykeys.pngbin0 -> 209 bytes
-rw-r--r--kbstateapplet/images/cr22-action-key.pngbin0 -> 80 bytes
-rw-r--r--kbstateapplet/images/cr22-action-keypressno.pngbin0 -> 228 bytes
-rw-r--r--kbstateapplet/images/cr22-action-keypressok.pngbin0 -> 349 bytes
-rw-r--r--kbstateapplet/images/cr22-action-lockkey.pngbin0 -> 202 bytes
-rw-r--r--kbstateapplet/images/cr22-action-metakey.pngbin0 -> 199 bytes
-rw-r--r--kbstateapplet/images/cr22-action-shiftkey.pngbin0 -> 217 bytes
-rw-r--r--kbstateapplet/images/cr22-action-superkey.pngbin0 -> 187 bytes
-rw-r--r--kbstateapplet/images/cr22-action-unlatched.pngbin0 -> 80 bytes
-rw-r--r--kbstateapplet/images/cr32-action-altkey.pngbin0 -> 162 bytes
-rw-r--r--kbstateapplet/images/cr32-action-capskey.pngbin0 -> 258 bytes
-rw-r--r--kbstateapplet/images/cr32-action-controlkey.pngbin0 -> 239 bytes
-rw-r--r--kbstateapplet/images/cr32-action-hyperkey.pngbin0 -> 168 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_mouse.pngbin0 -> 430 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_mouse_left.pngbin0 -> 155 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_mouse_left_selected.pngbin0 -> 187 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_mouse_mid.pngbin0 -> 144 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_mouse_mid_selected.pngbin0 -> 109 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_mouse_right.pngbin0 -> 156 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_mouse_right_selected.pngbin0 -> 199 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_slowkeys.pngbin0 -> 392 bytes
-rw-r--r--kbstateapplet/images/cr32-action-kbstate_stickykeys.pngbin0 -> 254 bytes
-rw-r--r--kbstateapplet/images/cr32-action-key.pngbin0 -> 83 bytes
-rw-r--r--kbstateapplet/images/cr32-action-keypressno.pngbin0 -> 215 bytes
-rw-r--r--kbstateapplet/images/cr32-action-keypressok.pngbin0 -> 521 bytes
-rw-r--r--kbstateapplet/images/cr32-action-lockkey.pngbin0 -> 240 bytes
-rw-r--r--kbstateapplet/images/cr32-action-metakey.pngbin0 -> 228 bytes
-rw-r--r--kbstateapplet/images/cr32-action-shiftkey.pngbin0 -> 259 bytes
-rw-r--r--kbstateapplet/images/cr32-action-superkey.pngbin0 -> 197 bytes
-rw-r--r--kbstateapplet/images/cr32-action-unlatched.pngbin0 -> 83 bytes
-rw-r--r--kbstateapplet/images/cr48-action-altkey.pngbin0 -> 170 bytes
-rw-r--r--kbstateapplet/images/cr48-action-capskey.pngbin0 -> 319 bytes
-rw-r--r--kbstateapplet/images/cr48-action-controlkey.pngbin0 -> 246 bytes
-rw-r--r--kbstateapplet/images/cr48-action-hyperkey.pngbin0 -> 178 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_mouse.pngbin0 -> 726 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_mouse_left.pngbin0 -> 189 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_mouse_left_selected.pngbin0 -> 238 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_mouse_mid.pngbin0 -> 186 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_mouse_mid_selected.pngbin0 -> 128 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_mouse_right.pngbin0 -> 193 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_mouse_right_selected.pngbin0 -> 244 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_slowkeys.pngbin0 -> 944 bytes
-rw-r--r--kbstateapplet/images/cr48-action-kbstate_stickykeys.pngbin0 -> 301 bytes
-rw-r--r--kbstateapplet/images/cr48-action-key.pngbin0 -> 88 bytes
-rw-r--r--kbstateapplet/images/cr48-action-keypressno.pngbin0 -> 269 bytes
-rw-r--r--kbstateapplet/images/cr48-action-keypressok.pngbin0 -> 784 bytes
-rw-r--r--kbstateapplet/images/cr48-action-lockkey.pngbin0 -> 279 bytes
-rw-r--r--kbstateapplet/images/cr48-action-metakey.pngbin0 -> 286 bytes
-rw-r--r--kbstateapplet/images/cr48-action-shiftkey.pngbin0 -> 296 bytes
-rw-r--r--kbstateapplet/images/cr48-action-superkey.pngbin0 -> 220 bytes
-rw-r--r--kbstateapplet/images/cr48-action-unlatched.pngbin0 -> 88 bytes
-rw-r--r--kbstateapplet/images/cr64-action-altkey.pngbin0 -> 173 bytes
-rw-r--r--kbstateapplet/images/cr64-action-capskey.pngbin0 -> 336 bytes
-rw-r--r--kbstateapplet/images/cr64-action-controlkey.pngbin0 -> 272 bytes
-rw-r--r--kbstateapplet/images/cr64-action-hyperkey.pngbin0 -> 181 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_mouse.pngbin0 -> 856 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_mouse_left.pngbin0 -> 204 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_mouse_left_selected.pngbin0 -> 228 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_mouse_mid.pngbin0 -> 205 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_mouse_mid_selected.pngbin0 -> 146 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_mouse_right.pngbin0 -> 209 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_mouse_right_selected.pngbin0 -> 263 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_slowkeys.pngbin0 -> 994 bytes
-rw-r--r--kbstateapplet/images/cr64-action-kbstate_stickykeys.pngbin0 -> 360 bytes
-rw-r--r--kbstateapplet/images/cr64-action-key.pngbin0 -> 96 bytes
-rw-r--r--kbstateapplet/images/cr64-action-keypressno.pngbin0 -> 337 bytes
-rw-r--r--kbstateapplet/images/cr64-action-keypressok.pngbin0 -> 1000 bytes
-rw-r--r--kbstateapplet/images/cr64-action-lockkey.pngbin0 -> 311 bytes
-rw-r--r--kbstateapplet/images/cr64-action-metakey.pngbin0 -> 348 bytes
-rw-r--r--kbstateapplet/images/cr64-action-shiftkey.pngbin0 -> 316 bytes
-rw-r--r--kbstateapplet/images/cr64-action-superkey.pngbin0 -> 236 bytes
-rw-r--r--kbstateapplet/images/cr64-action-unlatched.pngbin0 -> 96 bytes
-rw-r--r--kbstateapplet/images/crsc-action-altkey.svg7
-rw-r--r--kbstateapplet/images/crsc-action-capskey.svg7
-rw-r--r--kbstateapplet/images/crsc-action-controlkey.svg7
-rw-r--r--kbstateapplet/images/crsc-action-hyperkey.svg11
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_mouse.svg13
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_mouse_left.svg7
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_mouse_left_selected.svg7
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_mouse_mid.svg7
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_mouse_mid_selected.svg7
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_mouse_right.svg7
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_mouse_right_selected.svg7
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_slowkeys.svg9
-rw-r--r--kbstateapplet/images/crsc-action-kbstate_stickykeys.svg9
-rw-r--r--kbstateapplet/images/crsc-action-key.svg5
-rw-r--r--kbstateapplet/images/crsc-action-keypressno.svg9
-rw-r--r--kbstateapplet/images/crsc-action-keypressok.svg7
-rw-r--r--kbstateapplet/images/crsc-action-lockkey.svg7
-rw-r--r--kbstateapplet/images/crsc-action-metakey.svg7
-rw-r--r--kbstateapplet/images/crsc-action-shiftkey.svg7
-rw-r--r--kbstateapplet/images/crsc-action-superkey.svg17
-rw-r--r--kbstateapplet/images/crsc-action-unlatched.svg5
-rw-r--r--kbstateapplet/kbstate.cpp1079
-rw-r--r--kbstateapplet/kbstate.h200
-rw-r--r--kbstateapplet/kbstateapplet.desktop101
-rw-r--r--kbstateapplet/kdeexportfix.h22
-rw-r--r--kdeaccessibility.lsm15
-rw-r--r--kmag/AUTHORS9
-rw-r--r--kmag/COPYING280
-rw-r--r--kmag/ChangeLog63
-rw-r--r--kmag/INSTALL184
-rw-r--r--kmag/Makefile.am40
-rw-r--r--kmag/README8
-rw-r--r--kmag/TODO57
-rw-r--r--kmag/hi16-action-followmouse.pngbin0 -> 774 bytes
-rw-r--r--kmag/hi16-action-hidemouse.pngbin0 -> 308 bytes
-rw-r--r--kmag/hi16-action-window.pngbin0 -> 469 bytes
-rw-r--r--kmag/hi16-app-kmag.pngbin0 -> 359 bytes
-rw-r--r--kmag/hi32-app-kmag.pngbin0 -> 354 bytes
-rw-r--r--kmag/kmag.cpp958
-rw-r--r--kmag/kmag.desktop76
-rw-r--r--kmag/kmag.h237
-rw-r--r--kmag/kmag.kdevprj230
-rw-r--r--kmag/kmag.lsm14
-rw-r--r--kmag/kmag.mdk.spec108
-rw-r--r--kmag/kmagselrect.cpp385
-rw-r--r--kmag/kmagselrect.h146
-rw-r--r--kmag/kmagui.rc109
-rw-r--r--kmag/kmagzoomview.cpp927
-rw-r--r--kmag/kmagzoomview.h249
-rw-r--r--kmag/lo16-app-kmag.pngbin0 -> 359 bytes
-rw-r--r--kmag/lo32-app-kmag.pngbin0 -> 354 bytes
-rw-r--r--kmag/main.cpp81
-rw-r--r--kmag/version.h8
-rw-r--r--kmousetool/AUTHORS24
-rw-r--r--kmousetool/COPYING340
-rw-r--r--kmousetool/ChangeLog9
-rw-r--r--kmousetool/INSTALL167
-rw-r--r--kmousetool/Makefile.am1
-rw-r--r--kmousetool/README83
-rw-r--r--kmousetool/TODO10
-rw-r--r--kmousetool/kmousetool.lsm14
-rw-r--r--kmousetool/kmousetool/Makefile.am29
-rw-r--r--kmousetool/kmousetool/Xmd_kmousetool.h201
-rw-r--r--kmousetool/kmousetool/kmousetool.cpp641
-rw-r--r--kmousetool/kmousetool/kmousetool.desktop138
-rw-r--r--kmousetool/kmousetool/kmousetool.h209
-rw-r--r--kmousetool/kmousetool/kmousetoolui.ui422
-rw-r--r--kmousetool/kmousetool/main.cpp79
-rw-r--r--kmousetool/kmousetool/mousetool_tap.wavbin0 -> 1424 bytes
-rw-r--r--kmousetool/kmousetool/mtstroke.cpp288
-rw-r--r--kmousetool/kmousetool/mtstroke.h103
-rw-r--r--kmousetool/kmousetool/pics/Makefile.am3
-rw-r--r--kmousetool/kmousetool/pics/hi16-action-kmousetool_off.pngbin0 -> 360 bytes
-rw-r--r--kmousetool/kmousetool/pics/hi16-action-kmousetool_on.pngbin0 -> 346 bytes
-rw-r--r--kmousetool/kmousetool/pics/hi16-app-kmousetool.pngbin0 -> 290 bytes
-rw-r--r--kmousetool/kmousetool/pics/hi32-action-kmousetool_off.pngbin0 -> 448 bytes
-rw-r--r--kmousetool/kmousetool/pics/hi32-action-kmousetool_on.pngbin0 -> 384 bytes
-rw-r--r--kmousetool/kmousetool/pics/hi32-app-kmousetool.pngbin0 -> 325 bytes
-rw-r--r--kmousetool/kmousetool/version.h8
-rw-r--r--kmouth/AUTHORS2
-rw-r--r--kmouth/Makefile.am32
-rw-r--r--kmouth/books/Makefile.am9
-rw-r--r--kmouth/books/de-courteousness.phrasebook13
-rw-r--r--kmouth/books/de-greetings.phrasebook17
-rw-r--r--kmouth/books/de-howareyou.phrasebook13
-rw-r--r--kmouth/books/de-personal.phrasebook10
-rw-r--r--kmouth/books/de.desktop60
-rw-r--r--kmouth/books/en-courteousness.phrasebook15
-rw-r--r--kmouth/books/en-greetings.phrasebook15
-rw-r--r--kmouth/books/en-howareyou.phrasebook12
-rw-r--r--kmouth/books/en-personal.phrasebook10
-rw-r--r--kmouth/books/en.desktop61
-rw-r--r--kmouth/books/nl-courteousness.phrasebook13
-rw-r--r--kmouth/books/nl-greetings.phrasebook14
-rw-r--r--kmouth/books/nl-howareyou.phrasebook12
-rw-r--r--kmouth/books/nl-personal.phrasebook9
-rw-r--r--kmouth/books/nl.desktop50
-rw-r--r--kmouth/books/sv-courteousness.phrasebook12
-rw-r--r--kmouth/books/sv-greetings.phrasebook14
-rw-r--r--kmouth/books/sv-howareyou.phrasebook12
-rw-r--r--kmouth/books/sv-personal.phrasebook10
-rw-r--r--kmouth/books/sv.desktop61
-rw-r--r--kmouth/configwizard.cpp144
-rw-r--r--kmouth/configwizard.h59
-rw-r--r--kmouth/icons/Makefile.am11
-rw-r--r--kmouth/icons/app/Makefile.am1
-rw-r--r--kmouth/icons/app/hi16-app-kmouth.pngbin0 -> 219 bytes
-rw-r--r--kmouth/icons/app/hi22-app-kmouth.pngbin0 -> 285 bytes
-rw-r--r--kmouth/icons/app/hi32-app-kmouth.pngbin0 -> 383 bytes
-rw-r--r--kmouth/icons/app/hi48-app-kmouth.pngbin0 -> 563 bytes
-rw-r--r--kmouth/icons/app/lo16-app-kmouth.pngbin0 -> 219 bytes
-rw-r--r--kmouth/icons/app/lo22-app-kmouth.pngbin0 -> 285 bytes
-rw-r--r--kmouth/icons/app/lo32-app-kmouth.pngbin0 -> 383 bytes
-rw-r--r--kmouth/icons/hi16-action-speak.pngbin0 -> 219 bytes
-rw-r--r--kmouth/icons/hi22-action-speak.pngbin0 -> 285 bytes
-rw-r--r--kmouth/icons/hi32-action-speak.pngbin0 -> 383 bytes
-rw-r--r--kmouth/icons/hi48-action-speak.pngbin0 -> 563 bytes
-rw-r--r--kmouth/icons/history/Makefile.am9
-rw-r--r--kmouth/icons/history/hi16-action-phrasehistory_open.pngbin0 -> 765 bytes
-rw-r--r--kmouth/icons/history/hi16-action-phrasehistory_print.pngbin0 -> 914 bytes
-rw-r--r--kmouth/icons/history/hi16-action-phrasehistory_save.pngbin0 -> 893 bytes
-rw-r--r--kmouth/icons/history/hi22-action-phrasehistory_open.pngbin0 -> 1544 bytes
-rw-r--r--kmouth/icons/history/hi22-action-phrasehistory_print.pngbin0 -> 1608 bytes
-rw-r--r--kmouth/icons/history/hi22-action-phrasehistory_save.pngbin0 -> 1628 bytes
-rw-r--r--kmouth/icons/history/hi32-action-phrasehistory_open.pngbin0 -> 1923 bytes
-rw-r--r--kmouth/icons/history/hi32-action-phrasehistory_print.pngbin0 -> 2099 bytes
-rw-r--r--kmouth/icons/history/hi32-action-phrasehistory_save.pngbin0 -> 2147 bytes
-rw-r--r--kmouth/icons/phrase/Makefile.am9
-rw-r--r--kmouth/icons/phrase/hi16-action-phrase.pngbin0 -> 382 bytes
-rw-r--r--kmouth/icons/phrase/hi16-action-phrase_new.pngbin0 -> 454 bytes
-rw-r--r--kmouth/icons/phrase/hi16-action-phrase_open.pngbin0 -> 520 bytes
-rw-r--r--kmouth/icons/phrase/hi16-action-phrase_save.pngbin0 -> 705 bytes
-rw-r--r--kmouth/icons/phrase/hi22-action-phrase.pngbin0 -> 713 bytes
-rw-r--r--kmouth/icons/phrase/hi22-action-phrase_new.pngbin0 -> 803 bytes
-rw-r--r--kmouth/icons/phrase/hi22-action-phrase_open.pngbin0 -> 966 bytes
-rw-r--r--kmouth/icons/phrase/hi22-action-phrase_save.pngbin0 -> 1122 bytes
-rw-r--r--kmouth/icons/phrase/hi32-action-phrase.pngbin0 -> 1479 bytes
-rw-r--r--kmouth/icons/phrase/hi32-action-phrase_new.pngbin0 -> 1515 bytes
-rw-r--r--kmouth/icons/phrase/hi32-action-phrase_open.pngbin0 -> 1934 bytes
-rw-r--r--kmouth/icons/phrase/hi32-action-phrase_save.pngbin0 -> 2021 bytes
-rw-r--r--kmouth/icons/phrasebook/Makefile.am9
-rw-r--r--kmouth/icons/phrasebook/hi16-action-phrasebook.pngbin0 -> 549 bytes
-rw-r--r--kmouth/icons/phrasebook/hi16-action-phrasebook_closed.pngbin0 -> 538 bytes
-rw-r--r--kmouth/icons/phrasebook/hi16-action-phrasebook_new.pngbin0 -> 569 bytes
-rw-r--r--kmouth/icons/phrasebook/hi16-action-phrasebook_open.pngbin0 -> 621 bytes
-rw-r--r--kmouth/icons/phrasebook/hi16-action-phrasebook_save.pngbin0 -> 720 bytes
-rw-r--r--kmouth/icons/phrasebook/hi22-action-phrasebook.pngbin0 -> 1110 bytes
-rw-r--r--kmouth/icons/phrasebook/hi22-action-phrasebook_closed.pngbin0 -> 796 bytes
-rw-r--r--kmouth/icons/phrasebook/hi22-action-phrasebook_new.pngbin0 -> 1144 bytes
-rw-r--r--kmouth/icons/phrasebook/hi22-action-phrasebook_open.pngbin0 -> 1118 bytes
-rw-r--r--kmouth/icons/phrasebook/hi22-action-phrasebook_save.pngbin0 -> 1217 bytes
-rw-r--r--kmouth/icons/phrasebook/hi32-action-phrasebook.pngbin0 -> 1573 bytes
-rw-r--r--kmouth/icons/phrasebook/hi32-action-phrasebook_closed.pngbin0 -> 1160 bytes
-rw-r--r--kmouth/icons/phrasebook/hi32-action-phrasebook_new.pngbin0 -> 1627 bytes
-rw-r--r--kmouth/icons/phrasebook/hi32-action-phrasebook_open.pngbin0 -> 1967 bytes
-rw-r--r--kmouth/icons/phrasebook/hi32-action-phrasebook_save.pngbin0 -> 2127 bytes
-rw-r--r--kmouth/kmouth.cpp484
-rw-r--r--kmouth/kmouth.desktop80
-rw-r--r--kmouth/kmouth.h187
-rw-r--r--kmouth/kmouth.lsm14
-rw-r--r--kmouth/kmouthrc9
-rw-r--r--kmouth/kmouthui.rc93
-rw-r--r--kmouth/main.cpp73
-rw-r--r--kmouth/optionsdialog.cpp238
-rw-r--r--kmouth/optionsdialog.h88
-rw-r--r--kmouth/phrasebook/Makefile.am16
-rw-r--r--kmouth/phrasebook/buttonboxui.ui107
-rw-r--r--kmouth/phrasebook/phrasebook.cpp512
-rw-r--r--kmouth/phrasebook/phrasebook.h195
-rw-r--r--kmouth/phrasebook/phrasebookdialog.cpp758
-rw-r--r--kmouth/phrasebook/phrasebookdialog.h234
-rw-r--r--kmouth/phrasebook/phrasebookdialogui.rc64
-rw-r--r--kmouth/phrasebook/phrasebookparser.cpp112
-rw-r--r--kmouth/phrasebook/phrasebookparser.h73
-rw-r--r--kmouth/phrasebook/phrasetree.cpp556
-rw-r--r--kmouth/phrasebook/phrasetree.h108
-rw-r--r--kmouth/phraseedit.cpp57
-rw-r--r--kmouth/phraseedit.h36
-rw-r--r--kmouth/phraselist.cpp478
-rw-r--r--kmouth/phraselist.h110
-rw-r--r--kmouth/phraselistitem.cpp52
-rw-r--r--kmouth/phraselistitem.h43
-rw-r--r--kmouth/preferencesui.ui162
-rw-r--r--kmouth/speech.cpp242
-rw-r--r--kmouth/speech.h72
-rw-r--r--kmouth/texttospeechconfigurationui.ui170
-rw-r--r--kmouth/texttospeechconfigurationwidget.cpp86
-rw-r--r--kmouth/texttospeechconfigurationwidget.h51
-rw-r--r--kmouth/texttospeechsystem.cpp114
-rw-r--r--kmouth/texttospeechsystem.h55
-rw-r--r--kmouth/version.h8
-rw-r--r--kmouth/wordcompletion/Makefile.am13
-rw-r--r--kmouth/wordcompletion/creationsourcedetailsui.ui184
-rw-r--r--kmouth/wordcompletion/creationsourcedetailsui.ui.h37
-rw-r--r--kmouth/wordcompletion/creationsourceui.ui179
-rw-r--r--kmouth/wordcompletion/creationsourceui.ui.h26
-rw-r--r--kmouth/wordcompletion/dictionarycreationwizard.cpp376
-rw-r--r--kmouth/wordcompletion/dictionarycreationwizard.h110
-rw-r--r--kmouth/wordcompletion/kdedocsourceui.ui101
-rw-r--r--kmouth/wordcompletion/kdedocsourceui.ui.h19
-rw-r--r--kmouth/wordcompletion/klanguagebutton.cpp238
-rw-r--r--kmouth/wordcompletion/klanguagebutton.h93
-rw-r--r--kmouth/wordcompletion/klanguagebuttonhelper.cpp64
-rw-r--r--kmouth/wordcompletion/klanguagebuttonhelper.h28
-rw-r--r--kmouth/wordcompletion/wordcompletion.cpp224
-rw-r--r--kmouth/wordcompletion/wordcompletion.h77
-rw-r--r--kmouth/wordcompletion/wordcompletionui.ui293
-rw-r--r--kmouth/wordcompletion/wordcompletionui.ui.h35
-rw-r--r--kmouth/wordcompletion/wordcompletionwidget.cpp325
-rw-r--r--kmouth/wordcompletion/wordcompletionwidget.h80
-rw-r--r--kmouth/wordcompletion/wordlist.cpp550
-rw-r--r--kmouth/wordcompletion/wordlist.h92
-rw-r--r--ksayit/AUTHORS1
-rw-r--r--ksayit/COPYING340
-rw-r--r--ksayit/ChangeLog1
-rw-r--r--ksayit/DocBook.README76
-rw-r--r--ksayit/Doxyfile248
-rw-r--r--ksayit/Freeverb_plugin/Makefile.am13
-rw-r--r--ksayit/Freeverb_plugin/configure.in.in17
-rw-r--r--ksayit/Freeverb_plugin/freeverb_setup.ui668
-rw-r--r--ksayit/Freeverb_plugin/freeverbsetupimpl.cpp116
-rw-r--r--ksayit/Freeverb_plugin/freeverbsetupimpl.h62
-rw-r--r--ksayit/Freeverb_plugin/kdeexportfix.h22
-rw-r--r--ksayit/Freeverb_plugin/ksayit_libFreeverb.desktop52
-rw-r--r--ksayit/Freeverb_plugin/ksayit_libFreeverb_service.desktop48
-rw-r--r--ksayit/Freeverb_plugin/ksayitfreeverblib.cpp164
-rw-r--r--ksayit/Freeverb_plugin/ksayitfreeverblib.h96
-rw-r--r--ksayit/INSTALL167
-rw-r--r--ksayit/KTTSD_Lib/KTTSDlibSetup.ui121
-rw-r--r--ksayit/KTTSD_Lib/Makefile.am23
-rw-r--r--ksayit/KTTSD_Lib/kdeexportfix.h22
-rw-r--r--ksayit/KTTSD_Lib/kttsdlib.cpp221
-rw-r--r--ksayit/KTTSD_Lib/kttsdlib.h119
-rw-r--r--ksayit/KTTSD_Lib/kttsdlibsetupimpl.cpp76
-rw-r--r--ksayit/KTTSD_Lib/kttsdlibsetupimpl.h46
-rw-r--r--ksayit/KTTSD_Lib/kttsdlibtalker2.cpp166
-rw-r--r--ksayit/KTTSD_Lib/kttsdlibtalker2.h101
-rw-r--r--ksayit/Makefile.am5
-rw-r--r--ksayit/NEWS1
-rw-r--r--ksayit/README1
-rw-r--r--ksayit/TODO1
-rw-r--r--ksayit/configure.in.in16
-rw-r--r--ksayit/ksayit.kdevelop196
-rw-r--r--ksayit/src/ContextMenus.xml100
-rw-r--r--ksayit/src/DocTreeView.ui158
-rw-r--r--ksayit/src/DocTreeView.ui.h132
-rw-r--r--ksayit/src/KSayItView.ui69
-rw-r--r--ksayit/src/Makefile.am45
-rw-r--r--ksayit/src/Types.h83
-rw-r--r--ksayit/src/contextmenuhandler.cpp407
-rw-r--r--ksayit/src/contextmenuhandler.h152
-rw-r--r--ksayit/src/docbookclasses.cpp1056
-rw-r--r--ksayit/src/docbookclasses.h344
-rw-r--r--ksayit/src/docbookgenerator.cpp483
-rw-r--r--ksayit/src/docbookgenerator.h71
-rw-r--r--ksayit/src/docbookparser.cpp493
-rw-r--r--ksayit/src/docbookparser.h64
-rw-r--r--ksayit/src/doctreeviewimpl.cpp1141
-rw-r--r--ksayit/src/doctreeviewimpl.h191
-rw-r--r--ksayit/src/effectstack.cpp65
-rw-r--r--ksayit/src/effectstack.h57
-rw-r--r--ksayit/src/fx_setup.ui252
-rw-r--r--ksayit/src/fxpluginhandler.cpp239
-rw-r--r--ksayit/src/fxpluginhandler.h99
-rw-r--r--ksayit/src/fxsetupimpl.cpp159
-rw-r--r--ksayit/src/fxsetupimpl.h90
-rw-r--r--ksayit/src/hi16-app-ksayit.pngbin0 -> 818 bytes
-rw-r--r--ksayit/src/hi32-app-ksayit.pngbin0 -> 1977 bytes
-rw-r--r--ksayit/src/hi32-app-ksayit_clipempty.pngbin0 -> 2202 bytes
-rw-r--r--ksayit/src/hi32-app-ksayit_talking.pngbin0 -> 4254 bytes
-rw-r--r--ksayit/src/ksayit.cpp908
-rw-r--r--ksayit/src/ksayit.desktop64
-rw-r--r--ksayit/src/ksayit.h364
-rw-r--r--ksayit/src/ksayit_fxplugin.h88
-rw-r--r--ksayit/src/ksayit_ttsplugin.h166
-rw-r--r--ksayit/src/ksayitbookmarkhandler.cpp238
-rw-r--r--ksayit/src/ksayitbookmarkhandler.h120
-rw-r--r--ksayit/src/ksayitsystemtray.cpp356
-rw-r--r--ksayit/src/ksayitsystemtray.h228
-rw-r--r--ksayit/src/ksayitui.rc38
-rw-r--r--ksayit/src/ksayitviewimpl.cpp115
-rw-r--r--ksayit/src/ksayitviewimpl.h97
-rw-r--r--ksayit/src/main.cpp62
-rw-r--r--ksayit/src/parasaxparser.cpp96
-rw-r--r--ksayit/src/parasaxparser.h77
-rw-r--r--ksayit/src/saxhandler.cpp187
-rw-r--r--ksayit/src/saxhandler.h87
-rw-r--r--ksayit/src/version.h23
-rw-r--r--ksayit/src/voicesetupdlg.cpp145
-rw-r--r--ksayit/src/voicesetupdlg.h90
-rw-r--r--kttsd/AUTHORS5
-rw-r--r--kttsd/ChangeLog609
-rw-r--r--kttsd/Makefile.am19
-rw-r--r--kttsd/README166
-rw-r--r--kttsd/README.kttsd10
-rw-r--r--kttsd/TODO95
-rw-r--r--kttsd/TODO.french31
-rw-r--r--kttsd/app-plugins/Makefile.am1
-rw-r--r--kttsd/app-plugins/kate/Makefile.am19
-rw-r--r--kttsd/app-plugins/kate/katekttsd.cpp120
-rw-r--r--kttsd/app-plugins/kate/katekttsd.h57
-rw-r--r--kttsd/app-plugins/kate/ktexteditor_kttsd.desktop104
-rw-r--r--kttsd/app-plugins/kate/ktexteditor_kttsdui.rc11
-rwxr-xr-xkttsd/clean_obsolete.sh105
-rw-r--r--kttsd/compat/Makefile.am3
-rw-r--r--kttsd/compat/README_COMPAT6
-rw-r--r--kttsd/compat/icons/Makefile.am1
-rw-r--r--kttsd/compat/icons/cr128-app-kttsd.pngbin0 -> 23932 bytes
-rw-r--r--kttsd/compat/icons/cr16-app-kttsd.pngbin0 -> 965 bytes
-rw-r--r--kttsd/compat/icons/cr22-app-kttsd.pngbin0 -> 1509 bytes
-rw-r--r--kttsd/compat/icons/cr32-app-kttsd.pngbin0 -> 2688 bytes
-rw-r--r--kttsd/compat/icons/cr48-app-kttsd.pngbin0 -> 5039 bytes
-rw-r--r--kttsd/compat/icons/cr64-app-kttsd.pngbin0 -> 7877 bytes
-rw-r--r--kttsd/compat/icons/crsc-app-kttsd.svgzbin0 -> 17596 bytes
-rw-r--r--kttsd/compat/interfaces/Makefile.am1
-rw-r--r--kttsd/compat/interfaces/kspeech/Makefile.am8
-rw-r--r--kttsd/compat/interfaces/kspeech/dcoptexttospeech.desktop52
-rw-r--r--kttsd/compat/interfaces/kspeech/kspeech.h1285
-rw-r--r--kttsd/compat/interfaces/kspeech/kspeechsink.h164
-rw-r--r--kttsd/configure.in.bot65
-rw-r--r--kttsd/configure.in.in304
-rwxr-xr-xkttsd/cvs2dist634
-rw-r--r--kttsd/debian/TODO36
-rw-r--r--kttsd/debian/changelog5
-rw-r--r--kttsd/debian/compat1
-rw-r--r--kttsd/debian/control40
-rw-r--r--kttsd/debian/copyright33
-rw-r--r--kttsd/debian/dirs1
-rw-r--r--kttsd/debian/docs2
-rw-r--r--kttsd/debian/kttsd-gstreamer.install3
-rw-r--r--kttsd/debian/kttsd.install107
-rw-r--r--kttsd/debian/kttsd.manpages2
-rw-r--r--kttsd/debian/kttsmgr.menu6
-rw-r--r--kttsd/debian/man/kttsd.1159
-rw-r--r--kttsd/debian/man/kttsmgr.1157
-rw-r--r--kttsd/debian/man/manpages.in2
-rwxr-xr-xkttsd/debian/rules5
-rw-r--r--kttsd/debian/shlibs.kttsd2
-rw-r--r--kttsd/filters/Makefile.am26
-rw-r--r--kttsd/filters/kttsd_filterplugin.desktop6
-rw-r--r--kttsd/filters/main.cpp140
-rw-r--r--kttsd/filters/sbd/Makefile.am27
-rw-r--r--kttsd/filters/sbd/kttsd_sbdplugin.desktop91
-rw-r--r--kttsd/filters/sbd/polish_festival_sbdrc6
-rw-r--r--kttsd/filters/sbd/sbdconf.cpp341
-rw-r--r--kttsd/filters/sbd/sbdconf.h139
-rw-r--r--kttsd/filters/sbd/sbdconfwidget.ui363
-rw-r--r--kttsd/filters/sbd/sbdplugin.cpp33
-rw-r--r--kttsd/filters/sbd/sbdproc.cpp784
-rw-r--r--kttsd/filters/sbd/sbdproc.h366
-rw-r--r--kttsd/filters/sbd/standard_sbdrc6
-rw-r--r--kttsd/filters/stringreplacer/Makefile.am34
-rw-r--r--kttsd/filters/stringreplacer/abbreviations.xml58
-rw-r--r--kttsd/filters/stringreplacer/chat-de.xml616
-rw-r--r--kttsd/filters/stringreplacer/chat.xml616
-rw-r--r--kttsd/filters/stringreplacer/editreplacementwidget.ui263
-rw-r--r--kttsd/filters/stringreplacer/emoticons.xml304
-rw-r--r--kttsd/filters/stringreplacer/festival_unspeakable_chars.xml94
-rw-r--r--kttsd/filters/stringreplacer/kmail.xml31
-rw-r--r--kttsd/filters/stringreplacer/kttsd_stringreplacerplugin.desktop92
-rw-r--r--kttsd/filters/stringreplacer/polish_festival_fixes.xml12
-rw-r--r--kttsd/filters/stringreplacer/polish_festival_unspeakables.xml78
-rw-r--r--kttsd/filters/stringreplacer/qt2plaintext.xml359
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerconf.cpp725
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerconf.h158
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerconfwidget.ui474
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerplugin.cpp32
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerproc.cpp231
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerproc.h97
-rw-r--r--kttsd/filters/talkerchooser/Makefile.am25
-rw-r--r--kttsd/filters/talkerchooser/female_notifications_rc10
-rw-r--r--kttsd/filters/talkerchooser/kttsd_talkerchooserplugin.desktop89
-rw-r--r--kttsd/filters/talkerchooser/talkerchooserconf.cpp269
-rw-r--r--kttsd/filters/talkerchooser/talkerchooserconf.h134
-rw-r--r--kttsd/filters/talkerchooser/talkerchooserconfwidget.ui319
-rw-r--r--kttsd/filters/talkerchooser/talkerchooserplugin.cpp32
-rw-r--r--kttsd/filters/talkerchooser/talkerchooserproc.cpp148
-rw-r--r--kttsd/filters/talkerchooser/talkerchooserproc.h87
-rw-r--r--kttsd/filters/xhtml2ssml/Doxyfile266
-rw-r--r--kttsd/filters/xhtml2ssml/demonstration.html5
-rw-r--r--kttsd/filters/xhtml2ssml/main.cpp22
-rw-r--r--kttsd/filters/xhtml2ssml/tagmappingrc5
-rw-r--r--kttsd/filters/xhtml2ssml/xhtml2ssml.cpp105
-rw-r--r--kttsd/filters/xhtml2ssml/xhtml2ssml.h61
-rw-r--r--kttsd/filters/xhtml2ssml/xhtml2ssml.kdevelop112
-rw-r--r--kttsd/filters/xhtml2ssml/xhtml2ssml.kdevelop.pcsbin0 -> 14766 bytes
-rw-r--r--kttsd/filters/xhtml2ssml/xhtml2ssml.kdevses38
-rw-r--r--kttsd/filters/xhtml2ssml/xhtml2ssml.pro10
-rw-r--r--kttsd/filters/xhtml2ssml/xmlelement.cpp102
-rw-r--r--kttsd/filters/xhtml2ssml/xmlelement.h91
-rw-r--r--kttsd/filters/xmltransformer/Makefile.am24
-rw-r--r--kttsd/filters/xmltransformer/kttsd_xmltransformerplugin.desktop88
-rw-r--r--kttsd/filters/xmltransformer/xhtml2ssml.xsl252
-rw-r--r--kttsd/filters/xmltransformer/xhtml2ssml_simple.xsl95
-rw-r--r--kttsd/filters/xmltransformer/xmltransformerconf.cpp182
-rw-r--r--kttsd/filters/xmltransformer/xmltransformerconf.h120
-rw-r--r--kttsd/filters/xmltransformer/xmltransformerconfwidget.ui249
-rw-r--r--kttsd/filters/xmltransformer/xmltransformerplugin.cpp31
-rw-r--r--kttsd/filters/xmltransformer/xmltransformerproc.cpp385
-rw-r--r--kttsd/filters/xmltransformer/xmltransformerproc.h167
-rw-r--r--kttsd/icons/Makefile.am1
-rw-r--r--kttsd/icons/hi16-action-female.pngbin0 -> 206 bytes
-rw-r--r--kttsd/icons/hi16-action-male.pngbin0 -> 186 bytes
-rw-r--r--kttsd/icons/hi16-action-nospeak.pngbin0 -> 237 bytes
-rw-r--r--kttsd/icons/hi16-action-speak.pngbin0 -> 219 bytes
-rw-r--r--kttsd/icons/hi22-action-nospeak.pngbin0 -> 296 bytes
-rw-r--r--kttsd/icons/hi22-action-speak.pngbin0 -> 285 bytes
-rw-r--r--kttsd/icons/hi32-action-nospeak.pngbin0 -> 424 bytes
-rw-r--r--kttsd/icons/hi32-action-speak.pngbin0 -> 383 bytes
-rw-r--r--kttsd/icons/hi48-action-nospeak.pngbin0 -> 638 bytes
-rw-r--r--kttsd/icons/hi48-action-speak.pngbin0 -> 563 bytes
-rw-r--r--kttsd/icons/lo16-action-speak.pngbin0 -> 219 bytes
-rw-r--r--kttsd/icons/lo22-action-speak.pngbin0 -> 285 bytes
-rw-r--r--kttsd/icons/lo32-action-speak.pngbin0 -> 383 bytes
-rw-r--r--kttsd/kcmkttsmgr/Makefile.am51
-rw-r--r--kttsd/kcmkttsmgr/addtalker.cpp225
-rw-r--r--kttsd/kcmkttsmgr/addtalker.h89
-rw-r--r--kttsd/kcmkttsmgr/addtalkerwidget.ui260
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsd.desktop142
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsd_testmessage.desktop46
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsmgr.cpp2713
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsmgr.h530
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui1928
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui.h16
-rw-r--r--kttsd/kcmkttsmgr/selectevent.cpp149
-rw-r--r--kttsd/kcmkttsmgr/selectevent.h69
-rw-r--r--kttsd/kcmkttsmgr/selecteventwidget.ui62
-rw-r--r--kttsd/kttsd.lsm27
-rw-r--r--kttsd/kttsd/Makefile.am51
-rw-r--r--kttsd/kttsd/SSMLtoPlainText.xsl9
-rw-r--r--kttsd/kttsd/filtermgr.cpp405
-rw-r--r--kttsd/kttsd/filtermgr.h199
-rw-r--r--kttsd/kttsd/kttsd.cpp1183
-rw-r--r--kttsd/kttsd/kttsd.desktop56
-rw-r--r--kttsd/kttsd/kttsd.h686
-rw-r--r--kttsd/kttsd/main.cpp68
-rw-r--r--kttsd/kttsd/speaker.cpp1701
-rw-r--r--kttsd/kttsd/speaker.h599
-rw-r--r--kttsd/kttsd/speechdata.cpp1275
-rw-r--r--kttsd/kttsd/speechdata.h731
-rw-r--r--kttsd/kttsd/ssmlconvert.cpp295
-rw-r--r--kttsd/kttsd/ssmlconvert.h129
-rw-r--r--kttsd/kttsd/talkermgr.cpp388
-rw-r--r--kttsd/kttsd/talkermgr.h159
-rw-r--r--kttsd/kttsd/threadedplugin.cpp282
-rw-r--r--kttsd/kttsd/threadedplugin.h200
-rw-r--r--kttsd/kttsjobmgr/Makefile.am40
-rw-r--r--kttsd/kttsjobmgr/kttsjobmgr.cpp1023
-rw-r--r--kttsd/kttsjobmgr/kttsjobmgr.desktop49
-rw-r--r--kttsd/kttsjobmgr/kttsjobmgr.h298
-rw-r--r--kttsd/kttsmgr/Makefile.am34
-rw-r--r--kttsd/kttsmgr/kttsmgr.cpp334
-rw-r--r--kttsd/kttsmgr/kttsmgr.desktop98
-rw-r--r--kttsd/kttsmgr/kttsmgr.h86
-rw-r--r--kttsd/libkttsd/Makefile.am45
-rw-r--r--kttsd/libkttsd/filterconf.cpp166
-rw-r--r--kttsd/libkttsd/filterconf.h149
-rw-r--r--kttsd/libkttsd/filterproc.cpp153
-rw-r--r--kttsd/libkttsd/filterproc.h179
-rw-r--r--kttsd/libkttsd/kdeexportfix.h27
-rw-r--r--kttsd/libkttsd/kttsd_synthplugin.desktop8
-rw-r--r--kttsd/libkttsd/notify.cpp177
-rw-r--r--kttsd/libkttsd/notify.h85
-rw-r--r--kttsd/libkttsd/player.h76
-rw-r--r--kttsd/libkttsd/pluginconf.cpp245
-rw-r--r--kttsd/libkttsd/pluginconf.h378
-rw-r--r--kttsd/libkttsd/pluginproc.cpp292
-rw-r--r--kttsd/libkttsd/pluginproc.h466
-rw-r--r--kttsd/libkttsd/selecttalkerdlg.cpp365
-rw-r--r--kttsd/libkttsd/selecttalkerdlg.h110
-rw-r--r--kttsd/libkttsd/selecttalkerwidget.ui572
-rw-r--r--kttsd/libkttsd/stretcher.cpp99
-rw-r--r--kttsd/libkttsd/stretcher.h97
-rw-r--r--kttsd/libkttsd/talkercode.cpp517
-rw-r--r--kttsd/libkttsd/talkercode.h197
-rw-r--r--kttsd/libkttsd/testplayer.cpp209
-rw-r--r--kttsd/libkttsd/testplayer.h121
-rw-r--r--kttsd/libkttsd/utils.cpp132
-rw-r--r--kttsd/libkttsd/utils.h61
-rw-r--r--kttsd/players/Makefile.am27
-rw-r--r--kttsd/players/akodeplayer/Makefile.am28
-rw-r--r--kttsd/players/akodeplayer/README19
-rw-r--r--kttsd/players/akodeplayer/akodeplayer.cpp179
-rw-r--r--kttsd/players/akodeplayer/akodeplayer.h67
-rw-r--r--kttsd/players/akodeplayer/akodeplugin.cpp29
-rw-r--r--kttsd/players/akodeplayer/kttsd_akodeplugin.desktop89
-rw-r--r--kttsd/players/alsaplayer/Makefile.am30
-rw-r--r--kttsd/players/alsaplayer/alsaplayer.cpp1729
-rw-r--r--kttsd/players/alsaplayer/alsaplayer.h187
-rw-r--r--kttsd/players/alsaplayer/alsaplugin.cpp29
-rw-r--r--kttsd/players/alsaplayer/formats.h110
-rw-r--r--kttsd/players/alsaplayer/kttsd_alsaplugin.desktop89
-rw-r--r--kttsd/players/artsplayer/Makefile.am30
-rw-r--r--kttsd/players/artsplayer/artsplayer.cpp296
-rw-r--r--kttsd/players/artsplayer/artsplayer.h95
-rw-r--r--kttsd/players/artsplayer/artsplugin.cpp29
-rw-r--r--kttsd/players/artsplayer/kttsd_artsplugin.desktop91
-rw-r--r--kttsd/players/gstplayer/Makefile.am30
-rw-r--r--kttsd/players/gstplayer/gstplugin.cpp29
-rw-r--r--kttsd/players/gstplayer/gstreamerplayer.cpp258
-rw-r--r--kttsd/players/gstplayer/gstreamerplayer.h76
-rw-r--r--kttsd/players/gstplayer/kttsd_gstplugin.desktop92
-rw-r--r--kttsd/players/kttsd_audioplugin.desktop47
-rw-r--r--kttsd/plugins/Makefile.am37
-rw-r--r--kttsd/plugins/command/Makefile.am18
-rw-r--r--kttsd/plugins/command/README8
-rw-r--r--kttsd/plugins/command/commandconf.cpp217
-rw-r--r--kttsd/plugins/command/commandconf.h121
-rw-r--r--kttsd/plugins/command/commandconfwidget.ui227
-rw-r--r--kttsd/plugins/command/commandplugin.cpp24
-rw-r--r--kttsd/plugins/command/commandproc.cpp446
-rw-r--r--kttsd/plugins/command/commandproc.h201
-rw-r--r--kttsd/plugins/command/configure.in.in17
-rw-r--r--kttsd/plugins/command/kttsd_commandplugin.desktop92
-rw-r--r--kttsd/plugins/epos/Makefile.am20
-rw-r--r--kttsd/plugins/epos/README3
-rw-r--r--kttsd/plugins/epos/configure.in.bot15
-rw-r--r--kttsd/plugins/epos/configure.in.in22
-rw-r--r--kttsd/plugins/epos/eposconf.cpp319
-rw-r--r--kttsd/plugins/epos/eposconf.h141
-rw-r--r--kttsd/plugins/epos/eposconfwidget.ui610
-rw-r--r--kttsd/plugins/epos/eposplugin.cpp31
-rw-r--r--kttsd/plugins/epos/eposproc.cpp389
-rw-r--r--kttsd/plugins/epos/eposproc.h241
-rw-r--r--kttsd/plugins/epos/kttsd_eposplugin.desktop87
-rw-r--r--kttsd/plugins/festivalint/Makefile.am27
-rw-r--r--kttsd/plugins/festivalint/README9
-rw-r--r--kttsd/plugins/festivalint/SSMLtoSable.xsl272
-rw-r--r--kttsd/plugins/festivalint/configure.in.bot16
-rw-r--r--kttsd/plugins/festivalint/configure.in.in22
-rw-r--r--kttsd/plugins/festivalint/festivalintconf.cpp730
-rw-r--r--kttsd/plugins/festivalint/festivalintconf.h187
-rw-r--r--kttsd/plugins/festivalint/festivalintconfwidget.ui598
-rw-r--r--kttsd/plugins/festivalint/festivalintplugin.cpp31
-rw-r--r--kttsd/plugins/festivalint/festivalintproc.cpp662
-rw-r--r--kttsd/plugins/festivalint/festivalintproc.h361
-rw-r--r--kttsd/plugins/festivalint/kttsd_festivalintplugin.desktop72
-rw-r--r--kttsd/plugins/festivalint/sabletowave.scm92
-rw-r--r--kttsd/plugins/festivalint/voices738
-rw-r--r--kttsd/plugins/flite/Makefile.am20
-rw-r--r--kttsd/plugins/flite/README3
-rw-r--r--kttsd/plugins/flite/configure.in.bot15
-rw-r--r--kttsd/plugins/flite/configure.in.in22
-rw-r--r--kttsd/plugins/flite/fliteconf.cpp199
-rw-r--r--kttsd/plugins/flite/fliteconf.h124
-rw-r--r--kttsd/plugins/flite/fliteconfwidget.ui186
-rw-r--r--kttsd/plugins/flite/fliteplugin.cpp31
-rw-r--r--kttsd/plugins/flite/fliteproc.cpp281
-rw-r--r--kttsd/plugins/flite/fliteproc.h187
-rw-r--r--kttsd/plugins/flite/kttsd_fliteplugin.desktop59
-rw-r--r--kttsd/plugins/freetts/Makefile.am18
-rw-r--r--kttsd/plugins/freetts/README6
-rw-r--r--kttsd/plugins/freetts/configure.in.bot15
-rw-r--r--kttsd/plugins/freetts/configure.in.in22
-rw-r--r--kttsd/plugins/freetts/freettsconf.cpp230
-rw-r--r--kttsd/plugins/freetts/freettsconf.h122
-rw-r--r--kttsd/plugins/freetts/freettsconfigwidget.ui200
-rw-r--r--kttsd/plugins/freetts/freettsplugin.cpp26
-rw-r--r--kttsd/plugins/freetts/freettsproc.cpp275
-rw-r--r--kttsd/plugins/freetts/freettsproc.h180
-rw-r--r--kttsd/plugins/freetts/kttsd_freettsplugin.desktop51
-rw-r--r--kttsd/plugins/hadifix/Makefile.am23
-rw-r--r--kttsd/plugins/hadifix/README3
-rw-r--r--kttsd/plugins/hadifix/SSMLtoTxt2pho.xsl164
-rw-r--r--kttsd/plugins/hadifix/configure.in.bot37
-rw-r--r--kttsd/plugins/hadifix/configure.in.in37
-rw-r--r--kttsd/plugins/hadifix/hadifixconf.cpp406
-rw-r--r--kttsd/plugins/hadifix/hadifixconf.h83
-rw-r--r--kttsd/plugins/hadifix/hadifixconfigui.ui692
-rw-r--r--kttsd/plugins/hadifix/hadifixconfigui.ui.h114
-rw-r--r--kttsd/plugins/hadifix/hadifixplugin.cpp23
-rw-r--r--kttsd/plugins/hadifix/hadifixproc.cpp411
-rw-r--r--kttsd/plugins/hadifix/hadifixproc.h203
-rw-r--r--kttsd/plugins/hadifix/initialconfig.h164
-rw-r--r--kttsd/plugins/hadifix/kttsd_hadifixplugin.desktop51
-rw-r--r--kttsd/plugins/hadifix/voicefileui.ui119
-rw-r--r--kttsd/plugins/hadifix/voicefileui.ui.h35
-rw-r--r--kttsd/sample.polish8
-rw-r--r--kttsd/sample.ssml1
3279 files changed, 107941 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5185fd3
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,346 @@
+NOTE! The GPL below is copyrighted by the Free Software Foundation, but
+the instance of code that it refers to (the kde programs) are copyrighted
+by the authors who actually wrote it.
+
+---------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/COPYING-DOCS b/COPYING-DOCS
new file mode 100644
index 0000000..4a0fe1c
--- /dev/null
+++ b/COPYING-DOCS
@@ -0,0 +1,397 @@
+ GNU Free Documentation License
+ Version 1.2, November 2002
+
+
+ Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+0. PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document "free" in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of "copyleft", which means that derivative
+works of the document must themselves be free in the same sense. It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does. But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book. We recommend this License
+principally for works whose purpose is instruction or reference.
+
+
+1. APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License. Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein. The "Document", below,
+refers to any such manual or work. Any member of the public is a
+licensee, and is addressed as "you". You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A "Modified Version" of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A "Secondary Section" is a named appendix or a front-matter section of
+the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall subject
+(or to related matters) and contains nothing that could fall directly
+within that overall subject. (Thus, if the Document is in part a
+textbook of mathematics, a Secondary Section may not explain any
+mathematics.) The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The "Invariant Sections" are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License. If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant. The Document may contain zero
+Invariant Sections. If the Document does not identify any Invariant
+Sections then there are none.
+
+The "Cover Texts" are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License. A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A "Transparent" copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters. A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text. A copy that is not "Transparent" is called "Opaque".
+
+Examples of suitable formats for Transparent copies include plain
+ASCII without markup, Texinfo input format, LaTeX input format, SGML
+or XML using a publicly available DTD, and standard-conforming simple
+HTML, PostScript or PDF designed for human modification. Examples of
+transparent image formats include PNG, XCF and JPG. Opaque formats
+include proprietary formats that can be read and edited only by
+proprietary word processors, SGML or XML for which the DTD and/or
+processing tools are not generally available, and the
+machine-generated HTML, PostScript or PDF produced by some word
+processors for output purposes only.
+
+The "Title Page" means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page. For works in
+formats which do not have any title page as such, "Title Page" means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+A section "Entitled XYZ" means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language. (Here XYZ stands for a
+specific section name mentioned below, such as "Acknowledgements",
+"Dedications", "Endorsements", or "History".) To "Preserve the Title"
+of such a section when you modify the Document means that it remains a
+section "Entitled XYZ" according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document. These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+
+2. VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License. You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute. However, you may accept
+compensation in exchange for copies. If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+
+3. COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover. Both covers must also clearly and legibly identify
+you as the publisher of these copies. The front cover must present
+the full title with all words of the title equally prominent and
+visible. You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+
+4. MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it. In addition, you must do these things in the Modified Version:
+
+A. Use in the Title Page (and on the covers, if any) a title distinct
+ from that of the Document, and from those of previous versions
+ (which should, if there were any, be listed in the History section
+ of the Document). You may use the same title as a previous version
+ if the original publisher of that version gives permission.
+B. List on the Title Page, as authors, one or more persons or entities
+ responsible for authorship of the modifications in the Modified
+ Version, together with at least five of the principal authors of the
+ Document (all of its principal authors, if it has fewer than five),
+ unless they release you from this requirement.
+C. State on the Title page the name of the publisher of the
+ Modified Version, as the publisher.
+D. Preserve all the copyright notices of the Document.
+E. Add an appropriate copyright notice for your modifications
+ adjacent to the other copyright notices.
+F. Include, immediately after the copyright notices, a license notice
+ giving the public permission to use the Modified Version under the
+ terms of this License, in the form shown in the Addendum below.
+G. Preserve in that license notice the full lists of Invariant Sections
+ and required Cover Texts given in the Document's license notice.
+H. Include an unaltered copy of this License.
+I. Preserve the section Entitled "History", Preserve its Title, and add
+ to it an item stating at least the title, year, new authors, and
+ publisher of the Modified Version as given on the Title Page. If
+ there is no section Entitled "History" in the Document, create one
+ stating the title, year, authors, and publisher of the Document as
+ given on its Title Page, then add an item describing the Modified
+ Version as stated in the previous sentence.
+J. Preserve the network location, if any, given in the Document for
+ public access to a Transparent copy of the Document, and likewise
+ the network locations given in the Document for previous versions
+ it was based on. These may be placed in the "History" section.
+ You may omit a network location for a work that was published at
+ least four years before the Document itself, or if the original
+ publisher of the version it refers to gives permission.
+K. For any section Entitled "Acknowledgements" or "Dedications",
+ Preserve the Title of the section, and preserve in the section all
+ the substance and tone of each of the contributor acknowledgements
+ and/or dedications given therein.
+L. Preserve all the Invariant Sections of the Document,
+ unaltered in their text and in their titles. Section numbers
+ or the equivalent are not considered part of the section titles.
+M. Delete any section Entitled "Endorsements". Such a section
+ may not be included in the Modified Version.
+N. Do not retitle any existing section to be Entitled "Endorsements"
+ or to conflict in title with any Invariant Section.
+O. Preserve any Warranty Disclaimers.
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant. To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled "Endorsements", provided it contains
+nothing but endorsements of your Modified Version by various
+parties--for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version. Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity. If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+
+5. COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy. If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled "History"
+in the various original documents, forming one section Entitled
+"History"; likewise combine any sections Entitled "Acknowledgements",
+and any sections Entitled "Dedications". You must delete all sections
+Entitled "Endorsements".
+
+
+6. COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+
+7. AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an "aggregate" if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+
+8. TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections. You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers. In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled "Acknowledgements",
+"Dedications", or "History", the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+
+9. TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License. Any other attempt to
+copy, modify, sublicense or distribute the Document is void, and will
+automatically terminate your rights under this License. However,
+parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+
+10. FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns. See
+http://www.gnu.org/copyleft/.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License "or any later version" applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation. If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+
+
+ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+ Copyright (c) YEAR YOUR NAME.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
+ A copy of the license is included in the section entitled "GNU
+ Free Documentation License".
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the "with...Texts." line with this:
+
+ with the Invariant Sections being LIST THEIR TITLES, with the
+ Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..26aac1d
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,184 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `gmake' to compile the package. Or if you're using a Linux
+ powered machine, or if make is GNU make, type `make'. You can
+ check with make --version. KDE requires GNU make to build, if
+ gmake is appropriate, replace any instance below of make with gmake.
+ It will give output similar to:
+ #make --version
+ GNU Make version 3.78.1, by Richard Stallman and Roland McGrath.
+ Built for i386--freebsd4.0
+ Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
+ ...
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/kde/bin', `/usr/local/kde/lib', etc. You can specify an
+installation prefix other than `/usr/local/kde' by giving `configure'
+the option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/IconThemes/Makefile.am b/IconThemes/Makefile.am
new file mode 100644
index 0000000..3e7b623
--- /dev/null
+++ b/IconThemes/Makefile.am
@@ -0,0 +1,43 @@
+## kdeaccessibility/icontheme/Makefile.am
+## (C) 1997-2001 Stephan Kulow
+## (C) 2005 Gunnar Schmi Dt
+
+install-exec-am: install-data-local
+
+ICONTHEMES=mono
+
+# For Themes
+themesdir = $(kde_datadir)/kthememgr/Themes
+install-data-local:
+ @for theme in $(ICONTHEMES) ; do \
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/$$theme ; \
+ $(INSTALL_DATA) $(top_srcdir)/IconThemes/$$theme/index.theme $(DESTDIR)$(kde_icondir)/$$theme ; \
+ sizes=`cd $(top_srcdir)/IconThemes/$$theme && ls -1`; \
+ for size in $$sizes ; do \
+ if [ -d $(top_srcdir)/IconThemes/$$theme/$$size -a $$size != "CVS" -a $$size != ".svn" ]; then \
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/$$theme/$$size ; \
+ for group in actions apps devices filesystems mimetypes; do \
+ if [ -d $(top_srcdir)/IconThemes/$$theme/$$size/$$group ]; then \
+ echo "installing $$theme/$$size/$$group" ; \
+ $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/$$theme/$$size/$$group ; \
+ pngs=`cd $(top_srcdir)/IconThemes/$$theme/$$size/$$group && ls -1 *.png 2> /dev/null`; \
+ for png in $$pngs; do $(INSTALL_DATA) $(top_srcdir)/IconThemes/$$theme/$$size/$$group/$$png \
+ $(DESTDIR)$(kde_icondir)/$$theme/$$size/$$group/$$png ; done; \
+ mngs=`cd $(top_srcdir)/IconThemes/$$theme/$$size/$$group && ls -1 *.mng 2> /dev/null`; \
+ for mng in $$mngs; do \
+ $(INSTALL_DATA) $(top_srcdir)/IconThemes/$$theme/$$size/$$group/$$mng \
+ $(DESTDIR)$(kde_icondir)/$$theme/$$size/$$group/$$mng ; done; \
+ svgzs=`cd $(top_srcdir)/IconThemes/$$theme/$$size/$$group && ls -1 *.svgz 2> /dev/null`; \
+ for svgz in $$svgzs; do $(INSTALL_DATA) $(top_srcdir)/IconThemes/$$theme/$$size/$$group/$$svgz \
+ $(DESTDIR)$(kde_icondir)/$$theme/$$size/$$group/$$svgz ; done; \
+ if [ $$group = "actions" -a -d $(top_srcdir)/IconThemes/$$theme/$$size/$$group/kde ]; then \
+ (cd $(top_srcdir)/IconThemes/$$theme/$$size/$$group/kde && \
+ $(bindir)/kimage_concat kde- kde.png) ;\
+ $(INSTALL_DATA) $(top_srcdir)/IconThemes/$$theme/$$size/$$group/kde/kde.png \
+ $(DESTDIR)$(kde_icondir)/$$theme/$$size/$$group ; \
+ fi ; \
+ fi ; \
+ done ; \
+ fi ; \
+ done ; \
+ done
diff --git a/IconThemes/mono/index.theme b/IconThemes/mono/index.theme
new file mode 100644
index 0000000..f81bffb
--- /dev/null
+++ b/IconThemes/mono/index.theme
@@ -0,0 +1,175 @@
+[Icon Theme]
+Name=Monochrome
+Name[br]=Monokrom
+Name[ca]=Monocrom
+Name[cs]=Černobíle
+Name[cy]=Unlliw
+Name[da]=Monokrom
+Name[de]=Monochrom
+Name[el]=Μονόχρωμο
+Name[es]=Monocromo
+Name[et]=Ühevärviline
+Name[eu]=Monokromoa
+Name[fa]=تک رنگ
+Name[fi]=Yksivärinen
+Name[ga]=Monacrómach
+Name[gl]=Monocromo
+Name[he]=מונוכרום
+Name[hu]=Monokróm
+Name[is]=Svart/hvítt
+Name[it]=Monocromo
+Name[ka]=მონოქრომატული
+Name[km]=តែ​មួយ​ពណ៌
+Name[lt]=Monochrominis
+Name[mk]=Монохром
+Name[ms]=Monokrom
+Name[nb]=Ensfarget
+Name[nds]=Swattwitt
+Name[ne]=मोनोक्रोम
+Name[nl]=Monochroom
+Name[pl]=Monochromatyczny
+Name[pt]=Monocromático
+Name[pt_BR]=Monocromático
+Name[ru]=Чёрно-белая тема
+Name[sk]=Monochromatické
+Name[sl]=Monokromatsko
+Name[sr]=Монохроматски
+Name[sr@Latn]=Monohromatski
+Name[sv]=Monokrom
+Name[ta]=மோனோக்ரோம்
+Name[tg]=Мавзӯъи сиёҳ-сафед
+Name[tr]=Siyah-beyaz
+Name[uk]=Чорно-біле
+Name[vi]=Đơn sắc
+Name[zh_TW]=單色
+Comment=By Danny Allen (danny@dannyallen.co.uk)
+Comment[bs]=Autor: Danny Allen (danny@dannyallen.co.uk)
+Comment[ca]=Per Danny Allen (danny@dannyallen.co.uk)
+Comment[cs]=Danny Allen (danny@dannyallen.co.uk)
+Comment[da]=Ved Danny Allen (danny@dannyallen.co.uk)
+Comment[de]=Von Danny Allen (danny@dannyallen.co.uk)
+Comment[el]=Από τον Danny Allen (danny@dannyallen.co.uk)
+Comment[es]=Por Danny Allen (danny@dannyallen.co.uk)
+Comment[et]=Autor: Danny Allen (danny@dannyallen.co.uk)
+Comment[eu]=Egilea: Danny Allen (danny@dannyallen.co.uk)
+Comment[fa]=توسط دنی آلن (danny @dannyallen.co.uk)
+Comment[fi]=Danny Allen (danny@dannyallen.co.uk)
+Comment[fr]=De Danny Allen (danny@dannyallen.co.uk)
+Comment[ga]=Le Danny Allen (danny@dannyallen.co.uk)
+Comment[gl]=Por Danny Allen (danny@dannyallen.co.uk)
+Comment[he]=נכתב על ידי Danny Allen (danny@dannyallen.co.uk)
+Comment[hu]=Készítette: Danny Allen <danny@dannyallen.co.uk>
+Comment[is]=Eftir Danny Allen (danny@dannyallen.co.uk)
+Comment[it]=Di Danny Allen (danny@dannyallen.co.uk)
+Comment[ka]=დენი ალიენის ავტორობით (danny@dannyallen.co.uk)
+Comment[km]= ដោយ​លោក​ Danny Allen (danny@dannyallen.co.uk)
+Comment[lt]=Sukūrė Danny Allen (danny@dannyallen.co.uk)
+Comment[mk]=Од Danny Allen (danny@dannyallen.co.uk)
+Comment[ms]=Oleh Danny Allen (danny@dannyallen.co.uk)
+Comment[mt]=Ta' Danny Allen (danny@dannyallen.co.uk)
+Comment[nb]=av Danny Allen (danny@dannyallen.co.uk)
+Comment[nds]=Vun Danny Allen (danny@dannyallen.co.uk)
+Comment[ne]=डेनी एलेनद्वारा (danny@dannyallen.co.uk)
+Comment[nl]=door Danny Allen (danny@dannyallen.co.uk)
+Comment[pa]=Danny Allen (danny@dannyallen.co.uk) ਵਲੋਂ
+Comment[pl]=Autor Danny Allen (danny@dannyallen.co.uk)
+Comment[pt]=Por Danny Allen (danny@dannyallen.co.uk)
+Comment[pt_BR]=Por Danny Allen (danny@dannyallen.co.uk)
+Comment[ru]=Написал Дэнни Аллен (Danny Allen) (danny@dannyallen.co.uk)
+Comment[sk]=Danny Allen (danny@dannyallen.co.uk)
+Comment[sl]=Napisal Danny Allen (danny@dannyallen.co.uk)
+Comment[sr]=Од Денија Алена (Danny Allen, danny@dannyallen.co.uk)
+Comment[sr@Latn]=Od Denija Alena (Danny Allen, danny@dannyallen.co.uk)
+Comment[sv]=Av Danny Allen (danny@dannyallen.co.uk)
+Comment[ta]=டானி ஆலன் (danny@dannyallen.co.uk)
+Comment[tg]=Навишташудааст аз тарафи Аллен (Danny Allen) (danny@dannyallen.co.uk)
+Comment[th]=โดย Danny Allen (danny@dannyallen.co.uk)
+Comment[tr]=Danny Allen (danny@dannyallen.co.uk)
+Comment[uk]=Автор Danny Allen (danny@dannyallen.co.uk)
+Comment[vi]=Bởi Danny Allen (danny@dannyallen.co.uk)
+Comment[zh_CN]=由 Danny Allen (danny@dannyallen.co.uk) 制作
+Inherits=hicolor
+DisplayDepth=32
+Example=exec
+LinkOverlay=link_overlay
+LockOverlay=lock_overlay
+ZipOverlay=zip_overlay
+DesktopDefault=48
+DesktopSizes=22,32,48,64,128,256
+ToolbarDefault=32
+ToolbarSizes=16,22,32,48,64,128,256
+MainToolbarDefault=32
+MainToolbarSizes=16,22,32,48,64,128,256
+SmallDefault=16
+SmallSizes=16
+PanelDefault=48
+PanelSizes=16,22,32,48,64,128,256
+Directories=scalable/actions,png/16x16/actions,png/22x22/actions,png/32x32/actions,png/48x48/actions,png/64x64/actions,png/96x96/actions,png/128x128/actions,png/192x192/actions,png/256x256/actions,scalable/apps,scalable/devices,scalable/filesystems,scalable/mimetypes
+
+[scalable/actions]
+Size=48
+Type=Scalable
+MinSize=8
+MaxSize=256
+Context=Actions
+[scalable/apps]
+Size=48
+Type=Scalable
+MinSize=8
+MaxSize=256
+Context=Applications
+[scalable/devices]
+Size=48
+Type=Scalable
+MinSize=8
+MaxSize=256
+Context=Devices
+[scalable/filesystems]
+Size=48
+Type=Scalable
+MinSize=8
+MaxSize=256
+Context=FileSystems
+[scalable/mimetypes]
+Size=48
+Type=Scalable
+MinSize=8
+MaxSize=256
+Context=MimeTypes
+
+[png/16x16/actions]
+Size=16
+Context=Actions
+Type=Threshold
+[png/22x22/actions]
+Size=22
+Context=Actions
+Type=Threshold
+[png/32x32/actions]
+Size=32
+Context=Actions
+Type=Threshold
+[png/48x48/actions]
+Size=48
+Context=Actions
+Type=Threshold
+[png/64x64/actions]
+Size=64
+Context=Actions
+Type=Threshold
+[png/96x96/actions]
+Size=96
+Context=Actions
+Type=Threshold
+[png/128x128/actions]
+Size=128
+Context=Actions
+Type=Threshold
+[png/192x192/actions]
+Size=192
+Context=Actions
+Type=Threshold
+[png/256x256/actions]
+Size=256
+Context=Actions
+Type=Threshold
diff --git a/IconThemes/mono/png/128x128/actions/kde.png b/IconThemes/mono/png/128x128/actions/kde.png
new file mode 100644
index 0000000..f3d5d97
--- /dev/null
+++ b/IconThemes/mono/png/128x128/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/png/16x16/actions/kde.png b/IconThemes/mono/png/16x16/actions/kde.png
new file mode 100644
index 0000000..cf00a4c
--- /dev/null
+++ b/IconThemes/mono/png/16x16/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/png/192x192/actions/kde.png b/IconThemes/mono/png/192x192/actions/kde.png
new file mode 100644
index 0000000..4f33e58
--- /dev/null
+++ b/IconThemes/mono/png/192x192/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/png/22x22/actions/kde.png b/IconThemes/mono/png/22x22/actions/kde.png
new file mode 100644
index 0000000..f3a3a4f
--- /dev/null
+++ b/IconThemes/mono/png/22x22/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/png/256x256/actions/kde.png b/IconThemes/mono/png/256x256/actions/kde.png
new file mode 100644
index 0000000..ec179c2
--- /dev/null
+++ b/IconThemes/mono/png/256x256/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/png/32x32/actions/kde.png b/IconThemes/mono/png/32x32/actions/kde.png
new file mode 100644
index 0000000..f9e5fa5
--- /dev/null
+++ b/IconThemes/mono/png/32x32/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/png/48x48/actions/kde.png b/IconThemes/mono/png/48x48/actions/kde.png
new file mode 100644
index 0000000..12fdd1e
--- /dev/null
+++ b/IconThemes/mono/png/48x48/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/png/64x64/actions/kde.png b/IconThemes/mono/png/64x64/actions/kde.png
new file mode 100644
index 0000000..73bccde
--- /dev/null
+++ b/IconThemes/mono/png/64x64/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/png/96x96/actions/kde.png b/IconThemes/mono/png/96x96/actions/kde.png
new file mode 100644
index 0000000..59027bd
--- /dev/null
+++ b/IconThemes/mono/png/96x96/actions/kde.png
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_ellipse.svgz b/IconThemes/mono/scalable/actions/14_ellipse.svgz
new file mode 100644
index 0000000..ef9d66e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_ellipse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_flatten.svgz b/IconThemes/mono/scalable/actions/14_flatten.svgz
new file mode 100644
index 0000000..9faa1d6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_flatten.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_gradient.svgz b/IconThemes/mono/scalable/actions/14_gradient.svgz
new file mode 100644
index 0000000..d392bb7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_gradient.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_group.svgz b/IconThemes/mono/scalable/actions/14_group.svgz
new file mode 100644
index 0000000..fc2b4b6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_group.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_image.svgz b/IconThemes/mono/scalable/actions/14_image.svgz
new file mode 100644
index 0000000..8adbdc9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_image.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_insertknots.svgz b/IconThemes/mono/scalable/actions/14_insertknots.svgz
new file mode 100644
index 0000000..704ba68
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_insertknots.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_layer_deletelayer.svgz b/IconThemes/mono/scalable/actions/14_layer_deletelayer.svgz
new file mode 100644
index 0000000..11b87c8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_layer_deletelayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_layer_lowerlayer.svgz b/IconThemes/mono/scalable/actions/14_layer_lowerlayer.svgz
new file mode 100644
index 0000000..c8d726d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_layer_lowerlayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_layer_newlayer.svgz b/IconThemes/mono/scalable/actions/14_layer_newlayer.svgz
new file mode 100644
index 0000000..d8f51f3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_layer_newlayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_layer_novisible.svgz b/IconThemes/mono/scalable/actions/14_layer_novisible.svgz
new file mode 100644
index 0000000..f7731f7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_layer_novisible.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_layer_raiselayer.svgz b/IconThemes/mono/scalable/actions/14_layer_raiselayer.svgz
new file mode 100644
index 0000000..f14afb9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_layer_raiselayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_layer_visible.svgz b/IconThemes/mono/scalable/actions/14_layer_visible.svgz
new file mode 100644
index 0000000..a2a1852
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_layer_visible.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_pattern.svgz b/IconThemes/mono/scalable/actions/14_pattern.svgz
new file mode 100644
index 0000000..c4c821d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_pattern.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_pencil.svgz b/IconThemes/mono/scalable/actions/14_pencil.svgz
new file mode 100644
index 0000000..a3754ff
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_pencil.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_polygon.svgz b/IconThemes/mono/scalable/actions/14_polygon.svgz
new file mode 100644
index 0000000..372452b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_polygon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_polyline.svgz b/IconThemes/mono/scalable/actions/14_polyline.svgz
new file mode 100644
index 0000000..3850b8c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_polyline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_rectangle.svgz b/IconThemes/mono/scalable/actions/14_rectangle.svgz
new file mode 100644
index 0000000..7808754
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_rectangle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_rotate.svgz b/IconThemes/mono/scalable/actions/14_rotate.svgz
new file mode 100644
index 0000000..a82d576
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_rotate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_roundcorners.svgz b/IconThemes/mono/scalable/actions/14_roundcorners.svgz
new file mode 100644
index 0000000..0ce976b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_roundcorners.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_roundrect.svgz b/IconThemes/mono/scalable/actions/14_roundrect.svgz
new file mode 100644
index 0000000..e0f7b03
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_roundrect.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_select.svgz b/IconThemes/mono/scalable/actions/14_select.svgz
new file mode 100644
index 0000000..fefa43e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_select.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_selectnodes.svgz b/IconThemes/mono/scalable/actions/14_selectnodes.svgz
new file mode 100644
index 0000000..3a7439b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_selectnodes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_shear.svgz b/IconThemes/mono/scalable/actions/14_shear.svgz
new file mode 100644
index 0000000..1d7837f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_shear.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_sinus.svgz b/IconThemes/mono/scalable/actions/14_sinus.svgz
new file mode 100644
index 0000000..cb04f6b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_sinus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_spiral.svgz b/IconThemes/mono/scalable/actions/14_spiral.svgz
new file mode 100644
index 0000000..9fb2a1c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_spiral.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_star.svgz b/IconThemes/mono/scalable/actions/14_star.svgz
new file mode 100644
index 0000000..07f2627
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_star.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_text.svgz b/IconThemes/mono/scalable/actions/14_text.svgz
new file mode 100644
index 0000000..d3bcb57
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_transform.svgz b/IconThemes/mono/scalable/actions/14_transform.svgz
new file mode 100644
index 0000000..13ca3ff
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_transform.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_ungroup.svgz b/IconThemes/mono/scalable/actions/14_ungroup.svgz
new file mode 100644
index 0000000..5d46aa0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_ungroup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_whirl.svgz b/IconThemes/mono/scalable/actions/14_whirl.svgz
new file mode 100644
index 0000000..bc22679
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_whirl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/14_zoom.svgz b/IconThemes/mono/scalable/actions/14_zoom.svgz
new file mode 100644
index 0000000..c252e1f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/14_zoom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/1day.svgz b/IconThemes/mono/scalable/actions/1day.svgz
new file mode 100644
index 0000000..345e975
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/1day.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/1downarrow.svgz b/IconThemes/mono/scalable/actions/1downarrow.svgz
new file mode 100644
index 0000000..c03b12e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/1downarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/1leftarrow.svgz b/IconThemes/mono/scalable/actions/1leftarrow.svgz
new file mode 100644
index 0000000..24ccd1b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/1leftarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/1rightarrow.svgz b/IconThemes/mono/scalable/actions/1rightarrow.svgz
new file mode 100644
index 0000000..224f5a7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/1rightarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/1uparrow.svgz b/IconThemes/mono/scalable/actions/1uparrow.svgz
new file mode 100644
index 0000000..1ccb789
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/1uparrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/2downarrow.svgz b/IconThemes/mono/scalable/actions/2downarrow.svgz
new file mode 100644
index 0000000..20653a2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/2downarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/2leftarrow.svgz b/IconThemes/mono/scalable/actions/2leftarrow.svgz
new file mode 100644
index 0000000..4fd353c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/2leftarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/2rightarrow.svgz b/IconThemes/mono/scalable/actions/2rightarrow.svgz
new file mode 100644
index 0000000..7287eac
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/2rightarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/2uparrow.svgz b/IconThemes/mono/scalable/actions/2uparrow.svgz
new file mode 100644
index 0000000..4ec834b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/2uparrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/3downarrow.svgz b/IconThemes/mono/scalable/actions/3downarrow.svgz
new file mode 100644
index 0000000..cb3bb9b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/3downarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/3leftarrow.svgz b/IconThemes/mono/scalable/actions/3leftarrow.svgz
new file mode 100644
index 0000000..b58b825
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/3leftarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/3rightarrow.svgz b/IconThemes/mono/scalable/actions/3rightarrow.svgz
new file mode 100644
index 0000000..05dc7ee
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/3rightarrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/3uparrow.svgz b/IconThemes/mono/scalable/actions/3uparrow.svgz
new file mode 100644
index 0000000..326460a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/3uparrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/5days.svgz b/IconThemes/mono/scalable/actions/5days.svgz
new file mode 100644
index 0000000..b950b7f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/5days.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/7days.svgz b/IconThemes/mono/scalable/actions/7days.svgz
new file mode 100644
index 0000000..ac7b84a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/7days.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/abentry.svgz b/IconThemes/mono/scalable/actions/abentry.svgz
new file mode 100644
index 0000000..a17a39a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/abentry.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/about_kde.svgz b/IconThemes/mono/scalable/actions/about_kde.svgz
new file mode 100644
index 0000000..94e0d25
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/about_kde.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/abs.svgz b/IconThemes/mono/scalable/actions/abs.svgz
new file mode 100644
index 0000000..9f18353
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/abs.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/account.svgz b/IconThemes/mono/scalable/actions/account.svgz
new file mode 100644
index 0000000..1a79720
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/account.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/account_open.svgz b/IconThemes/mono/scalable/actions/account_open.svgz
new file mode 100644
index 0000000..bd91b54
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/account_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/add.svgz b/IconThemes/mono/scalable/actions/add.svgz
new file mode 100644
index 0000000..471f014
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/add.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/add_group.svgz b/IconThemes/mono/scalable/actions/add_group.svgz
new file mode 100644
index 0000000..119193f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/add_group.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/add_milestone.svgz b/IconThemes/mono/scalable/actions/add_milestone.svgz
new file mode 100644
index 0000000..8476433
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/add_milestone.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/add_sub_task.svgz b/IconThemes/mono/scalable/actions/add_sub_task.svgz
new file mode 100644
index 0000000..cc37d46
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/add_sub_task.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/add_target.svgz b/IconThemes/mono/scalable/actions/add_target.svgz
new file mode 100644
index 0000000..cb11241
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/add_target.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/add_task.svgz b/IconThemes/mono/scalable/actions/add_task.svgz
new file mode 100644
index 0000000..cb853df
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/add_task.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/add_user.svgz b/IconThemes/mono/scalable/actions/add_user.svgz
new file mode 100644
index 0000000..b181b6d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/add_user.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/addimagefolder.svgz b/IconThemes/mono/scalable/actions/addimagefolder.svgz
new file mode 100644
index 0000000..06207a1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/addimagefolder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/addpoint.svgz b/IconThemes/mono/scalable/actions/addpoint.svgz
new file mode 100644
index 0000000..b7e4f22
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/addpoint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/addquestion.svgz b/IconThemes/mono/scalable/actions/addquestion.svgz
new file mode 100644
index 0000000..f107435
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/addquestion.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adept_commit.svgz b/IconThemes/mono/scalable/actions/adept_commit.svgz
new file mode 100644
index 0000000..b0f6d11
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adept_commit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adept_distupgrade.svgz b/IconThemes/mono/scalable/actions/adept_distupgrade.svgz
new file mode 100644
index 0000000..4e78ec3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adept_distupgrade.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adept_install.svgz b/IconThemes/mono/scalable/actions/adept_install.svgz
new file mode 100644
index 0000000..e7972c2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adept_install.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adept_notifier_warning.svgz b/IconThemes/mono/scalable/actions/adept_notifier_warning.svgz
new file mode 100644
index 0000000..91d6ebf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adept_notifier_warning.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adept_purge.svgz b/IconThemes/mono/scalable/actions/adept_purge.svgz
new file mode 100644
index 0000000..1060c82
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adept_purge.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adept_remove.svgz b/IconThemes/mono/scalable/actions/adept_remove.svgz
new file mode 100644
index 0000000..28118cf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adept_remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adept_sourceseditor.svgz b/IconThemes/mono/scalable/actions/adept_sourceseditor.svgz
new file mode 100644
index 0000000..b2db4bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adept_sourceseditor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adept_update.svgz b/IconThemes/mono/scalable/actions/adept_update.svgz
new file mode 100644
index 0000000..46ff733
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adept_update.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adjustcol.svgz b/IconThemes/mono/scalable/actions/adjustcol.svgz
new file mode 100644
index 0000000..7234054
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adjustcol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/adjustrow.svgz b/IconThemes/mono/scalable/actions/adjustrow.svgz
new file mode 100644
index 0000000..31aaca7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/adjustrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/agenda.svgz b/IconThemes/mono/scalable/actions/agenda.svgz
new file mode 100644
index 0000000..827808e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/agenda.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aim_away.svgz b/IconThemes/mono/scalable/actions/aim_away.svgz
new file mode 100644
index 0000000..d67e3cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aim_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aim_offline.svgz b/IconThemes/mono/scalable/actions/aim_offline.svgz
new file mode 100644
index 0000000..b6ba31b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aim_offline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aim_online.svgz b/IconThemes/mono/scalable/actions/aim_online.svgz
new file mode 100644
index 0000000..d0145dd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aim_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aim_protocol.svgz b/IconThemes/mono/scalable/actions/aim_protocol.svgz
new file mode 100644
index 0000000..bea6507
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aim_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/airbrush.svgz b/IconThemes/mono/scalable/actions/airbrush.svgz
new file mode 100644
index 0000000..959b175
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/airbrush.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/albumfoldercomment.svgz b/IconThemes/mono/scalable/actions/albumfoldercomment.svgz
new file mode 100644
index 0000000..f089004
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/albumfoldercomment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/albumfoldernew.svgz b/IconThemes/mono/scalable/actions/albumfoldernew.svgz
new file mode 100644
index 0000000..375d0e6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/albumfoldernew.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/align_left.svgz b/IconThemes/mono/scalable/actions/align_left.svgz
new file mode 100644
index 0000000..68596fb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/align_left.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/align_right.svgz b/IconThemes/mono/scalable/actions/align_right.svgz
new file mode 100644
index 0000000..18769d4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/align_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/alignobjs.svgz b/IconThemes/mono/scalable/actions/alignobjs.svgz
new file mode 100644
index 0000000..11a123e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/alignobjs.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/angle.svgz b/IconThemes/mono/scalable/actions/angle.svgz
new file mode 100644
index 0000000..9e5b3af
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/angle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/angle_bisector.svgz b/IconThemes/mono/scalable/actions/angle_bisector.svgz
new file mode 100644
index 0000000..faad718
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/angle_bisector.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/angle_size.svgz b/IconThemes/mono/scalable/actions/angle_size.svgz
new file mode 100644
index 0000000..d9c19ca
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/angle_size.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/answer.svgz b/IconThemes/mono/scalable/actions/answer.svgz
new file mode 100644
index 0000000..1e8a89e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/answer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aobottom.svgz b/IconThemes/mono/scalable/actions/aobottom.svgz
new file mode 100644
index 0000000..0a2f211
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aobottom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aocenterh.svgz b/IconThemes/mono/scalable/actions/aocenterh.svgz
new file mode 100644
index 0000000..c09d583
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aocenterh.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aocenterv.svgz b/IconThemes/mono/scalable/actions/aocenterv.svgz
new file mode 100644
index 0000000..a329558
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aocenterv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aogrid.svgz b/IconThemes/mono/scalable/actions/aogrid.svgz
new file mode 100644
index 0000000..5df47a3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aogrid.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aoleft.svgz b/IconThemes/mono/scalable/actions/aoleft.svgz
new file mode 100644
index 0000000..ee5423e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aoleft.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aopos2grid.svgz b/IconThemes/mono/scalable/actions/aopos2grid.svgz
new file mode 100644
index 0000000..c7a540b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aopos2grid.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aoright.svgz b/IconThemes/mono/scalable/actions/aoright.svgz
new file mode 100644
index 0000000..29d645e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aoright.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/aotop.svgz b/IconThemes/mono/scalable/actions/aotop.svgz
new file mode 100644
index 0000000..9cfd373
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/aotop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/appearance.svgz b/IconThemes/mono/scalable/actions/appearance.svgz
new file mode 100644
index 0000000..b78b9e6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/appearance.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/apply.svgz b/IconThemes/mono/scalable/actions/apply.svgz
new file mode 100644
index 0000000..b0f6d11
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/apply.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/appointment.svgz b/IconThemes/mono/scalable/actions/appointment.svgz
new file mode 100644
index 0000000..f34fbd2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/appointment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/arc.svgz b/IconThemes/mono/scalable/actions/arc.svgz
new file mode 100644
index 0000000..28ff053
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/arc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/arc_center.svgz b/IconThemes/mono/scalable/actions/arc_center.svgz
new file mode 100644
index 0000000..88e0dea
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/arc_center.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/areaCircle.svgz b/IconThemes/mono/scalable/actions/areaCircle.svgz
new file mode 100644
index 0000000..a1cffc2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/areaCircle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ark_adddir.svgz b/IconThemes/mono/scalable/actions/ark_adddir.svgz
new file mode 100644
index 0000000..2290aae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ark_adddir.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ark_addfile.svgz b/IconThemes/mono/scalable/actions/ark_addfile.svgz
new file mode 100644
index 0000000..f10355a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ark_addfile.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ark_delete.svgz b/IconThemes/mono/scalable/actions/ark_delete.svgz
new file mode 100644
index 0000000..52cd3bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ark_delete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ark_extract.svgz b/IconThemes/mono/scalable/actions/ark_extract.svgz
new file mode 100644
index 0000000..4e78ec3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ark_extract.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ark_selectall.svgz b/IconThemes/mono/scalable/actions/ark_selectall.svgz
new file mode 100644
index 0000000..e28bd32
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ark_selectall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ark_view.svgz b/IconThemes/mono/scalable/actions/ark_view.svgz
new file mode 100644
index 0000000..ea42289
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ark_view.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/arrange.svgz b/IconThemes/mono/scalable/actions/arrange.svgz
new file mode 100644
index 0000000..8b65db3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/arrange.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/arrow.svgz b/IconThemes/mono/scalable/actions/arrow.svgz
new file mode 100644
index 0000000..8507c6f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/arrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/arrowheads.svgz b/IconThemes/mono/scalable/actions/arrowheads.svgz
new file mode 100644
index 0000000..f01b060
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/arrowheads.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/artsaudiomanager.svgz b/IconThemes/mono/scalable/actions/artsaudiomanager.svgz
new file mode 100644
index 0000000..7c15936
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/artsaudiomanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/artsbuilderexecute.svgz b/IconThemes/mono/scalable/actions/artsbuilderexecute.svgz
new file mode 100644
index 0000000..4d96e21
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/artsbuilderexecute.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/artsenvironment.svgz b/IconThemes/mono/scalable/actions/artsenvironment.svgz
new file mode 100644
index 0000000..e69235b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/artsenvironment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/artsfftscope.svgz b/IconThemes/mono/scalable/actions/artsfftscope.svgz
new file mode 100644
index 0000000..695ee85
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/artsfftscope.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/artsmediatypes.svgz b/IconThemes/mono/scalable/actions/artsmediatypes.svgz
new file mode 100644
index 0000000..6dcfdff
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/artsmediatypes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/artsmidimanager.svgz b/IconThemes/mono/scalable/actions/artsmidimanager.svgz
new file mode 100644
index 0000000..28374b6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/artsmidimanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/atlantik_buy_estate.svgz b/IconThemes/mono/scalable/actions/atlantik_buy_estate.svgz
new file mode 100644
index 0000000..b5ed75c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/atlantik_buy_estate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/attach.svgz b/IconThemes/mono/scalable/actions/attach.svgz
new file mode 100644
index 0000000..387c741
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/attach.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/attacher.svgz b/IconThemes/mono/scalable/actions/attacher.svgz
new file mode 100644
index 0000000..227ae7f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/attacher.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/auction.svgz b/IconThemes/mono/scalable/actions/auction.svgz
new file mode 100644
index 0000000..b8978c6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/auction.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/audioscrobbler.svgz b/IconThemes/mono/scalable/actions/audioscrobbler.svgz
new file mode 100644
index 0000000..51604de
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/audioscrobbler.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/authenticate.svgz b/IconThemes/mono/scalable/actions/authenticate.svgz
new file mode 100644
index 0000000..d6aaf32
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/authenticate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/autodiff.svgz b/IconThemes/mono/scalable/actions/autodiff.svgz
new file mode 100644
index 0000000..37b156f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/autodiff.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/autoform.svgz b/IconThemes/mono/scalable/actions/autoform.svgz
new file mode 100644
index 0000000..a1adf92
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/autoform.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/autonumber.svgz b/IconThemes/mono/scalable/actions/autonumber.svgz
new file mode 100644
index 0000000..84a4ef6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/autonumber.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/babelfish.svgz b/IconThemes/mono/scalable/actions/babelfish.svgz
new file mode 100644
index 0000000..19d4360
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/babelfish.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/back.svgz b/IconThemes/mono/scalable/actions/back.svgz
new file mode 100644
index 0000000..f803a91
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/back.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/backup.svgz b/IconThemes/mono/scalable/actions/backup.svgz
new file mode 100644
index 0000000..4570a2e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/backup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/backup_section.svgz b/IconThemes/mono/scalable/actions/backup_section.svgz
new file mode 100644
index 0000000..c554d58
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/backup_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bank.svgz b/IconThemes/mono/scalable/actions/bank.svgz
new file mode 100644
index 0000000..5f4accd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bank.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bar0.svgz b/IconThemes/mono/scalable/actions/bar0.svgz
new file mode 100644
index 0000000..89b2aaf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bar0.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bar1.svgz b/IconThemes/mono/scalable/actions/bar1.svgz
new file mode 100644
index 0000000..1d2c34a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bar1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bar2.svgz b/IconThemes/mono/scalable/actions/bar2.svgz
new file mode 100644
index 0000000..258827b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bar2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bar3.svgz b/IconThemes/mono/scalable/actions/bar3.svgz
new file mode 100644
index 0000000..99ad34a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bar3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bar4.svgz b/IconThemes/mono/scalable/actions/bar4.svgz
new file mode 100644
index 0000000..f73e3b0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bar4.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bar5.svgz b/IconThemes/mono/scalable/actions/bar5.svgz
new file mode 100644
index 0000000..43edf6d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bar5.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bar6.svgz b/IconThemes/mono/scalable/actions/bar6.svgz
new file mode 100644
index 0000000..cc4534e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bar6.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/baseCircle.svgz b/IconThemes/mono/scalable/actions/baseCircle.svgz
new file mode 100644
index 0000000..ba9d6b2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/baseCircle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bell.svgz b/IconThemes/mono/scalable/actions/bell.svgz
new file mode 100644
index 0000000..f6023e1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bisection.svgz b/IconThemes/mono/scalable/actions/bisection.svgz
new file mode 100644
index 0000000..fa9d803
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bisection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/black_sum.svgz b/IconThemes/mono/scalable/actions/black_sum.svgz
new file mode 100644
index 0000000..027f26c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/black_sum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/blend.svgz b/IconThemes/mono/scalable/actions/blend.svgz
new file mode 100644
index 0000000..7e5ae23
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/blend.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bold.svgz b/IconThemes/mono/scalable/actions/bold.svgz
new file mode 100644
index 0000000..f0c44a3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bold.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bookmark.svgz b/IconThemes/mono/scalable/actions/bookmark.svgz
new file mode 100644
index 0000000..b7e6706
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bookmark.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bookmark_add.svgz b/IconThemes/mono/scalable/actions/bookmark_add.svgz
new file mode 100644
index 0000000..9f44939
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bookmark_add.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bookmark_folder.svgz b/IconThemes/mono/scalable/actions/bookmark_folder.svgz
new file mode 100644
index 0000000..bf4afde
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bookmark_folder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bookmark_toolbar.svgz b/IconThemes/mono/scalable/actions/bookmark_toolbar.svgz
new file mode 100644
index 0000000..a49d7cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bookmark_toolbar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bookmarks_list_add.svgz b/IconThemes/mono/scalable/actions/bookmarks_list_add.svgz
new file mode 100644
index 0000000..acbb258
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bookmarks_list_add.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_all.svgz b/IconThemes/mono/scalable/actions/border_all.svgz
new file mode 100644
index 0000000..b17c1fa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_all.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_bottom.svgz b/IconThemes/mono/scalable/actions/border_bottom.svgz
new file mode 100644
index 0000000..5589652
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_bottom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_fall.svgz b/IconThemes/mono/scalable/actions/border_fall.svgz
new file mode 100644
index 0000000..068a36f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_fall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_horizontal.svgz b/IconThemes/mono/scalable/actions/border_horizontal.svgz
new file mode 100644
index 0000000..f1d88ba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_horizontal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_inside.svgz b/IconThemes/mono/scalable/actions/border_inside.svgz
new file mode 100644
index 0000000..19e4d91
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_inside.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_left.svgz b/IconThemes/mono/scalable/actions/border_left.svgz
new file mode 100644
index 0000000..d4f8593
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_left.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_outline.svgz b/IconThemes/mono/scalable/actions/border_outline.svgz
new file mode 100644
index 0000000..c5e9581
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_outline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_remove.svgz b/IconThemes/mono/scalable/actions/border_remove.svgz
new file mode 100644
index 0000000..2892044
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_right.svgz b/IconThemes/mono/scalable/actions/border_right.svgz
new file mode 100644
index 0000000..fef252f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_top.svgz b/IconThemes/mono/scalable/actions/border_top.svgz
new file mode 100644
index 0000000..b2be86f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_top.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_up.svgz b/IconThemes/mono/scalable/actions/border_up.svgz
new file mode 100644
index 0000000..14c6bf0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_up.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/border_vertical.svgz b/IconThemes/mono/scalable/actions/border_vertical.svgz
new file mode 100644
index 0000000..0126dc3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/border_vertical.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/borderbottom.svgz b/IconThemes/mono/scalable/actions/borderbottom.svgz
new file mode 100644
index 0000000..a59b409
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/borderbottom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/borderleft.svgz b/IconThemes/mono/scalable/actions/borderleft.svgz
new file mode 100644
index 0000000..3e01fee
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/borderleft.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/borderoutline.svgz b/IconThemes/mono/scalable/actions/borderoutline.svgz
new file mode 100644
index 0000000..cc6019d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/borderoutline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/borderright.svgz b/IconThemes/mono/scalable/actions/borderright.svgz
new file mode 100644
index 0000000..203bf17
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/borderright.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bordertool.svgz b/IconThemes/mono/scalable/actions/bordertool.svgz
new file mode 100644
index 0000000..c16b97a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bordertool.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bordertop.svgz b/IconThemes/mono/scalable/actions/bordertop.svgz
new file mode 100644
index 0000000..b243403
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bordertop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bottom.svgz b/IconThemes/mono/scalable/actions/bottom.svgz
new file mode 100644
index 0000000..b8866d0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bottom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/brackets.svgz b/IconThemes/mono/scalable/actions/brackets.svgz
new file mode 100644
index 0000000..886111e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/brackets.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/brightness.svgz b/IconThemes/mono/scalable/actions/brightness.svgz
new file mode 100644
index 0000000..f42e036
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/brightness.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bring_forward.svgz b/IconThemes/mono/scalable/actions/bring_forward.svgz
new file mode 100644
index 0000000..de73f83
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bring_forward.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bring_stencil_to_front.svgz b/IconThemes/mono/scalable/actions/bring_stencil_to_front.svgz
new file mode 100644
index 0000000..dc4adaa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bring_stencil_to_front.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/bug.svgz b/IconThemes/mono/scalable/actions/bug.svgz
new file mode 100644
index 0000000..9422d8d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/bug.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/business_user.svgz b/IconThemes/mono/scalable/actions/business_user.svgz
new file mode 100644
index 0000000..1a627e0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/business_user.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/button.svgz b/IconThemes/mono/scalable/actions/button.svgz
new file mode 100644
index 0000000..a92cb8f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/button.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/button_cancel.svgz b/IconThemes/mono/scalable/actions/button_cancel.svgz
new file mode 100644
index 0000000..980276a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/button_cancel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/button_fewer.svgz b/IconThemes/mono/scalable/actions/button_fewer.svgz
new file mode 100644
index 0000000..d705064
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/button_fewer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/button_more.svgz b/IconThemes/mono/scalable/actions/button_more.svgz
new file mode 100644
index 0000000..d355d9b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/button_more.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/button_ok.svgz b/IconThemes/mono/scalable/actions/button_ok.svgz
new file mode 100644
index 0000000..7c88b9a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/button_ok.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/calculate.svgz b/IconThemes/mono/scalable/actions/calculate.svgz
new file mode 100644
index 0000000..e02417a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/calculate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/camera.svgz b/IconThemes/mono/scalable/actions/camera.svgz
new file mode 100644
index 0000000..638b9e5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/camera.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/camera_test.svgz b/IconThemes/mono/scalable/actions/camera_test.svgz
new file mode 100644
index 0000000..3d9ccf1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/camera_test.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cancel.svgz b/IconThemes/mono/scalable/actions/cancel.svgz
new file mode 100644
index 0000000..1060c82
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cancel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cap_butt.svgz b/IconThemes/mono/scalable/actions/cap_butt.svgz
new file mode 100644
index 0000000..80d8a8f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cap_butt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cap_round.svgz b/IconThemes/mono/scalable/actions/cap_round.svgz
new file mode 100644
index 0000000..58de563
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cap_round.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cap_square.svgz b/IconThemes/mono/scalable/actions/cap_square.svgz
new file mode 100644
index 0000000..95dbfde
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cap_square.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/casesensitive.svgz b/IconThemes/mono/scalable/actions/casesensitive.svgz
new file mode 100644
index 0000000..66ad79e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/casesensitive.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/catalogmanager.svgz b/IconThemes/mono/scalable/actions/catalogmanager.svgz
new file mode 100644
index 0000000..dd4e581
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/catalogmanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cd.svgz b/IconThemes/mono/scalable/actions/cd.svgz
new file mode 100644
index 0000000..cb9ed84
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cdburn.svgz b/IconThemes/mono/scalable/actions/cdburn.svgz
new file mode 100644
index 0000000..1d0c2fc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cdburn.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cdcopy.svgz b/IconThemes/mono/scalable/actions/cdcopy.svgz
new file mode 100644
index 0000000..80abb6c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cdcopy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cdinfo.svgz b/IconThemes/mono/scalable/actions/cdinfo.svgz
new file mode 100644
index 0000000..2667a71
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cdinfo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cdrwblank.svgz b/IconThemes/mono/scalable/actions/cdrwblank.svgz
new file mode 100644
index 0000000..8b277d2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cdrwblank.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cdsmall.svgz b/IconThemes/mono/scalable/actions/cdsmall.svgz
new file mode 100644
index 0000000..241ca39
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cdsmall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cdtje.svgz b/IconThemes/mono/scalable/actions/cdtje.svgz
new file mode 100644
index 0000000..0b62c41
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cdtje.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cell_edit.svgz b/IconThemes/mono/scalable/actions/cell_edit.svgz
new file mode 100644
index 0000000..e051f7c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cell_edit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cell_layout.svgz b/IconThemes/mono/scalable/actions/cell_layout.svgz
new file mode 100644
index 0000000..71bcac3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cell_layout.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/centerofcurvature.svgz b/IconThemes/mono/scalable/actions/centerofcurvature.svgz
new file mode 100644
index 0000000..f4f0374
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/centerofcurvature.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/centralsymmetry.svgz b/IconThemes/mono/scalable/actions/centralsymmetry.svgz
new file mode 100644
index 0000000..405d0c9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/centralsymmetry.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/centrejust.svgz b/IconThemes/mono/scalable/actions/centrejust.svgz
new file mode 100644
index 0000000..93841d5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/centrejust.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/char.svgz b/IconThemes/mono/scalable/actions/char.svgz
new file mode 100644
index 0000000..cc8c6fd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/char.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/charset.svgz b/IconThemes/mono/scalable/actions/charset.svgz
new file mode 100644
index 0000000..f9dc091
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/charset.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart.svgz b/IconThemes/mono/scalable/actions/chart.svgz
new file mode 100644
index 0000000..da86a78
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_area.svgz b/IconThemes/mono/scalable/actions/chart_area.svgz
new file mode 100644
index 0000000..c100554
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_area.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_area_3d.svgz b/IconThemes/mono/scalable/actions/chart_area_3d.svgz
new file mode 100644
index 0000000..9e14157
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_area_3d.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_bar.svgz b/IconThemes/mono/scalable/actions/chart_bar.svgz
new file mode 100644
index 0000000..32d7827
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_bar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_bar_3d.svgz b/IconThemes/mono/scalable/actions/chart_bar_3d.svgz
new file mode 100644
index 0000000..2933850
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_bar_3d.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_boxwhisker.svgz b/IconThemes/mono/scalable/actions/chart_boxwhisker.svgz
new file mode 100644
index 0000000..8c68a73
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_boxwhisker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_hilo.svgz b/IconThemes/mono/scalable/actions/chart_hilo.svgz
new file mode 100644
index 0000000..d809672
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_hilo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_bottom.svgz b/IconThemes/mono/scalable/actions/chart_legend_bottom.svgz
new file mode 100644
index 0000000..9afb6db
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_bottom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_bottomleft.svgz b/IconThemes/mono/scalable/actions/chart_legend_bottomleft.svgz
new file mode 100644
index 0000000..482f096
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_bottomleft.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_bottomright.svgz b/IconThemes/mono/scalable/actions/chart_legend_bottomright.svgz
new file mode 100644
index 0000000..5fe5203
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_bottomright.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_left.svgz b/IconThemes/mono/scalable/actions/chart_legend_left.svgz
new file mode 100644
index 0000000..9d9b5f7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_left.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_nolegend.svgz b/IconThemes/mono/scalable/actions/chart_legend_nolegend.svgz
new file mode 100644
index 0000000..e7851c8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_nolegend.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_right.svgz b/IconThemes/mono/scalable/actions/chart_legend_right.svgz
new file mode 100644
index 0000000..d4b05db
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_top.svgz b/IconThemes/mono/scalable/actions/chart_legend_top.svgz
new file mode 100644
index 0000000..28dc0c6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_top.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_topleft.svgz b/IconThemes/mono/scalable/actions/chart_legend_topleft.svgz
new file mode 100644
index 0000000..68120bb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_topleft.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_legend_topright.svgz b/IconThemes/mono/scalable/actions/chart_legend_topright.svgz
new file mode 100644
index 0000000..2e9343d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_legend_topright.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_line.svgz b/IconThemes/mono/scalable/actions/chart_line.svgz
new file mode 100644
index 0000000..1f30720
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_line.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_line_3d.svgz b/IconThemes/mono/scalable/actions/chart_line_3d.svgz
new file mode 100644
index 0000000..1b3e301
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_line_3d.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_pie.svgz b/IconThemes/mono/scalable/actions/chart_pie.svgz
new file mode 100644
index 0000000..9bf92a5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_pie.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_pie_3d.svgz b/IconThemes/mono/scalable/actions/chart_pie_3d.svgz
new file mode 100644
index 0000000..b0af341
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_pie_3d.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_polar.svgz b/IconThemes/mono/scalable/actions/chart_polar.svgz
new file mode 100644
index 0000000..c910567
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_polar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chart_ring.svgz b/IconThemes/mono/scalable/actions/chart_ring.svgz
new file mode 100644
index 0000000..37cb31c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chart_ring.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chat.svgz b/IconThemes/mono/scalable/actions/chat.svgz
new file mode 100644
index 0000000..d8355b9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/check.svgz b/IconThemes/mono/scalable/actions/check.svgz
new file mode 100644
index 0000000..50872c5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/check.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/checkedbox.svgz b/IconThemes/mono/scalable/actions/checkedbox.svgz
new file mode 100644
index 0000000..a7c9729
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/checkedbox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/checkmark.svgz b/IconThemes/mono/scalable/actions/checkmark.svgz
new file mode 100644
index 0000000..e94dff5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/checkmark.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/chemical.svgz b/IconThemes/mono/scalable/actions/chemical.svgz
new file mode 100644
index 0000000..185e49a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/chemical.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/circle.svgz b/IconThemes/mono/scalable/actions/circle.svgz
new file mode 100644
index 0000000..c23c22a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/circle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/circlebcl.svgz b/IconThemes/mono/scalable/actions/circlebcl.svgz
new file mode 100644
index 0000000..775f839
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/circlebcl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/circlebcp.svgz b/IconThemes/mono/scalable/actions/circlebcp.svgz
new file mode 100644
index 0000000..419c13e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/circlebcp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/circlebpd.svgz b/IconThemes/mono/scalable/actions/circlebpd.svgz
new file mode 100644
index 0000000..20940f8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/circlebpd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/circlebps.svgz b/IconThemes/mono/scalable/actions/circlebps.svgz
new file mode 100644
index 0000000..55de96f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/circlebps.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/circlebtp.svgz b/IconThemes/mono/scalable/actions/circlebtp.svgz
new file mode 100644
index 0000000..323ddf2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/circlebtp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/circlelineintersection.svgz b/IconThemes/mono/scalable/actions/circlelineintersection.svgz
new file mode 100644
index 0000000..06b3ac5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/circlelineintersection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/circumference.svgz b/IconThemes/mono/scalable/actions/circumference.svgz
new file mode 100644
index 0000000..bfdc6cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/circumference.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/clear_left.svgz b/IconThemes/mono/scalable/actions/clear_left.svgz
new file mode 100644
index 0000000..9cd5e6b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/clear_left.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/clipart.svgz b/IconThemes/mono/scalable/actions/clipart.svgz
new file mode 100644
index 0000000..66de38d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/clipart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/clipart_from_file.svgz b/IconThemes/mono/scalable/actions/clipart_from_file.svgz
new file mode 100644
index 0000000..9d7f8bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/clipart_from_file.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/close.svgz b/IconThemes/mono/scalable/actions/close.svgz
new file mode 100644
index 0000000..a3f298a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/close.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/closed_cubicbeziercurve.svgz b/IconThemes/mono/scalable/actions/closed_cubicbeziercurve.svgz
new file mode 100644
index 0000000..d3eaccf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/closed_cubicbeziercurve.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/closed_freehand.svgz b/IconThemes/mono/scalable/actions/closed_freehand.svgz
new file mode 100644
index 0000000..75c995f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/closed_freehand.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/closed_polyline.svgz b/IconThemes/mono/scalable/actions/closed_polyline.svgz
new file mode 100644
index 0000000..6eb1910
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/closed_polyline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/closed_quadricbeziercurve.svgz b/IconThemes/mono/scalable/actions/closed_quadricbeziercurve.svgz
new file mode 100644
index 0000000..731b24a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/closed_quadricbeziercurve.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/collection.svgz b/IconThemes/mono/scalable/actions/collection.svgz
new file mode 100644
index 0000000..fd5cf88
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/collection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/color_fill.svgz b/IconThemes/mono/scalable/actions/color_fill.svgz
new file mode 100644
index 0000000..86c6d36
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/color_fill.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/color_line.svgz b/IconThemes/mono/scalable/actions/color_line.svgz
new file mode 100644
index 0000000..49076ee
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/color_line.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/colorize.svgz b/IconThemes/mono/scalable/actions/colorize.svgz
new file mode 100644
index 0000000..9918491
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/colorize.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/colorman.svgz b/IconThemes/mono/scalable/actions/colorman.svgz
new file mode 100644
index 0000000..ed07026
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/colorman.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/colorpicker.svgz b/IconThemes/mono/scalable/actions/colorpicker.svgz
new file mode 100644
index 0000000..8ba5723
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/colorpicker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/combo.svgz b/IconThemes/mono/scalable/actions/combo.svgz
new file mode 100644
index 0000000..c3a0e2d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/combo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/comment.svgz b/IconThemes/mono/scalable/actions/comment.svgz
new file mode 100644
index 0000000..0b1fd90
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/comment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/compfile.svgz b/IconThemes/mono/scalable/actions/compfile.svgz
new file mode 100644
index 0000000..b44aff9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/compfile.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/completion.svgz b/IconThemes/mono/scalable/actions/completion.svgz
new file mode 100644
index 0000000..c0bb515
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/completion.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/configure.svgz b/IconThemes/mono/scalable/actions/configure.svgz
new file mode 100644
index 0000000..8075b3a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/configure.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/configure_shortcuts.svgz b/IconThemes/mono/scalable/actions/configure_shortcuts.svgz
new file mode 100644
index 0000000..a419e11
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/configure_shortcuts.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/configure_toolbars.svgz b/IconThemes/mono/scalable/actions/configure_toolbars.svgz
new file mode 100644
index 0000000..9867bf5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/configure_toolbars.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/conicasymptotes.svgz b/IconThemes/mono/scalable/actions/conicasymptotes.svgz
new file mode 100644
index 0000000..e36e48e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/conicasymptotes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/conicb5p.svgz b/IconThemes/mono/scalable/actions/conicb5p.svgz
new file mode 100644
index 0000000..85f22f7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/conicb5p.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/coniclineintersection.svgz b/IconThemes/mono/scalable/actions/coniclineintersection.svgz
new file mode 100644
index 0000000..7a98ab1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/coniclineintersection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/conicsradicalline.svgz b/IconThemes/mono/scalable/actions/conicsradicalline.svgz
new file mode 100644
index 0000000..00ebe86
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/conicsradicalline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/connect_creating.svgz b/IconThemes/mono/scalable/actions/connect_creating.svgz
new file mode 100644
index 0000000..c91f5e1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/connect_creating.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/connect_established.svgz b/IconThemes/mono/scalable/actions/connect_established.svgz
new file mode 100644
index 0000000..07b9884
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/connect_established.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/connect_no.svgz b/IconThemes/mono/scalable/actions/connect_no.svgz
new file mode 100644
index 0000000..148618f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/connect_no.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/contents.svgz b/IconThemes/mono/scalable/actions/contents.svgz
new file mode 100644
index 0000000..380b273
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/contents.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/contents2.svgz b/IconThemes/mono/scalable/actions/contents2.svgz
new file mode 100644
index 0000000..865a891
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/contents2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/contexthelp.svgz b/IconThemes/mono/scalable/actions/contexthelp.svgz
new file mode 100644
index 0000000..00b1157
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/contexthelp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/contrast.svgz b/IconThemes/mono/scalable/actions/contrast.svgz
new file mode 100644
index 0000000..0a8f775
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/contrast.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/control.svgz b/IconThemes/mono/scalable/actions/control.svgz
new file mode 100644
index 0000000..f787cf4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/control.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/convexhull.svgz b/IconThemes/mono/scalable/actions/convexhull.svgz
new file mode 100644
index 0000000..834926e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/convexhull.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/coords.svgz b/IconThemes/mono/scalable/actions/coords.svgz
new file mode 100644
index 0000000..faaf1bb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/coords.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/copy.svgz b/IconThemes/mono/scalable/actions/copy.svgz
new file mode 100644
index 0000000..7796d36
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/copy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/copy_stencil.svgz b/IconThemes/mono/scalable/actions/copy_stencil.svgz
new file mode 100644
index 0000000..0e94c0c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/copy_stencil.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/covermanager.svgz b/IconThemes/mono/scalable/actions/covermanager.svgz
new file mode 100644
index 0000000..30bbedb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/covermanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cpufreq_100.svgz b/IconThemes/mono/scalable/actions/cpufreq_100.svgz
new file mode 100644
index 0000000..331a44f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cpufreq_100.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cpufreq_25.svgz b/IconThemes/mono/scalable/actions/cpufreq_25.svgz
new file mode 100644
index 0000000..b17e7d0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cpufreq_25.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cpufreq_50.svgz b/IconThemes/mono/scalable/actions/cpufreq_50.svgz
new file mode 100644
index 0000000..afd65c1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cpufreq_50.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cpufreq_75.svgz b/IconThemes/mono/scalable/actions/cpufreq_75.svgz
new file mode 100644
index 0000000..9c30cff
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cpufreq_75.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cpufreq_na.svgz b/IconThemes/mono/scalable/actions/cpufreq_na.svgz
new file mode 100644
index 0000000..78b5fb2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cpufreq_na.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/crop.svgz b/IconThemes/mono/scalable/actions/crop.svgz
new file mode 100644
index 0000000..f00f7bf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/crop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/css.svgz b/IconThemes/mono/scalable/actions/css.svgz
new file mode 100644
index 0000000..d29f2d4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/css.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cssvalidator.svgz b/IconThemes/mono/scalable/actions/cssvalidator.svgz
new file mode 100644
index 0000000..d29f2d4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cssvalidator.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cubicbeziercurve.svgz b/IconThemes/mono/scalable/actions/cubicbeziercurve.svgz
new file mode 100644
index 0000000..a5dc79b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cubicbeziercurve.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/curvelineintersection.svgz b/IconThemes/mono/scalable/actions/curvelineintersection.svgz
new file mode 100644
index 0000000..582ee9d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/curvelineintersection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cut.svgz b/IconThemes/mono/scalable/actions/cut.svgz
new file mode 100644
index 0000000..e9c1774
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cut.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/cut_stencil.svgz b/IconThemes/mono/scalable/actions/cut_stencil.svgz
new file mode 100644
index 0000000..0b091fe
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/cut_stencil.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/data.svgz b/IconThemes/mono/scalable/actions/data.svgz
new file mode 100644
index 0000000..bba01cf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/data.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/dateedit.svgz b/IconThemes/mono/scalable/actions/dateedit.svgz
new file mode 100644
index 0000000..583c48a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/dateedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/datetimeedit.svgz b/IconThemes/mono/scalable/actions/datetimeedit.svgz
new file mode 100644
index 0000000..7cf1d40
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/datetimeedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/dayview.svgz b/IconThemes/mono/scalable/actions/dayview.svgz
new file mode 100644
index 0000000..72b55e5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/dayview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/db.svgz b/IconThemes/mono/scalable/actions/db.svgz
new file mode 100644
index 0000000..9f1da4d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/db.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/decrypted.svgz b/IconThemes/mono/scalable/actions/decrypted.svgz
new file mode 100644
index 0000000..d3fc0e3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/decrypted.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/define_clip.svgz b/IconThemes/mono/scalable/actions/define_clip.svgz
new file mode 100644
index 0000000..c6220da
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/define_clip.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/delete.svgz b/IconThemes/mono/scalable/actions/delete.svgz
new file mode 100644
index 0000000..0647ce3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/delete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/delete_group.svgz b/IconThemes/mono/scalable/actions/delete_group.svgz
new file mode 100644
index 0000000..92164bb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/delete_group.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/delete_table.svgz b/IconThemes/mono/scalable/actions/delete_table.svgz
new file mode 100644
index 0000000..4344b1b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/delete_table.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/delete_table_col.svgz b/IconThemes/mono/scalable/actions/delete_table_col.svgz
new file mode 100644
index 0000000..1435f57
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/delete_table_col.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/delete_table_row.svgz b/IconThemes/mono/scalable/actions/delete_table_row.svgz
new file mode 100644
index 0000000..d0bd878
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/delete_table_row.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/delete_user.svgz b/IconThemes/mono/scalable/actions/delete_user.svgz
new file mode 100644
index 0000000..8244d8d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/delete_user.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/deletecell.svgz b/IconThemes/mono/scalable/actions/deletecell.svgz
new file mode 100644
index 0000000..8b777b6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/deletecell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/deletelayer.svgz b/IconThemes/mono/scalable/actions/deletelayer.svgz
new file mode 100644
index 0000000..11b87c8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/deletelayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/delquestion.svgz b/IconThemes/mono/scalable/actions/delquestion.svgz
new file mode 100644
index 0000000..f9bc92d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/delquestion.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/delslide.svgz b/IconThemes/mono/scalable/actions/delslide.svgz
new file mode 100644
index 0000000..dac1b4e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/delslide.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/deriv_func.svgz b/IconThemes/mono/scalable/actions/deriv_func.svgz
new file mode 100644
index 0000000..a4d17f3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/deriv_func.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/diff.svgz b/IconThemes/mono/scalable/actions/diff.svgz
new file mode 100644
index 0000000..a9d9baa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/diff.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/digikamimageplugins.svgz b/IconThemes/mono/scalable/actions/digikamimageplugins.svgz
new file mode 100644
index 0000000..a6c805b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/digikamimageplugins.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/digitalcam.svgz b/IconThemes/mono/scalable/actions/digitalcam.svgz
new file mode 100644
index 0000000..96f61c0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/digitalcam.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/directrix.svgz b/IconThemes/mono/scalable/actions/directrix.svgz
new file mode 100644
index 0000000..f1ad1f6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/directrix.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/dirsynch.svgz b/IconThemes/mono/scalable/actions/dirsynch.svgz
new file mode 100644
index 0000000..d733ea9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/dirsynch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/dirsynch_new.svgz b/IconThemes/mono/scalable/actions/dirsynch_new.svgz
new file mode 100644
index 0000000..116c4c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/dirsynch_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/dissociatecell.svgz b/IconThemes/mono/scalable/actions/dissociatecell.svgz
new file mode 100644
index 0000000..6d0d1fa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/dissociatecell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/distance.svgz b/IconThemes/mono/scalable/actions/distance.svgz
new file mode 100644
index 0000000..49ef480
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/distance.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/div_center.svgz b/IconThemes/mono/scalable/actions/div_center.svgz
new file mode 100644
index 0000000..51f686b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/div_center.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/div_justify.svgz b/IconThemes/mono/scalable/actions/div_justify.svgz
new file mode 100644
index 0000000..683949d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/div_justify.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/div_left.svgz b/IconThemes/mono/scalable/actions/div_left.svgz
new file mode 100644
index 0000000..8a753ac
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/div_left.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/div_right.svgz b/IconThemes/mono/scalable/actions/div_right.svgz
new file mode 100644
index 0000000..4c6e52c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/div_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/documentinfo.svgz b/IconThemes/mono/scalable/actions/documentinfo.svgz
new file mode 100644
index 0000000..9d3c82b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/documentinfo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/domtreeviewer.svgz b/IconThemes/mono/scalable/actions/domtreeviewer.svgz
new file mode 100644
index 0000000..a3a67c0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/domtreeviewer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/dontknow.svgz b/IconThemes/mono/scalable/actions/dontknow.svgz
new file mode 100644
index 0000000..1ca62ec
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/dontknow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/down.svgz b/IconThemes/mono/scalable/actions/down.svgz
new file mode 100644
index 0000000..a68c425
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/down.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/duringbreaks.svgz b/IconThemes/mono/scalable/actions/duringbreaks.svgz
new file mode 100644
index 0000000..b365182
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/duringbreaks.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/dynamic.svgz b/IconThemes/mono/scalable/actions/dynamic.svgz
new file mode 100644
index 0000000..056cb46
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/dynamic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit.svgz b/IconThemes/mono/scalable/actions/edit.svgz
new file mode 100644
index 0000000..b2db4bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit_add.svgz b/IconThemes/mono/scalable/actions/edit_add.svgz
new file mode 100644
index 0000000..e7972c2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit_add.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit_copy.svgz b/IconThemes/mono/scalable/actions/edit_copy.svgz
new file mode 100644
index 0000000..dad1adb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit_copy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit_group.svgz b/IconThemes/mono/scalable/actions/edit_group.svgz
new file mode 100644
index 0000000..2732649
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit_group.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit_picture.svgz b/IconThemes/mono/scalable/actions/edit_picture.svgz
new file mode 100644
index 0000000..a2fb458
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit_picture.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit_pie.svgz b/IconThemes/mono/scalable/actions/edit_pie.svgz
new file mode 100644
index 0000000..f1c7d8b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit_pie.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit_polygon.svgz b/IconThemes/mono/scalable/actions/edit_polygon.svgz
new file mode 100644
index 0000000..c693649
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit_polygon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit_remove.svgz b/IconThemes/mono/scalable/actions/edit_remove.svgz
new file mode 100644
index 0000000..28118cf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit_remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edit_user.svgz b/IconThemes/mono/scalable/actions/edit_user.svgz
new file mode 100644
index 0000000..efc84bb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edit_user.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editclear.svgz b/IconThemes/mono/scalable/actions/editclear.svgz
new file mode 100644
index 0000000..a747d04
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editclear.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editconstants.svgz b/IconThemes/mono/scalable/actions/editconstants.svgz
new file mode 100644
index 0000000..3a1e923
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editconstants.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editcopy.svgz b/IconThemes/mono/scalable/actions/editcopy.svgz
new file mode 100644
index 0000000..9b96ee8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editcopy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editcut.svgz b/IconThemes/mono/scalable/actions/editcut.svgz
new file mode 100644
index 0000000..3b481d9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editcut.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editdelete.svgz b/IconThemes/mono/scalable/actions/editdelete.svgz
new file mode 100644
index 0000000..c6280d8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editdelete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editimage.svgz b/IconThemes/mono/scalable/actions/editimage.svgz
new file mode 100644
index 0000000..873b7ac
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editimage.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editor.svgz b/IconThemes/mono/scalable/actions/editor.svgz
new file mode 100644
index 0000000..e2c3c07
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editpaste.svgz b/IconThemes/mono/scalable/actions/editpaste.svgz
new file mode 100644
index 0000000..c7e21c6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editpaste.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editplots.svgz b/IconThemes/mono/scalable/actions/editplots.svgz
new file mode 100644
index 0000000..f3c8ca3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editplots.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editquestion.svgz b/IconThemes/mono/scalable/actions/editquestion.svgz
new file mode 100644
index 0000000..09ab4c9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editquestion.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/editshred.svgz b/IconThemes/mono/scalable/actions/editshred.svgz
new file mode 100644
index 0000000..229c712
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/editshred.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/edittrash.svgz b/IconThemes/mono/scalable/actions/edittrash.svgz
new file mode 100644
index 0000000..9e57672
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/edittrash.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/effect.svgz b/IconThemes/mono/scalable/actions/effect.svgz
new file mode 100644
index 0000000..901780e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/effect.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/elempic.svgz b/IconThemes/mono/scalable/actions/elempic.svgz
new file mode 100644
index 0000000..17f9bd6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/elempic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ellipse.svgz b/IconThemes/mono/scalable/actions/ellipse.svgz
new file mode 100644
index 0000000..e0ea2ba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ellipse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ellipsebffp.svgz b/IconThemes/mono/scalable/actions/ellipsebffp.svgz
new file mode 100644
index 0000000..6f66551
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ellipsebffp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/emoticon.svgz b/IconThemes/mono/scalable/actions/emoticon.svgz
new file mode 100644
index 0000000..5ea78df
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/emoticon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/emptybox.svgz b/IconThemes/mono/scalable/actions/emptybox.svgz
new file mode 100644
index 0000000..33c3a91
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/emptybox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/emptytrash.svgz b/IconThemes/mono/scalable/actions/emptytrash.svgz
new file mode 100644
index 0000000..e3a7149
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/emptytrash.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/en.svgz b/IconThemes/mono/scalable/actions/en.svgz
new file mode 100644
index 0000000..b977f93
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/en.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/encrypted.svgz b/IconThemes/mono/scalable/actions/encrypted.svgz
new file mode 100644
index 0000000..8079d31
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/encrypted.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/endturn.svgz b/IconThemes/mono/scalable/actions/endturn.svgz
new file mode 100644
index 0000000..b60ffc0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/endturn.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/energies.svgz b/IconThemes/mono/scalable/actions/energies.svgz
new file mode 100644
index 0000000..ec94608
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/energies.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/enumList.svgz b/IconThemes/mono/scalable/actions/enumList.svgz
new file mode 100644
index 0000000..7484f8f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/enumList.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/enum_list.svgz b/IconThemes/mono/scalable/actions/enum_list.svgz
new file mode 100644
index 0000000..d63e563
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/enum_list.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/eqchem.svgz b/IconThemes/mono/scalable/actions/eqchem.svgz
new file mode 100644
index 0000000..2346842
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/eqchem.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/equalizer.svgz b/IconThemes/mono/scalable/actions/equalizer.svgz
new file mode 100644
index 0000000..f9f5c65
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/equalizer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/equilateralhyperbolab4p.svgz b/IconThemes/mono/scalable/actions/equilateralhyperbolab4p.svgz
new file mode 100644
index 0000000..6aff0b2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/equilateralhyperbolab4p.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/equitriangle.svgz b/IconThemes/mono/scalable/actions/equitriangle.svgz
new file mode 100644
index 0000000..0f71c1b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/equitriangle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/eraser.svgz b/IconThemes/mono/scalable/actions/eraser.svgz
new file mode 100644
index 0000000..84bed3c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/eraser.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/error.svgz b/IconThemes/mono/scalable/actions/error.svgz
new file mode 100644
index 0000000..0a2bf93
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/error.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/exclamation.svgz b/IconThemes/mono/scalable/actions/exclamation.svgz
new file mode 100644
index 0000000..62778a8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/exclamation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/exec.svgz b/IconThemes/mono/scalable/actions/exec.svgz
new file mode 100644
index 0000000..c4ab4c9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/exec.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/exifinfo.svgz b/IconThemes/mono/scalable/actions/exifinfo.svgz
new file mode 100644
index 0000000..b009bcf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/exifinfo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/exit.svgz b/IconThemes/mono/scalable/actions/exit.svgz
new file mode 100644
index 0000000..802ed30
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/exit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/favorites.svgz b/IconThemes/mono/scalable/actions/favorites.svgz
new file mode 100644
index 0000000..ecef248
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/favorites.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/file.svgz b/IconThemes/mono/scalable/actions/file.svgz
new file mode 100644
index 0000000..66d992a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/file.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/file_transfer_section.svgz b/IconThemes/mono/scalable/actions/file_transfer_section.svgz
new file mode 100644
index 0000000..75ca916
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/file_transfer_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fileblend.svgz b/IconThemes/mono/scalable/actions/fileblend.svgz
new file mode 100644
index 0000000..3603eae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fileblend.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fileclose.svgz b/IconThemes/mono/scalable/actions/fileclose.svgz
new file mode 100644
index 0000000..1b10b79
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fileclose.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fileexport.svgz b/IconThemes/mono/scalable/actions/fileexport.svgz
new file mode 100644
index 0000000..7832fc1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fileexport.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filefind.svgz b/IconThemes/mono/scalable/actions/filefind.svgz
new file mode 100644
index 0000000..7ecce07
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filefind.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fileimport.svgz b/IconThemes/mono/scalable/actions/fileimport.svgz
new file mode 100644
index 0000000..a63c325
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fileimport.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filenew.svgz b/IconThemes/mono/scalable/actions/filenew.svgz
new file mode 100644
index 0000000..4c245f4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filenew.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fileopen.svgz b/IconThemes/mono/scalable/actions/fileopen.svgz
new file mode 100644
index 0000000..d8c773e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fileopen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fileopenurl.svgz b/IconThemes/mono/scalable/actions/fileopenurl.svgz
new file mode 100644
index 0000000..dba4647
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fileopenurl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fileprint.svgz b/IconThemes/mono/scalable/actions/fileprint.svgz
new file mode 100644
index 0000000..e8baf6a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fileprint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filequickprint.svgz b/IconThemes/mono/scalable/actions/filequickprint.svgz
new file mode 100644
index 0000000..ac32803
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filequickprint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filereplace.svgz b/IconThemes/mono/scalable/actions/filereplace.svgz
new file mode 100644
index 0000000..4ff7005
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filereplace.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filesave.svgz b/IconThemes/mono/scalable/actions/filesave.svgz
new file mode 100644
index 0000000..b215abf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filesave.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filesaveas.svgz b/IconThemes/mono/scalable/actions/filesaveas.svgz
new file mode 100644
index 0000000..daa9d75
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filesaveas.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filesimulate.svgz b/IconThemes/mono/scalable/actions/filesimulate.svgz
new file mode 100644
index 0000000..15d970f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filesimulate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filestop.svgz b/IconThemes/mono/scalable/actions/filestop.svgz
new file mode 100644
index 0000000..8c8166e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filestop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fill.svgz b/IconThemes/mono/scalable/actions/fill.svgz
new file mode 100644
index 0000000..5f4202d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fill.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fill_colour.svgz b/IconThemes/mono/scalable/actions/fill_colour.svgz
new file mode 100644
index 0000000..9172350
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fill_colour.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filledcircle.svgz b/IconThemes/mono/scalable/actions/filledcircle.svgz
new file mode 100644
index 0000000..06f8f5d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filledcircle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filledellipse.svgz b/IconThemes/mono/scalable/actions/filledellipse.svgz
new file mode 100644
index 0000000..0feebaf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filledellipse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filledrectangle.svgz b/IconThemes/mono/scalable/actions/filledrectangle.svgz
new file mode 100644
index 0000000..f70939f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filledrectangle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filter.svgz b/IconThemes/mono/scalable/actions/filter.svgz
new file mode 100644
index 0000000..0a5bbc8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/filterstop.svgz b/IconThemes/mono/scalable/actions/filterstop.svgz
new file mode 100644
index 0000000..0bff256
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/filterstop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/find.svgz b/IconThemes/mono/scalable/actions/find.svgz
new file mode 100644
index 0000000..a63fe42
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/find.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/findf.svgz b/IconThemes/mono/scalable/actions/findf.svgz
new file mode 100644
index 0000000..9704b6d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/findf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/finish.svgz b/IconThemes/mono/scalable/actions/finish.svgz
new file mode 100644
index 0000000..7cd001b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/finish.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/first_letter_upper.svgz b/IconThemes/mono/scalable/actions/first_letter_upper.svgz
new file mode 100644
index 0000000..cb1f73c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/first_letter_upper.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/flag.svgz b/IconThemes/mono/scalable/actions/flag.svgz
new file mode 100644
index 0000000..502dce3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/flag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/flash.svgz b/IconThemes/mono/scalable/actions/flash.svgz
new file mode 100644
index 0000000..c085d52
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/flash.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/flightevaluation.svgz b/IconThemes/mono/scalable/actions/flightevaluation.svgz
new file mode 100644
index 0000000..e4fec6e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/flightevaluation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/flip.svgz b/IconThemes/mono/scalable/actions/flip.svgz
new file mode 100644
index 0000000..faa1af6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/flip.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/folder.svgz b/IconThemes/mono/scalable/actions/folder.svgz
new file mode 100644
index 0000000..a7d8747
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/folder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/folder_closed.svgz b/IconThemes/mono/scalable/actions/folder_closed.svgz
new file mode 100644
index 0000000..9661030
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/folder_closed.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/folder_grey.svgz b/IconThemes/mono/scalable/actions/folder_grey.svgz
new file mode 100644
index 0000000..ae76ecc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/folder_grey.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/folder_new.svgz b/IconThemes/mono/scalable/actions/folder_new.svgz
new file mode 100644
index 0000000..599b3a6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/folder_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/folder_open.svgz b/IconThemes/mono/scalable/actions/folder_open.svgz
new file mode 100644
index 0000000..6ef2526
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/folder_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/followmouse.svgz b/IconThemes/mono/scalable/actions/followmouse.svgz
new file mode 100644
index 0000000..9c06e1a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/followmouse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fonts.svgz b/IconThemes/mono/scalable/actions/fonts.svgz
new file mode 100644
index 0000000..76d4fcf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fonts.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fontsizedown.svgz b/IconThemes/mono/scalable/actions/fontsizedown.svgz
new file mode 100644
index 0000000..c3555c2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fontsizedown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fontsizeup.svgz b/IconThemes/mono/scalable/actions/fontsizeup.svgz
new file mode 100644
index 0000000..8b86232
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fontsizeup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/fork.svgz b/IconThemes/mono/scalable/actions/fork.svgz
new file mode 100644
index 0000000..76a3e15
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/fork.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/form.svgz b/IconThemes/mono/scalable/actions/form.svgz
new file mode 100644
index 0000000..1a033bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/form.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/form_edit.svgz b/IconThemes/mono/scalable/actions/form_edit.svgz
new file mode 100644
index 0000000..fdc7eba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/form_edit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/form_newobj.svgz b/IconThemes/mono/scalable/actions/form_newobj.svgz
new file mode 100644
index 0000000..36702e5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/form_newobj.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/format_decreaseindent.svgz b/IconThemes/mono/scalable/actions/format_decreaseindent.svgz
new file mode 100644
index 0000000..f500af0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/format_decreaseindent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/format_increaseindent.svgz b/IconThemes/mono/scalable/actions/format_increaseindent.svgz
new file mode 100644
index 0000000..0926937
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/format_increaseindent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/forms.svgz b/IconThemes/mono/scalable/actions/forms.svgz
new file mode 100644
index 0000000..ab150c9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/forms.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/forward.svgz b/IconThemes/mono/scalable/actions/forward.svgz
new file mode 100644
index 0000000..d9cbf71
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/forward.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frac.svgz b/IconThemes/mono/scalable/actions/frac.svgz
new file mode 100644
index 0000000..59647e5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frac.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame.svgz b/IconThemes/mono/scalable/actions/frame.svgz
new file mode 100644
index 0000000..1d53a38
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame_chart.svgz b/IconThemes/mono/scalable/actions/frame_chart.svgz
new file mode 100644
index 0000000..20d4379
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame_chart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame_edit.svgz b/IconThemes/mono/scalable/actions/frame_edit.svgz
new file mode 100644
index 0000000..1882598
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame_edit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame_field.svgz b/IconThemes/mono/scalable/actions/frame_field.svgz
new file mode 100644
index 0000000..b333160
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame_field.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame_formula.svgz b/IconThemes/mono/scalable/actions/frame_formula.svgz
new file mode 100644
index 0000000..3976659
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame_formula.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame_image.svgz b/IconThemes/mono/scalable/actions/frame_image.svgz
new file mode 100644
index 0000000..84a0901
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame_image.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame_query.svgz b/IconThemes/mono/scalable/actions/frame_query.svgz
new file mode 100644
index 0000000..139c2cd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame_query.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame_spreadsheet.svgz b/IconThemes/mono/scalable/actions/frame_spreadsheet.svgz
new file mode 100644
index 0000000..ac8565f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame_spreadsheet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frame_text.svgz b/IconThemes/mono/scalable/actions/frame_text.svgz
new file mode 100644
index 0000000..ccb955e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frame_text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/frameprint.svgz b/IconThemes/mono/scalable/actions/frameprint.svgz
new file mode 100644
index 0000000..3b0abab
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/frameprint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/freehand.svgz b/IconThemes/mono/scalable/actions/freehand.svgz
new file mode 100644
index 0000000..9d1e1fa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/freehand.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ftin.svgz b/IconThemes/mono/scalable/actions/ftin.svgz
new file mode 100644
index 0000000..018cc75
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ftin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ftout.svgz b/IconThemes/mono/scalable/actions/ftout.svgz
new file mode 100644
index 0000000..0f49f7d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ftout.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/func.svgz b/IconThemes/mono/scalable/actions/func.svgz
new file mode 100644
index 0000000..5b97187
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/func.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/funct.svgz b/IconThemes/mono/scalable/actions/funct.svgz
new file mode 100644
index 0000000..263a5eb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/funct.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/functionhelp.svgz b/IconThemes/mono/scalable/actions/functionhelp.svgz
new file mode 100644
index 0000000..85ecb10
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/functionhelp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gadu_protocol.svgz b/IconThemes/mono/scalable/actions/gadu_protocol.svgz
new file mode 100644
index 0000000..3a8626c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gadu_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gear.svgz b/IconThemes/mono/scalable/actions/gear.svgz
new file mode 100644
index 0000000..7395afa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gear.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/genericaffinity.svgz b/IconThemes/mono/scalable/actions/genericaffinity.svgz
new file mode 100644
index 0000000..131a979
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/genericaffinity.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/genericprojectivity.svgz b/IconThemes/mono/scalable/actions/genericprojectivity.svgz
new file mode 100644
index 0000000..a66397d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/genericprojectivity.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gg_away.svgz b/IconThemes/mono/scalable/actions/gg_away.svgz
new file mode 100644
index 0000000..d67e3cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gg_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gg_ignore.svgz b/IconThemes/mono/scalable/actions/gg_ignore.svgz
new file mode 100644
index 0000000..a553911
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gg_ignore.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gg_invi.svgz b/IconThemes/mono/scalable/actions/gg_invi.svgz
new file mode 100644
index 0000000..7d91cc2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gg_invi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gg_offline.svgz b/IconThemes/mono/scalable/actions/gg_offline.svgz
new file mode 100644
index 0000000..9c6ecf8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gg_offline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gg_online.svgz b/IconThemes/mono/scalable/actions/gg_online.svgz
new file mode 100644
index 0000000..254660c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gg_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/glossary.svgz b/IconThemes/mono/scalable/actions/glossary.svgz
new file mode 100644
index 0000000..aa399ae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/glossary.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gnutelladown.svgz b/IconThemes/mono/scalable/actions/gnutelladown.svgz
new file mode 100644
index 0000000..d320dea
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gnutelladown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gnutellaup.svgz b/IconThemes/mono/scalable/actions/gnutellaup.svgz
new file mode 100644
index 0000000..c41446a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gnutellaup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gohome.svgz b/IconThemes/mono/scalable/actions/gohome.svgz
new file mode 100644
index 0000000..22a4e3b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gohome.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/goto.svgz b/IconThemes/mono/scalable/actions/goto.svgz
new file mode 100644
index 0000000..6436f45
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/goto.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/grayscale.svgz b/IconThemes/mono/scalable/actions/grayscale.svgz
new file mode 100644
index 0000000..890f4f7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/grayscale.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/green_ball.svgz b/IconThemes/mono/scalable/actions/green_ball.svgz
new file mode 100644
index 0000000..403f6a2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/green_ball.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/grid.svgz b/IconThemes/mono/scalable/actions/grid.svgz
new file mode 100644
index 0000000..f101da6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/grid.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/group.svgz b/IconThemes/mono/scalable/actions/group.svgz
new file mode 100644
index 0000000..d7c8984
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/group.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/group_stencils.svgz b/IconThemes/mono/scalable/actions/group_stencils.svgz
new file mode 100644
index 0000000..3c22939
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/group_stencils.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/groupbox.svgz b/IconThemes/mono/scalable/actions/groupbox.svgz
new file mode 100644
index 0000000..47d537e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/groupbox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/groupevent.svgz b/IconThemes/mono/scalable/actions/groupevent.svgz
new file mode 100644
index 0000000..7c37e9b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/groupevent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/groupwise_online.svgz b/IconThemes/mono/scalable/actions/groupwise_online.svgz
new file mode 100644
index 0000000..227f2d4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/groupwise_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gsub.svgz b/IconThemes/mono/scalable/actions/gsub.svgz
new file mode 100644
index 0000000..4cf2e0d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gsub.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/gsup.svgz b/IconThemes/mono/scalable/actions/gsup.svgz
new file mode 100644
index 0000000..04d62b3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/gsup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/guides_horizontal.svgz b/IconThemes/mono/scalable/actions/guides_horizontal.svgz
new file mode 100644
index 0000000..1747353
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/guides_horizontal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/guides_vertical.svgz b/IconThemes/mono/scalable/actions/guides_vertical.svgz
new file mode 100644
index 0000000..f9101f3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/guides_vertical.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/halfencrypted.svgz b/IconThemes/mono/scalable/actions/halfencrypted.svgz
new file mode 100644
index 0000000..bbc8216
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/halfencrypted.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/halflinebyvector.svgz b/IconThemes/mono/scalable/actions/halflinebyvector.svgz
new file mode 100644
index 0000000..efad397
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/halflinebyvector.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/harmonichomology.svgz b/IconThemes/mono/scalable/actions/harmonichomology.svgz
new file mode 100644
index 0000000..6562557
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/harmonichomology.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hdd.svgz b/IconThemes/mono/scalable/actions/hdd.svgz
new file mode 100644
index 0000000..650d4d0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hdd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/help.svgz b/IconThemes/mono/scalable/actions/help.svgz
new file mode 100644
index 0000000..a782345
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/help.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hexagonbcv.svgz b/IconThemes/mono/scalable/actions/hexagonbcv.svgz
new file mode 100644
index 0000000..10ec192
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hexagonbcv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hibernate.svgz b/IconThemes/mono/scalable/actions/hibernate.svgz
new file mode 100644
index 0000000..83f79bc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hibernate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hide_table_column.svgz b/IconThemes/mono/scalable/actions/hide_table_column.svgz
new file mode 100644
index 0000000..9fab919
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hide_table_column.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hide_table_row.svgz b/IconThemes/mono/scalable/actions/hide_table_row.svgz
new file mode 100644
index 0000000..81ec5b4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hide_table_row.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hidemouse.svgz b/IconThemes/mono/scalable/actions/hidemouse.svgz
new file mode 100644
index 0000000..ed2df77
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hidemouse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/highlighting.svgz b/IconThemes/mono/scalable/actions/highlighting.svgz
new file mode 100644
index 0000000..8b0a15e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/highlighting.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/highscore.svgz b/IconThemes/mono/scalable/actions/highscore.svgz
new file mode 100644
index 0000000..fafecd6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/highscore.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hint.svgz b/IconThemes/mono/scalable/actions/hint.svgz
new file mode 100644
index 0000000..1abeeec
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/history.svgz b/IconThemes/mono/scalable/actions/history.svgz
new file mode 100644
index 0000000..4fb431e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/history.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/history_clear.svgz b/IconThemes/mono/scalable/actions/history_clear.svgz
new file mode 100644
index 0000000..ed27c12
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/history_clear.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/homepage.svgz b/IconThemes/mono/scalable/actions/homepage.svgz
new file mode 100644
index 0000000..dfc4427
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/homepage.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hotmail.svgz b/IconThemes/mono/scalable/actions/hotmail.svgz
new file mode 100644
index 0000000..40e00f1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hotmail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/htmlvalidator.svgz b/IconThemes/mono/scalable/actions/htmlvalidator.svgz
new file mode 100644
index 0000000..2a9bb86
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/htmlvalidator.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hue.svgz b/IconThemes/mono/scalable/actions/hue.svgz
new file mode 100644
index 0000000..7677a92
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hue.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/hyperbolabffp.svgz b/IconThemes/mono/scalable/actions/hyperbolabffp.svgz
new file mode 100644
index 0000000..290c9cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/hyperbolabffp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/icq_away.svgz b/IconThemes/mono/scalable/actions/icq_away.svgz
new file mode 100644
index 0000000..d67e3cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/icq_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/icq_invisible.svgz b/IconThemes/mono/scalable/actions/icq_invisible.svgz
new file mode 100644
index 0000000..71e4c62
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/icq_invisible.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/icq_offline.svgz b/IconThemes/mono/scalable/actions/icq_offline.svgz
new file mode 100644
index 0000000..020a78d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/icq_offline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/icq_online.svgz b/IconThemes/mono/scalable/actions/icq_online.svgz
new file mode 100644
index 0000000..b5f1b92
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/icq_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/icq_protocol.svgz b/IconThemes/mono/scalable/actions/icq_protocol.svgz
new file mode 100644
index 0000000..1c9e046
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/icq_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/id.svgz b/IconThemes/mono/scalable/actions/id.svgz
new file mode 100644
index 0000000..fd1e9dc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/id.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/idea.svgz b/IconThemes/mono/scalable/actions/idea.svgz
new file mode 100644
index 0000000..425edc7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/idea.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/identity.svgz b/IconThemes/mono/scalable/actions/identity.svgz
new file mode 100644
index 0000000..d6aaf32
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/identity.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/idf.svgz b/IconThemes/mono/scalable/actions/idf.svgz
new file mode 100644
index 0000000..23e19d8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/idf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/idh.svgz b/IconThemes/mono/scalable/actions/idh.svgz
new file mode 100644
index 0000000..289c7fc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/idh.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/imagecomment.svgz b/IconThemes/mono/scalable/actions/imagecomment.svgz
new file mode 100644
index 0000000..6f0e344
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/imagecomment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/imagegallery.svgz b/IconThemes/mono/scalable/actions/imagegallery.svgz
new file mode 100644
index 0000000..4ac282f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/imagegallery.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/images_display.svgz b/IconThemes/mono/scalable/actions/images_display.svgz
new file mode 100644
index 0000000..4b7b2f6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/images_display.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/indent.svgz b/IconThemes/mono/scalable/actions/indent.svgz
new file mode 100644
index 0000000..2d4c9a7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/indent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/info.svgz b/IconThemes/mono/scalable/actions/info.svgz
new file mode 100644
index 0000000..f8ec7ba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/info.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/inline_image.svgz b/IconThemes/mono/scalable/actions/inline_image.svgz
new file mode 100644
index 0000000..d17c106
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/inline_image.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/inline_table.svgz b/IconThemes/mono/scalable/actions/inline_table.svgz
new file mode 100644
index 0000000..5583e7c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/inline_table.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/inscol.svgz b/IconThemes/mono/scalable/actions/inscol.svgz
new file mode 100644
index 0000000..0b480eb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/inscol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insert_arg.svgz b/IconThemes/mono/scalable/actions/insert_arg.svgz
new file mode 100644
index 0000000..364d4c5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insert_arg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insert_chart.svgz b/IconThemes/mono/scalable/actions/insert_chart.svgz
new file mode 100644
index 0000000..bc464ba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insert_chart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insert_link.svgz b/IconThemes/mono/scalable/actions/insert_link.svgz
new file mode 100644
index 0000000..c2ae85c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insert_link.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insert_table_col.svgz b/IconThemes/mono/scalable/actions/insert_table_col.svgz
new file mode 100644
index 0000000..0a73b12
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insert_table_col.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insert_table_row.svgz b/IconThemes/mono/scalable/actions/insert_table_row.svgz
new file mode 100644
index 0000000..f0f9340
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insert_table_row.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insert_tag.svgz b/IconThemes/mono/scalable/actions/insert_tag.svgz
new file mode 100644
index 0000000..eb601bb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insert_tag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insertcell.svgz b/IconThemes/mono/scalable/actions/insertcell.svgz
new file mode 100644
index 0000000..14fcf8a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insertcell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insertcellcopy.svgz b/IconThemes/mono/scalable/actions/insertcellcopy.svgz
new file mode 100644
index 0000000..19fb42f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insertcellcopy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/inserttable.svgz b/IconThemes/mono/scalable/actions/inserttable.svgz
new file mode 100644
index 0000000..83a39bb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/inserttable.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/insrow.svgz b/IconThemes/mono/scalable/actions/insrow.svgz
new file mode 100644
index 0000000..62d6b89
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/insrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/int.svgz b/IconThemes/mono/scalable/actions/int.svgz
new file mode 100644
index 0000000..5efe482
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/int.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/integral_func.svgz b/IconThemes/mono/scalable/actions/integral_func.svgz
new file mode 100644
index 0000000..8f65665
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/integral_func.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/intersection.svgz b/IconThemes/mono/scalable/actions/intersection.svgz
new file mode 100644
index 0000000..fd2d825
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/intersection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/inversion.svgz b/IconThemes/mono/scalable/actions/inversion.svgz
new file mode 100644
index 0000000..db12d57
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/inversion.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/invert.svgz b/IconThemes/mono/scalable/actions/invert.svgz
new file mode 100644
index 0000000..2145348
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/invert.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ipf.svgz b/IconThemes/mono/scalable/actions/ipf.svgz
new file mode 100644
index 0000000..b3c8ccd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ipf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/iph.svgz b/IconThemes/mono/scalable/actions/iph.svgz
new file mode 100644
index 0000000..daebe64
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/iph.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irc_away.svgz b/IconThemes/mono/scalable/actions/irc_away.svgz
new file mode 100644
index 0000000..49e3555
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irc_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irc_normal.svgz b/IconThemes/mono/scalable/actions/irc_normal.svgz
new file mode 100644
index 0000000..b1d97a9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irc_normal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irc_online.svgz b/IconThemes/mono/scalable/actions/irc_online.svgz
new file mode 100644
index 0000000..000483a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irc_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irc_server.svgz b/IconThemes/mono/scalable/actions/irc_server.svgz
new file mode 100644
index 0000000..c3d3448
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irc_server.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irc_voice.svgz b/IconThemes/mono/scalable/actions/irc_voice.svgz
new file mode 100644
index 0000000..70d9db4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irc_voice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irf.svgz b/IconThemes/mono/scalable/actions/irf.svgz
new file mode 100644
index 0000000..95ada21
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irh.svgz b/IconThemes/mono/scalable/actions/irh.svgz
new file mode 100644
index 0000000..afc6912
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irh.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irkick.svgz b/IconThemes/mono/scalable/actions/irkick.svgz
new file mode 100644
index 0000000..32bdf20
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irkick.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irkickflash.svgz b/IconThemes/mono/scalable/actions/irkickflash.svgz
new file mode 100644
index 0000000..1a14d83
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irkickflash.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/irkickoff.svgz b/IconThemes/mono/scalable/actions/irkickoff.svgz
new file mode 100644
index 0000000..1f5e6bb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/irkickoff.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/isotopemap.svgz b/IconThemes/mono/scalable/actions/isotopemap.svgz
new file mode 100644
index 0000000..12c1a4f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/isotopemap.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/italic.svgz b/IconThemes/mono/scalable/actions/italic.svgz
new file mode 100644
index 0000000..00c4025
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/italic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/item_add.svgz b/IconThemes/mono/scalable/actions/item_add.svgz
new file mode 100644
index 0000000..0636c43
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/item_add.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/item_remove.svgz b/IconThemes/mono/scalable/actions/item_remove.svgz
new file mode 100644
index 0000000..aba23e3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/item_remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/item_rename.svgz b/IconThemes/mono/scalable/actions/item_rename.svgz
new file mode 100644
index 0000000..4e1b3e7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/item_rename.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/jabber_offline.svgz b/IconThemes/mono/scalable/actions/jabber_offline.svgz
new file mode 100644
index 0000000..561e1af
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/jabber_offline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/jabber_online.svgz b/IconThemes/mono/scalable/actions/jabber_online.svgz
new file mode 100644
index 0000000..bb2ee48
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/jabber_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/jabber_protocol.svgz b/IconThemes/mono/scalable/actions/jabber_protocol.svgz
new file mode 100644
index 0000000..336e1bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/jabber_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/jail_pay.svgz b/IconThemes/mono/scalable/actions/jail_pay.svgz
new file mode 100644
index 0000000..e872289
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/jail_pay.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/join_bevel.svgz b/IconThemes/mono/scalable/actions/join_bevel.svgz
new file mode 100644
index 0000000..f53921e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/join_bevel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/join_miter.svgz b/IconThemes/mono/scalable/actions/join_miter.svgz
new file mode 100644
index 0000000..9100e71
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/join_miter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/join_round.svgz b/IconThemes/mono/scalable/actions/join_round.svgz
new file mode 100644
index 0000000..5c03c82
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/join_round.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/journal.svgz b/IconThemes/mono/scalable/actions/journal.svgz
new file mode 100644
index 0000000..788e2f5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/journal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/juk_dock.svgz b/IconThemes/mono/scalable/actions/juk_dock.svgz
new file mode 100644
index 0000000..5c8d764
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/juk_dock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/juk_time.svgz b/IconThemes/mono/scalable/actions/juk_time.svgz
new file mode 100644
index 0000000..86c27ce
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/juk_time.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kaboodleloop.svgz b/IconThemes/mono/scalable/actions/kaboodleloop.svgz
new file mode 100644
index 0000000..476ff0b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kaboodleloop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kalarm.svgz b/IconThemes/mono/scalable/actions/kalarm.svgz
new file mode 100644
index 0000000..597c5ae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kalarm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kalarm_disabled.svgz b/IconThemes/mono/scalable/actions/kalarm_disabled.svgz
new file mode 100644
index 0000000..2ed541b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kalarm_disabled.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kanjidic.svgz b/IconThemes/mono/scalable/actions/kanjidic.svgz
new file mode 100644
index 0000000..fa52ea7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kanjidic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kazaadown.svgz b/IconThemes/mono/scalable/actions/kazaadown.svgz
new file mode 100644
index 0000000..dc42263
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kazaadown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kazaaup.svgz b/IconThemes/mono/scalable/actions/kazaaup.svgz
new file mode 100644
index 0000000..e91e029
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kazaaup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kbear-firewall.svgz b/IconThemes/mono/scalable/actions/kbear-firewall.svgz
new file mode 100644
index 0000000..3f15965
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kbear-firewall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kbearsitemanager.svgz b/IconThemes/mono/scalable/actions/kbearsitemanager.svgz
new file mode 100644
index 0000000..8ec561d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kbearsitemanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kbearsitemanagerdb.svgz b/IconThemes/mono/scalable/actions/kbearsitemanagerdb.svgz
new file mode 100644
index 0000000..c71b3c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kbearsitemanagerdb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kbruch_exercise_common.svgz b/IconThemes/mono/scalable/actions/kbruch_exercise_common.svgz
new file mode 100644
index 0000000..0f7efa9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kbruch_exercise_common.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kbruch_exercise_compare.svgz b/IconThemes/mono/scalable/actions/kbruch_exercise_compare.svgz
new file mode 100644
index 0000000..ce76d3f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kbruch_exercise_compare.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kbruch_exercise_conversion.svgz b/IconThemes/mono/scalable/actions/kbruch_exercise_conversion.svgz
new file mode 100644
index 0000000..336daaf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kbruch_exercise_conversion.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kbruch_exercise_factorisation.svgz b/IconThemes/mono/scalable/actions/kbruch_exercise_factorisation.svgz
new file mode 100644
index 0000000..62fa688
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kbruch_exercise_factorisation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdat.svgz b/IconThemes/mono/scalable/actions/kdat.svgz
new file mode 100644
index 0000000..4ea07a4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdb_form.svgz b/IconThemes/mono/scalable/actions/kdb_form.svgz
new file mode 100644
index 0000000..a3f433f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdb_form.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdb_table.svgz b/IconThemes/mono/scalable/actions/kdb_table.svgz
new file mode 100644
index 0000000..e42fa4a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdb_table.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kde1.svgz b/IconThemes/mono/scalable/actions/kde1.svgz
new file mode 100644
index 0000000..41e9c54
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kde1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kde2.svgz b/IconThemes/mono/scalable/actions/kde2.svgz
new file mode 100644
index 0000000..467b0e5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kde2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kde3.svgz b/IconThemes/mono/scalable/actions/kde3.svgz
new file mode 100644
index 0000000..5724e83
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kde3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kde4.svgz b/IconThemes/mono/scalable/actions/kde4.svgz
new file mode 100644
index 0000000..0c4a6a2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kde4.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kde5.svgz b/IconThemes/mono/scalable/actions/kde5.svgz
new file mode 100644
index 0000000..4b02234
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kde5.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kde6.svgz b/IconThemes/mono/scalable/actions/kde6.svgz
new file mode 100644
index 0000000..4bc56f0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kde6.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_addprinter.svgz b/IconThemes/mono/scalable/actions/kdeprint_addprinter.svgz
new file mode 100644
index 0000000..46d11b1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_addprinter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_addpseudo.svgz b/IconThemes/mono/scalable/actions/kdeprint_addpseudo.svgz
new file mode 100644
index 0000000..7acb83d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_addpseudo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_configmgr.svgz b/IconThemes/mono/scalable/actions/kdeprint_configmgr.svgz
new file mode 100644
index 0000000..0847566
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_configmgr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_configsrv.svgz b/IconThemes/mono/scalable/actions/kdeprint_configsrv.svgz
new file mode 100644
index 0000000..d90908e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_configsrv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_defaulthard.svgz b/IconThemes/mono/scalable/actions/kdeprint_defaulthard.svgz
new file mode 100644
index 0000000..b2dfd52
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_defaulthard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_defaultsoft.svgz b/IconThemes/mono/scalable/actions/kdeprint_defaultsoft.svgz
new file mode 100644
index 0000000..a7fa912
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_defaultsoft.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_printer_infos.svgz b/IconThemes/mono/scalable/actions/kdeprint_printer_infos.svgz
new file mode 100644
index 0000000..1b40842
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_printer_infos.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_printstate.svgz b/IconThemes/mono/scalable/actions/kdeprint_printstate.svgz
new file mode 100644
index 0000000..51a1399
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_printstate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_queuestate.svgz b/IconThemes/mono/scalable/actions/kdeprint_queuestate.svgz
new file mode 100644
index 0000000..525cdd2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_queuestate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_report.svgz b/IconThemes/mono/scalable/actions/kdeprint_report.svgz
new file mode 100644
index 0000000..197bf04
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_report.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_restartsrv.svgz b/IconThemes/mono/scalable/actions/kdeprint_restartsrv.svgz
new file mode 100644
index 0000000..c815c8b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_restartsrv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_stopprinter.svgz b/IconThemes/mono/scalable/actions/kdeprint_stopprinter.svgz
new file mode 100644
index 0000000..8871c61
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_stopprinter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_testprinter.svgz b/IconThemes/mono/scalable/actions/kdeprint_testprinter.svgz
new file mode 100644
index 0000000..4f5c031
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_testprinter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdeprint_uploadsmb.svgz b/IconThemes/mono/scalable/actions/kdeprint_uploadsmb.svgz
new file mode 100644
index 0000000..62f83f3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdeprint_uploadsmb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdevelop_down.svgz b/IconThemes/mono/scalable/actions/kdevelop_down.svgz
new file mode 100644
index 0000000..1b47226
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdevelop_down.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdissert_link.svgz b/IconThemes/mono/scalable/actions/kdissert_link.svgz
new file mode 100644
index 0000000..cb11241
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdissert_link.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdissert_point.svgz b/IconThemes/mono/scalable/actions/kdissert_point.svgz
new file mode 100644
index 0000000..8507c6f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdissert_point.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kdissert_sort.svgz b/IconThemes/mono/scalable/actions/kdissert_sort.svgz
new file mode 100644
index 0000000..84a4ef6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kdissert_sort.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/key.svgz b/IconThemes/mono/scalable/actions/key.svgz
new file mode 100644
index 0000000..ccf753a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/key.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/key_enter.svgz b/IconThemes/mono/scalable/actions/key_enter.svgz
new file mode 100644
index 0000000..5f22b0a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/key_enter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kget_dock.svgz b/IconThemes/mono/scalable/actions/kget_dock.svgz
new file mode 100644
index 0000000..6eef86a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kget_dock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kget_dock_download.svgz b/IconThemes/mono/scalable/actions/kget_dock_download.svgz
new file mode 100644
index 0000000..44185dc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kget_dock_download.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_edit.svgz b/IconThemes/mono/scalable/actions/kgpg_edit.svgz
new file mode 100644
index 0000000..58093cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_edit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_export.svgz b/IconThemes/mono/scalable/actions/kgpg_export.svgz
new file mode 100644
index 0000000..8cdd768
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_export.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_gen.svgz b/IconThemes/mono/scalable/actions/kgpg_gen.svgz
new file mode 100644
index 0000000..a609d9a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_gen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_identity.svgz b/IconThemes/mono/scalable/actions/kgpg_identity.svgz
new file mode 100644
index 0000000..d6aaf32
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_identity.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_import.svgz b/IconThemes/mono/scalable/actions/kgpg_import.svgz
new file mode 100644
index 0000000..6314779
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_import.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_info.svgz b/IconThemes/mono/scalable/actions/kgpg_info.svgz
new file mode 100644
index 0000000..5b700c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_info.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_photo.svgz b/IconThemes/mono/scalable/actions/kgpg_photo.svgz
new file mode 100644
index 0000000..d64dc95
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_photo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_show.svgz b/IconThemes/mono/scalable/actions/kgpg_show.svgz
new file mode 100644
index 0000000..913f532
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_show.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_sign.svgz b/IconThemes/mono/scalable/actions/kgpg_sign.svgz
new file mode 100644
index 0000000..e736eca
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_sign.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kgpg_term.svgz b/IconThemes/mono/scalable/actions/kgpg_term.svgz
new file mode 100644
index 0000000..47fa264
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kgpg_term.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/khotkeys.svgz b/IconThemes/mono/scalable/actions/khotkeys.svgz
new file mode 100644
index 0000000..48986e1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/khotkeys.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/khtml_kget.svgz b/IconThemes/mono/scalable/actions/khtml_kget.svgz
new file mode 100644
index 0000000..6ee7e47
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/khtml_kget.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kig_numbers.svgz b/IconThemes/mono/scalable/actions/kig_numbers.svgz
new file mode 100644
index 0000000..352c341
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kig_numbers.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kig_polygon.svgz b/IconThemes/mono/scalable/actions/kig_polygon.svgz
new file mode 100644
index 0000000..7f8b95b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kig_polygon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kig_text.svgz b/IconThemes/mono/scalable/actions/kig_text.svgz
new file mode 100644
index 0000000..7934c73
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kig_text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kiten.svgz b/IconThemes/mono/scalable/actions/kiten.svgz
new file mode 100644
index 0000000..59bf279
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kiten.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_arrow.svgz b/IconThemes/mono/scalable/actions/kivio_arrow.svgz
new file mode 100644
index 0000000..73530e4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_arrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_connector.svgz b/IconThemes/mono/scalable/actions/kivio_connector.svgz
new file mode 100644
index 0000000..984c679
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_connector.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_text.svgz b/IconThemes/mono/scalable/actions/kivio_text.svgz
new file mode 100644
index 0000000..df1379d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_zoom.svgz b/IconThemes/mono/scalable/actions/kivio_zoom.svgz
new file mode 100644
index 0000000..e94aca6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_zoom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_zoom_hand.svgz b/IconThemes/mono/scalable/actions/kivio_zoom_hand.svgz
new file mode 100644
index 0000000..148eed0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_zoom_hand.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_zoom_height.svgz b/IconThemes/mono/scalable/actions/kivio_zoom_height.svgz
new file mode 100644
index 0000000..1a54b2c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_zoom_height.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_zoom_minus.svgz b/IconThemes/mono/scalable/actions/kivio_zoom_minus.svgz
new file mode 100644
index 0000000..40a42ba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_zoom_minus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_zoom_page.svgz b/IconThemes/mono/scalable/actions/kivio_zoom_page.svgz
new file mode 100644
index 0000000..d348923
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_zoom_page.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_zoom_plus.svgz b/IconThemes/mono/scalable/actions/kivio_zoom_plus.svgz
new file mode 100644
index 0000000..f7b6481
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_zoom_plus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kivio_zoom_width.svgz b/IconThemes/mono/scalable/actions/kivio_zoom_width.svgz
new file mode 100644
index 0000000..9ff8740
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kivio_zoom_width.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/klettres_desert.svgz b/IconThemes/mono/scalable/actions/klettres_desert.svgz
new file mode 100644
index 0000000..4506729
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/klettres_desert.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/klettres_grownup.svgz b/IconThemes/mono/scalable/actions/klettres_grownup.svgz
new file mode 100644
index 0000000..e909e66
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/klettres_grownup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/klettres_kids.svgz b/IconThemes/mono/scalable/actions/klettres_kids.svgz
new file mode 100644
index 0000000..c9d7f61
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/klettres_kids.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/klipper_doc.svgz b/IconThemes/mono/scalable/actions/klipper_doc.svgz
new file mode 100644
index 0000000..d4951ac
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/klipper_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/klipper_dock.svgz b/IconThemes/mono/scalable/actions/klipper_dock.svgz
new file mode 100644
index 0000000..b513f37
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/klipper_dock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/klipper_dock2.svgz b/IconThemes/mono/scalable/actions/klipper_dock2.svgz
new file mode 100644
index 0000000..fba2bbe
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/klipper_dock2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmaway.svgz b/IconThemes/mono/scalable/actions/kmaway.svgz
new file mode 100644
index 0000000..d67e3cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmaway.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmback.svgz b/IconThemes/mono/scalable/actions/kmback.svgz
new file mode 100644
index 0000000..8c719d7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmback.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmbsy.svgz b/IconThemes/mono/scalable/actions/kmbsy.svgz
new file mode 100644
index 0000000..c29f307
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmbsy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmlunch.svgz b/IconThemes/mono/scalable/actions/kmlunch.svgz
new file mode 100644
index 0000000..1340dd9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmlunch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgattachment.svgz b/IconThemes/mono/scalable/actions/kmmsgattachment.svgz
new file mode 100644
index 0000000..9f16b56
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgattachment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgflag.svgz b/IconThemes/mono/scalable/actions/kmmsgflag.svgz
new file mode 100644
index 0000000..f6961b8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgflag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgforwarded.svgz b/IconThemes/mono/scalable/actions/kmmsgforwarded.svgz
new file mode 100644
index 0000000..b350662
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgforwarded.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgignored.svgz b/IconThemes/mono/scalable/actions/kmmsgignored.svgz
new file mode 100644
index 0000000..f49999e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgignored.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgnew.svgz b/IconThemes/mono/scalable/actions/kmmsgnew.svgz
new file mode 100644
index 0000000..718487c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgnew.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgread.svgz b/IconThemes/mono/scalable/actions/kmmsgread.svgz
new file mode 100644
index 0000000..3f46b42
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgread.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgreplied.svgz b/IconThemes/mono/scalable/actions/kmmsgreplied.svgz
new file mode 100644
index 0000000..6314779
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgreplied.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgtodo.svgz b/IconThemes/mono/scalable/actions/kmmsgtodo.svgz
new file mode 100644
index 0000000..41f01c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgtodo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgunseen.svgz b/IconThemes/mono/scalable/actions/kmmsgunseen.svgz
new file mode 100644
index 0000000..07ae726
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgunseen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmmsgwatched.svgz b/IconThemes/mono/scalable/actions/kmmsgwatched.svgz
new file mode 100644
index 0000000..f548527
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmmsgwatched.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmoffline.svgz b/IconThemes/mono/scalable/actions/kmoffline.svgz
new file mode 100644
index 0000000..2a9378a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmoffline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmonline.svgz b/IconThemes/mono/scalable/actions/kmonline.svgz
new file mode 100644
index 0000000..fafb642
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmonline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmousetool_off.svgz b/IconThemes/mono/scalable/actions/kmousetool_off.svgz
new file mode 100644
index 0000000..98dbe18
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmousetool_off.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmousetool_on.svgz b/IconThemes/mono/scalable/actions/kmousetool_on.svgz
new file mode 100644
index 0000000..e0f38fe
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmousetool_on.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kmphone.svgz b/IconThemes/mono/scalable/actions/kmphone.svgz
new file mode 100644
index 0000000..f668d92
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kmphone.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/knewstuff.svgz b/IconThemes/mono/scalable/actions/knewstuff.svgz
new file mode 100644
index 0000000..e8defba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/knewstuff.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/knotes_close.svgz b/IconThemes/mono/scalable/actions/knotes_close.svgz
new file mode 100644
index 0000000..a60d13f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/knotes_close.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/knotes_date.svgz b/IconThemes/mono/scalable/actions/knotes_date.svgz
new file mode 100644
index 0000000..2e4b1b0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/knotes_date.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/knotes_delete.svgz b/IconThemes/mono/scalable/actions/knotes_delete.svgz
new file mode 100644
index 0000000..11db68a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/knotes_delete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/know.svgz b/IconThemes/mono/scalable/actions/know.svgz
new file mode 100644
index 0000000..f6619fe
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/know.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_contacts.svgz b/IconThemes/mono/scalable/actions/kontact_contacts.svgz
new file mode 100644
index 0000000..69e3bc9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_contacts.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_date.svgz b/IconThemes/mono/scalable/actions/kontact_date.svgz
new file mode 100644
index 0000000..797948d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_date.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_journal.svgz b/IconThemes/mono/scalable/actions/kontact_journal.svgz
new file mode 100644
index 0000000..ddfc041
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_journal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_mail.svgz b/IconThemes/mono/scalable/actions/kontact_mail.svgz
new file mode 100644
index 0000000..5d1a113
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_mail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_news.svgz b/IconThemes/mono/scalable/actions/kontact_news.svgz
new file mode 100644
index 0000000..ca86250
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_news.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_notes.svgz b/IconThemes/mono/scalable/actions/kontact_notes.svgz
new file mode 100644
index 0000000..e5af495
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_notes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_summary.svgz b/IconThemes/mono/scalable/actions/kontact_summary.svgz
new file mode 100644
index 0000000..6f6883e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_summary.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_summary_green.svgz b/IconThemes/mono/scalable/actions/kontact_summary_green.svgz
new file mode 100644
index 0000000..491fd73
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_summary_green.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kontact_todo.svgz b/IconThemes/mono/scalable/actions/kontact_todo.svgz
new file mode 100644
index 0000000..a852461
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kontact_todo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/konv_message.svgz b/IconThemes/mono/scalable/actions/konv_message.svgz
new file mode 100644
index 0000000..09f5470
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/konv_message.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kopeteavailable.svgz b/IconThemes/mono/scalable/actions/kopeteavailable.svgz
new file mode 100644
index 0000000..a9828f5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kopeteavailable.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kopeteaway.svgz b/IconThemes/mono/scalable/actions/kopeteaway.svgz
new file mode 100644
index 0000000..fd8edf3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kopeteaway.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kopeteeditstatusmessage.svgz b/IconThemes/mono/scalable/actions/kopeteeditstatusmessage.svgz
new file mode 100644
index 0000000..b2db4bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kopeteeditstatusmessage.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/korgac.svgz b/IconThemes/mono/scalable/actions/korgac.svgz
new file mode 100644
index 0000000..5d4ba9e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/korgac.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/korgac_disabled.svgz b/IconThemes/mono/scalable/actions/korgac_disabled.svgz
new file mode 100644
index 0000000..1f8c587
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/korgac_disabled.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kpilotaddress.svgz b/IconThemes/mono/scalable/actions/kpilotaddress.svgz
new file mode 100644
index 0000000..3f7f2e1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kpilotaddress.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kpilotbhotsync.svgz b/IconThemes/mono/scalable/actions/kpilotbhotsync.svgz
new file mode 100644
index 0000000..3603eae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kpilotbhotsync.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kpilotcalendar.svgz b/IconThemes/mono/scalable/actions/kpilotcalendar.svgz
new file mode 100644
index 0000000..ac7b84a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kpilotcalendar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kpilotdb.svgz b/IconThemes/mono/scalable/actions/kpilotdb.svgz
new file mode 100644
index 0000000..5a2dbad
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kpilotdb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kpilotfileinstaller.svgz b/IconThemes/mono/scalable/actions/kpilotfileinstaller.svgz
new file mode 100644
index 0000000..77e7f75
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kpilotfileinstaller.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kpilotknotes.svgz b/IconThemes/mono/scalable/actions/kpilotknotes.svgz
new file mode 100644
index 0000000..e2c3c07
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kpilotknotes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kpilottodo.svgz b/IconThemes/mono/scalable/actions/kpilottodo.svgz
new file mode 100644
index 0000000..41f01c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kpilottodo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/krec_record.svgz b/IconThemes/mono/scalable/actions/krec_record.svgz
new file mode 100644
index 0000000..412be57
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/krec_record.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kroete.svgz b/IconThemes/mono/scalable/actions/kroete.svgz
new file mode 100644
index 0000000..cadff3c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kroete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ksirc_dock.svgz b/IconThemes/mono/scalable/actions/ksirc_dock.svgz
new file mode 100644
index 0000000..2763bf7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ksirc_dock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_advanced.svgz b/IconThemes/mono/scalable/actions/kstars_advanced.svgz
new file mode 100644
index 0000000..7bbf1b7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_advanced.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_catalog.svgz b/IconThemes/mono/scalable/actions/kstars_catalog.svgz
new file mode 100644
index 0000000..064c0fd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_catalog.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_cbound.svgz b/IconThemes/mono/scalable/actions/kstars_cbound.svgz
new file mode 100644
index 0000000..ce4b5d8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_cbound.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_clines.svgz b/IconThemes/mono/scalable/actions/kstars_clines.svgz
new file mode 100644
index 0000000..6f5c95b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_clines.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_cnames.svgz b/IconThemes/mono/scalable/actions/kstars_cnames.svgz
new file mode 100644
index 0000000..365e533
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_cnames.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_colors.svgz b/IconThemes/mono/scalable/actions/kstars_colors.svgz
new file mode 100644
index 0000000..91337c0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_colors.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_deepsky.svgz b/IconThemes/mono/scalable/actions/kstars_deepsky.svgz
new file mode 100644
index 0000000..7f4399c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_deepsky.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_geo.svgz b/IconThemes/mono/scalable/actions/kstars_geo.svgz
new file mode 100644
index 0000000..98ca279
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_geo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_grid.svgz b/IconThemes/mono/scalable/actions/kstars_grid.svgz
new file mode 100644
index 0000000..5bd75d2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_grid.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_guides.svgz b/IconThemes/mono/scalable/actions/kstars_guides.svgz
new file mode 100644
index 0000000..f7d2a29
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_guides.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_horizon.svgz b/IconThemes/mono/scalable/actions/kstars_horizon.svgz
new file mode 100644
index 0000000..713bfdd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_horizon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_mw.svgz b/IconThemes/mono/scalable/actions/kstars_mw.svgz
new file mode 100644
index 0000000..c64037b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_mw.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_planets.svgz b/IconThemes/mono/scalable/actions/kstars_planets.svgz
new file mode 100644
index 0000000..b4da37c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_planets.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_solarsystem.svgz b/IconThemes/mono/scalable/actions/kstars_solarsystem.svgz
new file mode 100644
index 0000000..f7937e6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_solarsystem.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kstars_stars.svgz b/IconThemes/mono/scalable/actions/kstars_stars.svgz
new file mode 100644
index 0000000..e72ff69
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kstars_stars.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ksys1.svgz b/IconThemes/mono/scalable/actions/ksys1.svgz
new file mode 100644
index 0000000..cea267f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ksys1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ksys2.svgz b/IconThemes/mono/scalable/actions/ksys2.svgz
new file mode 100644
index 0000000..fefb435
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ksys2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ksys3.svgz b/IconThemes/mono/scalable/actions/ksys3.svgz
new file mode 100644
index 0000000..8d74817
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ksys3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktinfowidget.svgz b/IconThemes/mono/scalable/actions/ktinfowidget.svgz
new file mode 100644
index 0000000..6784c7a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktinfowidget.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktip.svgz b/IconThemes/mono/scalable/actions/ktip.svgz
new file mode 100644
index 0000000..7112a67
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktip.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktnef_extract_all_to.svgz b/IconThemes/mono/scalable/actions/ktnef_extract_all_to.svgz
new file mode 100644
index 0000000..e82e95c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktnef_extract_all_to.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktnef_extract_to.svgz b/IconThemes/mono/scalable/actions/ktnef_extract_to.svgz
new file mode 100644
index 0000000..0ad3196
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktnef_extract_to.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktplugins.svgz b/IconThemes/mono/scalable/actions/ktplugins.svgz
new file mode 100644
index 0000000..8628363
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktplugins.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktqueuemanager.svgz b/IconThemes/mono/scalable/actions/ktqueuemanager.svgz
new file mode 100644
index 0000000..41038cc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktqueuemanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktremove.svgz b/IconThemes/mono/scalable/actions/ktremove.svgz
new file mode 100644
index 0000000..08fc1ca
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktremove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktstart.svgz b/IconThemes/mono/scalable/actions/ktstart.svgz
new file mode 100644
index 0000000..f91caa5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktstart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktstart_all.svgz b/IconThemes/mono/scalable/actions/ktstart_all.svgz
new file mode 100644
index 0000000..42768d7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktstart_all.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktstop.svgz b/IconThemes/mono/scalable/actions/ktstop.svgz
new file mode 100644
index 0000000..19e37b0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktstop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ktstop_all.svgz b/IconThemes/mono/scalable/actions/ktstop_all.svgz
new file mode 100644
index 0000000..6becca9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ktstop_all.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/kverbosuser.svgz b/IconThemes/mono/scalable/actions/kverbosuser.svgz
new file mode 100644
index 0000000..3f46b42
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/kverbosuser.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/label.svgz b/IconThemes/mono/scalable/actions/label.svgz
new file mode 100644
index 0000000..2855173
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/label.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lan.svgz b/IconThemes/mono/scalable/actions/lan.svgz
new file mode 100644
index 0000000..32bdf20
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lan.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/languages.svgz b/IconThemes/mono/scalable/actions/languages.svgz
new file mode 100644
index 0000000..7934c73
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/languages.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/laptop_charge.svgz b/IconThemes/mono/scalable/actions/laptop_charge.svgz
new file mode 100644
index 0000000..b083871
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/laptop_charge.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/laptop_nobattery.svgz b/IconThemes/mono/scalable/actions/laptop_nobattery.svgz
new file mode 100644
index 0000000..87a946d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/laptop_nobattery.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/laptop_nocharge.svgz b/IconThemes/mono/scalable/actions/laptop_nocharge.svgz
new file mode 100644
index 0000000..4cabbfa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/laptop_nocharge.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/laptop_power.svgz b/IconThemes/mono/scalable/actions/laptop_power.svgz
new file mode 100644
index 0000000..43e83f3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/laptop_power.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/laptoppower.svgz b/IconThemes/mono/scalable/actions/laptoppower.svgz
new file mode 100644
index 0000000..b45697d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/laptoppower.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/largethumbnails.svgz b/IconThemes/mono/scalable/actions/largethumbnails.svgz
new file mode 100644
index 0000000..8864e8b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/largethumbnails.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lastmoves.svgz b/IconThemes/mono/scalable/actions/lastmoves.svgz
new file mode 100644
index 0000000..d4eb7f1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lastmoves.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/launch.svgz b/IconThemes/mono/scalable/actions/launch.svgz
new file mode 100644
index 0000000..c7d5fdf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/launch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/layer_editable.svgz b/IconThemes/mono/scalable/actions/layer_editable.svgz
new file mode 100644
index 0000000..d7f1077
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/layer_editable.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/layer_noeditable.svgz b/IconThemes/mono/scalable/actions/layer_noeditable.svgz
new file mode 100644
index 0000000..9c21c79
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/layer_noeditable.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/layer_noprint.svgz b/IconThemes/mono/scalable/actions/layer_noprint.svgz
new file mode 100644
index 0000000..1c03ad0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/layer_noprint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/layer_print.svgz b/IconThemes/mono/scalable/actions/layer_print.svgz
new file mode 100644
index 0000000..a22de4e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/layer_print.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/layer_visible.svgz b/IconThemes/mono/scalable/actions/layer_visible.svgz
new file mode 100644
index 0000000..25fc9c0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/layer_visible.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ldap_lookup.svgz b/IconThemes/mono/scalable/actions/ldap_lookup.svgz
new file mode 100644
index 0000000..88a8019
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ldap_lookup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/leftjust.svgz b/IconThemes/mono/scalable/actions/leftjust.svgz
new file mode 100644
index 0000000..8a753ac
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/leftjust.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/legalmoves.svgz b/IconThemes/mono/scalable/actions/legalmoves.svgz
new file mode 100644
index 0000000..78cc431
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/legalmoves.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/legend.svgz b/IconThemes/mono/scalable/actions/legend.svgz
new file mode 100644
index 0000000..c63f8b2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/legend.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lessen.svgz b/IconThemes/mono/scalable/actions/lessen.svgz
new file mode 100644
index 0000000..eb4db19
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lessen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line.svgz b/IconThemes/mono/scalable/actions/line.svgz
new file mode 100644
index 0000000..b680ee0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_arrow_begin.svgz b/IconThemes/mono/scalable/actions/line_arrow_begin.svgz
new file mode 100644
index 0000000..d677e76
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_arrow_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_arrow_end.svgz b/IconThemes/mono/scalable/actions/line_arrow_end.svgz
new file mode 100644
index 0000000..fc7e5bf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_arrow_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_begin.svgz b/IconThemes/mono/scalable/actions/line_begin.svgz
new file mode 100644
index 0000000..eb29089
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_circle_begin.svgz b/IconThemes/mono/scalable/actions/line_circle_begin.svgz
new file mode 100644
index 0000000..ba2e354
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_circle_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_circle_end.svgz b/IconThemes/mono/scalable/actions/line_circle_end.svgz
new file mode 100644
index 0000000..63f87fc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_circle_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_dimension_line_begin.svgz b/IconThemes/mono/scalable/actions/line_dimension_line_begin.svgz
new file mode 100644
index 0000000..7376c4d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_dimension_line_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_dimension_line_end.svgz b/IconThemes/mono/scalable/actions/line_dimension_line_end.svgz
new file mode 100644
index 0000000..408593e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_dimension_line_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_double_arrow_begin.svgz b/IconThemes/mono/scalable/actions/line_double_arrow_begin.svgz
new file mode 100644
index 0000000..c5900b5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_double_arrow_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_double_arrow_end.svgz b/IconThemes/mono/scalable/actions/line_double_arrow_end.svgz
new file mode 100644
index 0000000..50c0268
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_double_arrow_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_double_line_arrow_begin.svgz b/IconThemes/mono/scalable/actions/line_double_line_arrow_begin.svgz
new file mode 100644
index 0000000..2e8322d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_double_line_arrow_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_double_line_arrow_end.svgz b/IconThemes/mono/scalable/actions/line_double_line_arrow_end.svgz
new file mode 100644
index 0000000..9ebe613
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_double_line_arrow_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_end.svgz b/IconThemes/mono/scalable/actions/line_end.svgz
new file mode 100644
index 0000000..4f60c88
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_line_arrow_begin.svgz b/IconThemes/mono/scalable/actions/line_line_arrow_begin.svgz
new file mode 100644
index 0000000..ac76c66
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_line_arrow_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_line_arrow_end.svgz b/IconThemes/mono/scalable/actions/line_line_arrow_end.svgz
new file mode 100644
index 0000000..685df29
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_line_arrow_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_normal_begin.svgz b/IconThemes/mono/scalable/actions/line_normal_begin.svgz
new file mode 100644
index 0000000..8fb0aae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_normal_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_normal_end.svgz b/IconThemes/mono/scalable/actions/line_normal_end.svgz
new file mode 100644
index 0000000..df7a6d0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_normal_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_rect_begin.svgz b/IconThemes/mono/scalable/actions/line_rect_begin.svgz
new file mode 100644
index 0000000..239744a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_rect_begin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_rect_end.svgz b/IconThemes/mono/scalable/actions/line_rect_end.svgz
new file mode 100644
index 0000000..7253dbe
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_rect_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/line_width.svgz b/IconThemes/mono/scalable/actions/line_width.svgz
new file mode 100644
index 0000000..9157486
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/line_width.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/linebyvector.svgz b/IconThemes/mono/scalable/actions/linebyvector.svgz
new file mode 100644
index 0000000..da28b36
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/linebyvector.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lineedit.svgz b/IconThemes/mono/scalable/actions/lineedit.svgz
new file mode 100644
index 0000000..0a3ec09
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lineedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/linewidth.svgz b/IconThemes/mono/scalable/actions/linewidth.svgz
new file mode 100644
index 0000000..f3764e7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/linewidth.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/linked.svgz b/IconThemes/mono/scalable/actions/linked.svgz
new file mode 100644
index 0000000..82fab41
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/linked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/list.svgz b/IconThemes/mono/scalable/actions/list.svgz
new file mode 100644
index 0000000..3ca70be
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/list.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/listbox.svgz b/IconThemes/mono/scalable/actions/listbox.svgz
new file mode 100644
index 0000000..ebb4c70
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/listbox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/listview.svgz b/IconThemes/mono/scalable/actions/listview.svgz
new file mode 100644
index 0000000..226b783
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/listview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/locationbar_erase.svgz b/IconThemes/mono/scalable/actions/locationbar_erase.svgz
new file mode 100644
index 0000000..c276d54
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/locationbar_erase.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lock.svgz b/IconThemes/mono/scalable/actions/lock.svgz
new file mode 100644
index 0000000..be31a0b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/locked.svgz b/IconThemes/mono/scalable/actions/locked.svgz
new file mode 100644
index 0000000..b526dda
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/locked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lockzoom.svgz b/IconThemes/mono/scalable/actions/lockzoom.svgz
new file mode 100644
index 0000000..1f561a5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lockzoom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/locus.svgz b/IconThemes/mono/scalable/actions/locus.svgz
new file mode 100644
index 0000000..e80a562
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/locus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/loop.svgz b/IconThemes/mono/scalable/actions/loop.svgz
new file mode 100644
index 0000000..61ade67
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/loop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lower.svgz b/IconThemes/mono/scalable/actions/lower.svgz
new file mode 100644
index 0000000..837efb7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lower.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lowerlayer.svgz b/IconThemes/mono/scalable/actions/lowerlayer.svgz
new file mode 100644
index 0000000..4e7e9ed
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lowerlayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lsub.svgz b/IconThemes/mono/scalable/actions/lsub.svgz
new file mode 100644
index 0000000..320be14
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lsub.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/lsup.svgz b/IconThemes/mono/scalable/actions/lsup.svgz
new file mode 100644
index 0000000..fe078bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/lsup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/magnify.svgz b/IconThemes/mono/scalable/actions/magnify.svgz
new file mode 100644
index 0000000..2a85c3d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/magnify.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_delete.svgz b/IconThemes/mono/scalable/actions/mail_delete.svgz
new file mode 100644
index 0000000..f608d6d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_delete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_find.svgz b/IconThemes/mono/scalable/actions/mail_find.svgz
new file mode 100644
index 0000000..fecbf5a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_find.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_flag.svgz b/IconThemes/mono/scalable/actions/mail_flag.svgz
new file mode 100644
index 0000000..f6961b8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_flag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_forward.svgz b/IconThemes/mono/scalable/actions/mail_forward.svgz
new file mode 100644
index 0000000..0f6f6c2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_forward.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_generic.svgz b/IconThemes/mono/scalable/actions/mail_generic.svgz
new file mode 100644
index 0000000..b44e9d6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_generic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_get.svgz b/IconThemes/mono/scalable/actions/mail_get.svgz
new file mode 100644
index 0000000..1b8afe0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_get.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_ham.svgz b/IconThemes/mono/scalable/actions/mail_ham.svgz
new file mode 100644
index 0000000..d11b074
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_ham.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_ignore.svgz b/IconThemes/mono/scalable/actions/mail_ignore.svgz
new file mode 100644
index 0000000..f49999e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_ignore.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_new.svgz b/IconThemes/mono/scalable/actions/mail_new.svgz
new file mode 100644
index 0000000..74fdf7e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_new3.svgz b/IconThemes/mono/scalable/actions/mail_new3.svgz
new file mode 100644
index 0000000..6ded278
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_new3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_post_to.svgz b/IconThemes/mono/scalable/actions/mail_post_to.svgz
new file mode 100644
index 0000000..3d2bcd0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_post_to.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_post_to3.svgz b/IconThemes/mono/scalable/actions/mail_post_to3.svgz
new file mode 100644
index 0000000..1abc16d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_post_to3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_reply.svgz b/IconThemes/mono/scalable/actions/mail_reply.svgz
new file mode 100644
index 0000000..6b9f6d6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_reply.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_replyall.svgz b/IconThemes/mono/scalable/actions/mail_replyall.svgz
new file mode 100644
index 0000000..3ff8a8d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_replyall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_replylist.svgz b/IconThemes/mono/scalable/actions/mail_replylist.svgz
new file mode 100644
index 0000000..07f81f7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_replylist.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_send.svgz b/IconThemes/mono/scalable/actions/mail_send.svgz
new file mode 100644
index 0000000..1ac2921
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_send.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_send_via.svgz b/IconThemes/mono/scalable/actions/mail_send_via.svgz
new file mode 100644
index 0000000..1ac2921
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_send_via.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_spam.svgz b/IconThemes/mono/scalable/actions/mail_spam.svgz
new file mode 100644
index 0000000..3666140
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_spam.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mail_todo.svgz b/IconThemes/mono/scalable/actions/mail_todo.svgz
new file mode 100644
index 0000000..41f01c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mail_todo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mailappt.svgz b/IconThemes/mono/scalable/actions/mailappt.svgz
new file mode 100644
index 0000000..07ae726
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mailappt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/make.svgz b/IconThemes/mono/scalable/actions/make.svgz
new file mode 100644
index 0000000..5a40cd4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/make.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/make_kdevelop.svgz b/IconThemes/mono/scalable/actions/make_kdevelop.svgz
new file mode 100644
index 0000000..149a585
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/make_kdevelop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/markasblank.svgz b/IconThemes/mono/scalable/actions/markasblank.svgz
new file mode 100644
index 0000000..173ee43
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/markasblank.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_abs.svgz b/IconThemes/mono/scalable/actions/math_abs.svgz
new file mode 100644
index 0000000..3d97d6b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_abs.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_brace.svgz b/IconThemes/mono/scalable/actions/math_brace.svgz
new file mode 100644
index 0000000..f5999c0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_brace.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_brackets.svgz b/IconThemes/mono/scalable/actions/math_brackets.svgz
new file mode 100644
index 0000000..93ebcdb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_brackets.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_frac.svgz b/IconThemes/mono/scalable/actions/math_frac.svgz
new file mode 100644
index 0000000..15603db
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_frac.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_int.svgz b/IconThemes/mono/scalable/actions/math_int.svgz
new file mode 100644
index 0000000..c609da6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_int.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_lsub.svgz b/IconThemes/mono/scalable/actions/math_lsub.svgz
new file mode 100644
index 0000000..2731ba6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_lsub.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_lsup.svgz b/IconThemes/mono/scalable/actions/math_lsup.svgz
new file mode 100644
index 0000000..fa1cf84
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_lsup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_matrix.svgz b/IconThemes/mono/scalable/actions/math_matrix.svgz
new file mode 100644
index 0000000..d9dbf77
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_matrix.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_onetwomatrix.svgz b/IconThemes/mono/scalable/actions/math_onetwomatrix.svgz
new file mode 100644
index 0000000..63b5203
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_onetwomatrix.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_paren.svgz b/IconThemes/mono/scalable/actions/math_paren.svgz
new file mode 100644
index 0000000..6d44f6c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_paren.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_prod.svgz b/IconThemes/mono/scalable/actions/math_prod.svgz
new file mode 100644
index 0000000..2b06b2b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_prod.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_rsub.svgz b/IconThemes/mono/scalable/actions/math_rsub.svgz
new file mode 100644
index 0000000..dafa9eb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_rsub.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_rsup.svgz b/IconThemes/mono/scalable/actions/math_rsup.svgz
new file mode 100644
index 0000000..2e63988
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_rsup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_sqrt.svgz b/IconThemes/mono/scalable/actions/math_sqrt.svgz
new file mode 100644
index 0000000..96dff01
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_sqrt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/math_sum.svgz b/IconThemes/mono/scalable/actions/math_sum.svgz
new file mode 100644
index 0000000..91843fd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/math_sum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/matrix.svgz b/IconThemes/mono/scalable/actions/matrix.svgz
new file mode 100644
index 0000000..42ab62a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/matrix.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/maximum.svgz b/IconThemes/mono/scalable/actions/maximum.svgz
new file mode 100644
index 0000000..844a17a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/maximum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/medthumbnails.svgz b/IconThemes/mono/scalable/actions/medthumbnails.svgz
new file mode 100644
index 0000000..cccb386
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/medthumbnails.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/menu_new.svgz b/IconThemes/mono/scalable/actions/menu_new.svgz
new file mode 100644
index 0000000..5db1b63
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/menu_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/menu_new_sep.svgz b/IconThemes/mono/scalable/actions/menu_new_sep.svgz
new file mode 100644
index 0000000..a51a8ef
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/menu_new_sep.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mergecell.svgz b/IconThemes/mono/scalable/actions/mergecell.svgz
new file mode 100644
index 0000000..f6f5a9b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mergecell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/message.svgz b/IconThemes/mono/scalable/actions/message.svgz
new file mode 100644
index 0000000..150b7f8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/message.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/message_reply.svgz b/IconThemes/mono/scalable/actions/message_reply.svgz
new file mode 100644
index 0000000..63d8cb7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/message_reply.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/messagebox_critical.svgz b/IconThemes/mono/scalable/actions/messagebox_critical.svgz
new file mode 100644
index 0000000..c173c73
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/messagebox_critical.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/messagebox_info.svgz b/IconThemes/mono/scalable/actions/messagebox_info.svgz
new file mode 100644
index 0000000..038ff16
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/messagebox_info.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/messagebox_warning.svgz b/IconThemes/mono/scalable/actions/messagebox_warning.svgz
new file mode 100644
index 0000000..d2a596f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/messagebox_warning.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/metacontact_away.svgz b/IconThemes/mono/scalable/actions/metacontact_away.svgz
new file mode 100644
index 0000000..a7bacf8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/metacontact_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/metacontact_offline.svgz b/IconThemes/mono/scalable/actions/metacontact_offline.svgz
new file mode 100644
index 0000000..e1fae91
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/metacontact_offline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/metacontact_online.svgz b/IconThemes/mono/scalable/actions/metacontact_online.svgz
new file mode 100644
index 0000000..724045e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/metacontact_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/metacontact_unknown.svgz b/IconThemes/mono/scalable/actions/metacontact_unknown.svgz
new file mode 100644
index 0000000..1423c30
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/metacontact_unknown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/middle.svgz b/IconThemes/mono/scalable/actions/middle.svgz
new file mode 100644
index 0000000..393c42c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/middle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mini_autoform.svgz b/IconThemes/mono/scalable/actions/mini_autoform.svgz
new file mode 100644
index 0000000..75fce9c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mini_autoform.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mini_circle.svgz b/IconThemes/mono/scalable/actions/mini_circle.svgz
new file mode 100644
index 0000000..5267132
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mini_circle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mini_clipart.svgz b/IconThemes/mono/scalable/actions/mini_clipart.svgz
new file mode 100644
index 0000000..25bbeeb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mini_clipart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mini_dock.svgz b/IconThemes/mono/scalable/actions/mini_dock.svgz
new file mode 100644
index 0000000..fd6fe5c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mini_dock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mini_line.svgz b/IconThemes/mono/scalable/actions/mini_line.svgz
new file mode 100644
index 0000000..1c977a4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mini_line.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mini_pie.svgz b/IconThemes/mono/scalable/actions/mini_pie.svgz
new file mode 100644
index 0000000..b0beb6f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mini_pie.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mini_polygon.svgz b/IconThemes/mono/scalable/actions/mini_polygon.svgz
new file mode 100644
index 0000000..7c90fc4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mini_polygon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mini_rect.svgz b/IconThemes/mono/scalable/actions/mini_rect.svgz
new file mode 100644
index 0000000..9d176b5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mini_rect.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/minimum.svgz b/IconThemes/mono/scalable/actions/minimum.svgz
new file mode 100644
index 0000000..7981d11
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/minimum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/minitools.svgz b/IconThemes/mono/scalable/actions/minitools.svgz
new file mode 100644
index 0000000..22c44cc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/minitools.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/miror.svgz b/IconThemes/mono/scalable/actions/miror.svgz
new file mode 100644
index 0000000..f0be962
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/miror.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mirror-both.svgz b/IconThemes/mono/scalable/actions/mirror-both.svgz
new file mode 100644
index 0000000..f258d48
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mirror-both.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mirror-horiz.svgz b/IconThemes/mono/scalable/actions/mirror-horiz.svgz
new file mode 100644
index 0000000..2d9b03e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mirror-horiz.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mirror-vert.svgz b/IconThemes/mono/scalable/actions/mirror-vert.svgz
new file mode 100644
index 0000000..e54553c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mirror-vert.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mirror.svgz b/IconThemes/mono/scalable/actions/mirror.svgz
new file mode 100644
index 0000000..5593605
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mirror.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mirrorpoint.svgz b/IconThemes/mono/scalable/actions/mirrorpoint.svgz
new file mode 100644
index 0000000..d9de92c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mirrorpoint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/misc.svgz b/IconThemes/mono/scalable/actions/misc.svgz
new file mode 100644
index 0000000..9a81f28
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/misc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mode1.svgz b/IconThemes/mono/scalable/actions/mode1.svgz
new file mode 100644
index 0000000..5d3b5eb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mode1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mode2.svgz b/IconThemes/mono/scalable/actions/mode2.svgz
new file mode 100644
index 0000000..4bcddec
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mode2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mode3.svgz b/IconThemes/mono/scalable/actions/mode3.svgz
new file mode 100644
index 0000000..63a64e1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mode3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mode4.svgz b/IconThemes/mono/scalable/actions/mode4.svgz
new file mode 100644
index 0000000..5c1ce9c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mode4.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mode5.svgz b/IconThemes/mono/scalable/actions/mode5.svgz
new file mode 100644
index 0000000..7f47e9f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mode5.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/modified.svgz b/IconThemes/mono/scalable/actions/modified.svgz
new file mode 100644
index 0000000..718487c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/modified.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/money.svgz b/IconThemes/mono/scalable/actions/money.svgz
new file mode 100644
index 0000000..63f6680
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/money.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/monop_board.svgz b/IconThemes/mono/scalable/actions/monop_board.svgz
new file mode 100644
index 0000000..41eb533
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/monop_board.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/month.svgz b/IconThemes/mono/scalable/actions/month.svgz
new file mode 100644
index 0000000..7b713df
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/month.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mouse.svgz b/IconThemes/mono/scalable/actions/mouse.svgz
new file mode 100644
index 0000000..eaea1e4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mouse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mouse_pointer.svgz b/IconThemes/mono/scalable/actions/mouse_pointer.svgz
new file mode 100644
index 0000000..8507c6f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mouse_pointer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/move.svgz b/IconThemes/mono/scalable/actions/move.svgz
new file mode 100644
index 0000000..3c9779d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/move.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/msgid2msgstr.svgz b/IconThemes/mono/scalable/actions/msgid2msgstr.svgz
new file mode 100644
index 0000000..1e40af0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/msgid2msgstr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/msn_away.svgz b/IconThemes/mono/scalable/actions/msn_away.svgz
new file mode 100644
index 0000000..d67e3cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/msn_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/msn_blocked.svgz b/IconThemes/mono/scalable/actions/msn_blocked.svgz
new file mode 100644
index 0000000..27b7ed7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/msn_blocked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/msn_invisible.svgz b/IconThemes/mono/scalable/actions/msn_invisible.svgz
new file mode 100644
index 0000000..07536ba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/msn_invisible.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/msn_offline.svgz b/IconThemes/mono/scalable/actions/msn_offline.svgz
new file mode 100644
index 0000000..bfa0225
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/msn_offline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/msn_online.svgz b/IconThemes/mono/scalable/actions/msn_online.svgz
new file mode 100644
index 0000000..f6f8052
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/msn_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/msn_phone.svgz b/IconThemes/mono/scalable/actions/msn_phone.svgz
new file mode 100644
index 0000000..cdf50b5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/msn_phone.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/msn_protocol.svgz b/IconThemes/mono/scalable/actions/msn_protocol.svgz
new file mode 100644
index 0000000..566119e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/msn_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mug.svgz b/IconThemes/mono/scalable/actions/mug.svgz
new file mode 100644
index 0000000..2fdada1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mug.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/multiline.svgz b/IconThemes/mono/scalable/actions/multiline.svgz
new file mode 100644
index 0000000..c2ef266
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/multiline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/multiple.svgz b/IconThemes/mono/scalable/actions/multiple.svgz
new file mode 100644
index 0000000..e72d5ca
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/multiple.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/multirow.svgz b/IconThemes/mono/scalable/actions/multirow.svgz
new file mode 100644
index 0000000..af5d857
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/multirow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_32ndnote.svgz b/IconThemes/mono/scalable/actions/music_32ndnote.svgz
new file mode 100644
index 0000000..eb134c5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_32ndnote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_cleficon.svgz b/IconThemes/mono/scalable/actions/music_cleficon.svgz
new file mode 100644
index 0000000..0488917
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_cleficon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_cross.svgz b/IconThemes/mono/scalable/actions/music_cross.svgz
new file mode 100644
index 0000000..6529fc4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_cross.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_dottednote.svgz b/IconThemes/mono/scalable/actions/music_dottednote.svgz
new file mode 100644
index 0000000..b4c6096
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_dottednote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_eightnote.svgz b/IconThemes/mono/scalable/actions/music_eightnote.svgz
new file mode 100644
index 0000000..c0cf9dc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_eightnote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_fermatenote.svgz b/IconThemes/mono/scalable/actions/music_fermatenote.svgz
new file mode 100644
index 0000000..121e171
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_fermatenote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_flat.svgz b/IconThemes/mono/scalable/actions/music_flat.svgz
new file mode 100644
index 0000000..bc3ee43
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_flat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_fullnote.svgz b/IconThemes/mono/scalable/actions/music_fullnote.svgz
new file mode 100644
index 0000000..ef7baf8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_fullnote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_halfnote.svgz b/IconThemes/mono/scalable/actions/music_halfnote.svgz
new file mode 100644
index 0000000..cba5b17
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_halfnote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_natur.svgz b/IconThemes/mono/scalable/actions/music_natur.svgz
new file mode 100644
index 0000000..13a0280
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_natur.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_quarternote.svgz b/IconThemes/mono/scalable/actions/music_quarternote.svgz
new file mode 100644
index 0000000..e6e9d62
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_quarternote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/music_sixteenthnote.svgz b/IconThemes/mono/scalable/actions/music_sixteenthnote.svgz
new file mode 100644
index 0000000..9ebfe05
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/music_sixteenthnote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/mute.svgz b/IconThemes/mono/scalable/actions/mute.svgz
new file mode 100644
index 0000000..fb16add
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/mute.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/napsterdown.svgz b/IconThemes/mono/scalable/actions/napsterdown.svgz
new file mode 100644
index 0000000..c57fcdc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/napsterdown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/napsterup.svgz b/IconThemes/mono/scalable/actions/napsterup.svgz
new file mode 100644
index 0000000..89c7949
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/napsterup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/navigator_first.svgz b/IconThemes/mono/scalable/actions/navigator_first.svgz
new file mode 100644
index 0000000..4e2d738
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/navigator_first.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/navigator_last.svgz b/IconThemes/mono/scalable/actions/navigator_last.svgz
new file mode 100644
index 0000000..fdd7c1d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/navigator_last.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/navigator_new.svgz b/IconThemes/mono/scalable/actions/navigator_new.svgz
new file mode 100644
index 0000000..14257a8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/navigator_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/navigator_next.svgz b/IconThemes/mono/scalable/actions/navigator_next.svgz
new file mode 100644
index 0000000..e9750a0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/navigator_next.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/navigator_prev.svgz b/IconThemes/mono/scalable/actions/navigator_prev.svgz
new file mode 100644
index 0000000..54fadf2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/navigator_prev.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/neonpen.svgz b/IconThemes/mono/scalable/actions/neonpen.svgz
new file mode 100644
index 0000000..76cfc17
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/neonpen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/netactivity_full.svgz b/IconThemes/mono/scalable/actions/netactivity_full.svgz
new file mode 100644
index 0000000..54fd0d0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/netactivity_full.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/netactivity_none.svgz b/IconThemes/mono/scalable/actions/netactivity_none.svgz
new file mode 100644
index 0000000..25820d5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/netactivity_none.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/netactivity_off.svgz b/IconThemes/mono/scalable/actions/netactivity_off.svgz
new file mode 100644
index 0000000..0866b3a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/netactivity_off.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/netactivity_rx.svgz b/IconThemes/mono/scalable/actions/netactivity_rx.svgz
new file mode 100644
index 0000000..fc0a4dd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/netactivity_rx.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/netactivity_tx.svgz b/IconThemes/mono/scalable/actions/netactivity_tx.svgz
new file mode 100644
index 0000000..566fe5b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/netactivity_tx.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/network.svgz b/IconThemes/mono/scalable/actions/network.svgz
new file mode 100644
index 0000000..e5e2ba4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/network.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/network_connected.svgz b/IconThemes/mono/scalable/actions/network_connected.svgz
new file mode 100644
index 0000000..88de27c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/network_connected.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/network_disconnected.svgz b/IconThemes/mono/scalable/actions/network_disconnected.svgz
new file mode 100644
index 0000000..c3bffb2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/network_disconnected.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/network_incoming.svgz b/IconThemes/mono/scalable/actions/network_incoming.svgz
new file mode 100644
index 0000000..a6d54be
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/network_incoming.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/network_outgoing.svgz b/IconThemes/mono/scalable/actions/network_outgoing.svgz
new file mode 100644
index 0000000..dc87597
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/network_outgoing.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/network_traffic.svgz b/IconThemes/mono/scalable/actions/network_traffic.svgz
new file mode 100644
index 0000000..fa8c9a5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/network_traffic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newfont.svgz b/IconThemes/mono/scalable/actions/newfont.svgz
new file mode 100644
index 0000000..79f53d1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newfont.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newfunction.svgz b/IconThemes/mono/scalable/actions/newfunction.svgz
new file mode 100644
index 0000000..54ac2cc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newfunction.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newlayer.svgz b/IconThemes/mono/scalable/actions/newlayer.svgz
new file mode 100644
index 0000000..d8f51f3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newlayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newmsg.svgz b/IconThemes/mono/scalable/actions/newmsg.svgz
new file mode 100644
index 0000000..eb8cccb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newmsg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newnum.svgz b/IconThemes/mono/scalable/actions/newnum.svgz
new file mode 100644
index 0000000..59cb4a6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newnum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newparametric.svgz b/IconThemes/mono/scalable/actions/newparametric.svgz
new file mode 100644
index 0000000..d869d32
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newparametric.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newpolar.svgz b/IconThemes/mono/scalable/actions/newpolar.svgz
new file mode 100644
index 0000000..70d4606
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newpolar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newrecurevent.svgz b/IconThemes/mono/scalable/actions/newrecurevent.svgz
new file mode 100644
index 0000000..9ae776d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newrecurevent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/news_subscribe.svgz b/IconThemes/mono/scalable/actions/news_subscribe.svgz
new file mode 100644
index 0000000..bf66c7e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/news_subscribe.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/news_unsubscribe.svgz b/IconThemes/mono/scalable/actions/news_unsubscribe.svgz
new file mode 100644
index 0000000..3ae1162
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/news_unsubscribe.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newslide.svgz b/IconThemes/mono/scalable/actions/newslide.svgz
new file mode 100644
index 0000000..73d55aa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newslide.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/newtodo.svgz b/IconThemes/mono/scalable/actions/newtodo.svgz
new file mode 100644
index 0000000..c291697
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/newtodo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/next.svgz b/IconThemes/mono/scalable/actions/next.svgz
new file mode 100644
index 0000000..3eabe00
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/next.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nexterror.svgz b/IconThemes/mono/scalable/actions/nexterror.svgz
new file mode 100644
index 0000000..80ca334
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nexterror.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nextfuzzy.svgz b/IconThemes/mono/scalable/actions/nextfuzzy.svgz
new file mode 100644
index 0000000..4e80c5d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nextfuzzy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nextfuzzyuntrans.svgz b/IconThemes/mono/scalable/actions/nextfuzzyuntrans.svgz
new file mode 100644
index 0000000..ab2aa65
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nextfuzzyuntrans.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nextmarked.svgz b/IconThemes/mono/scalable/actions/nextmarked.svgz
new file mode 100644
index 0000000..93369ae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nextmarked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nextpo.svgz b/IconThemes/mono/scalable/actions/nextpo.svgz
new file mode 100644
index 0000000..f152b87
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nextpo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nexttemplate.svgz b/IconThemes/mono/scalable/actions/nexttemplate.svgz
new file mode 100644
index 0000000..ab4709e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nexttemplate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nextuntranslated.svgz b/IconThemes/mono/scalable/actions/nextuntranslated.svgz
new file mode 100644
index 0000000..73678cf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nextuntranslated.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nm_device_wired.svgz b/IconThemes/mono/scalable/actions/nm_device_wired.svgz
new file mode 100644
index 0000000..d280c9a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nm_device_wired.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nm_no_connection.svgz b/IconThemes/mono/scalable/actions/nm_no_connection.svgz
new file mode 100644
index 0000000..78bd76d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nm_no_connection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/no.svgz b/IconThemes/mono/scalable/actions/no.svgz
new file mode 100644
index 0000000..b9ff770
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/no.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunback.svgz b/IconThemes/mono/scalable/actions/noatunback.svgz
new file mode 100644
index 0000000..1e4e734
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunback.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunfback.svgz b/IconThemes/mono/scalable/actions/noatunfback.svgz
new file mode 100644
index 0000000..56fcc23
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunfback.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunfforward.svgz b/IconThemes/mono/scalable/actions/noatunfforward.svgz
new file mode 100644
index 0000000..79e0fc6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunfforward.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunforward.svgz b/IconThemes/mono/scalable/actions/noatunforward.svgz
new file mode 100644
index 0000000..01f102d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunforward.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunloopnone.svgz b/IconThemes/mono/scalable/actions/noatunloopnone.svgz
new file mode 100644
index 0000000..b5338d1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunloopnone.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunloopplaylist.svgz b/IconThemes/mono/scalable/actions/noatunloopplaylist.svgz
new file mode 100644
index 0000000..e12e415
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunloopplaylist.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunlooprandom.svgz b/IconThemes/mono/scalable/actions/noatunlooprandom.svgz
new file mode 100644
index 0000000..1c3c0d9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunlooprandom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunloopsong.svgz b/IconThemes/mono/scalable/actions/noatunloopsong.svgz
new file mode 100644
index 0000000..b91c9a1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunloopsong.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunpause.svgz b/IconThemes/mono/scalable/actions/noatunpause.svgz
new file mode 100644
index 0000000..6a74a40
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunpause.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunplay.svgz b/IconThemes/mono/scalable/actions/noatunplay.svgz
new file mode 100644
index 0000000..bf16625
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunplay.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunplaylist.svgz b/IconThemes/mono/scalable/actions/noatunplaylist.svgz
new file mode 100644
index 0000000..fd470c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunplaylist.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/noatunstop.svgz b/IconThemes/mono/scalable/actions/noatunstop.svgz
new file mode 100644
index 0000000..eec2f63
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/noatunstop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/nomailappt.svgz b/IconThemes/mono/scalable/actions/nomailappt.svgz
new file mode 100644
index 0000000..1c3ca4a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/nomailappt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/novisible.svgz b/IconThemes/mono/scalable/actions/novisible.svgz
new file mode 100644
index 0000000..f7731f7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/novisible.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ocr-select.svgz b/IconThemes/mono/scalable/actions/ocr-select.svgz
new file mode 100644
index 0000000..726cb7c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ocr-select.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ocr.svgz b/IconThemes/mono/scalable/actions/ocr.svgz
new file mode 100644
index 0000000..2ace90f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ocr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ocrImage.svgz b/IconThemes/mono/scalable/actions/ocrImage.svgz
new file mode 100644
index 0000000..171bfac
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ocrImage.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/oilpaint.svgz b/IconThemes/mono/scalable/actions/oilpaint.svgz
new file mode 100644
index 0000000..5a4555e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/oilpaint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ok.svgz b/IconThemes/mono/scalable/actions/ok.svgz
new file mode 100644
index 0000000..631d115
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ok.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/onetwomatrix.svgz b/IconThemes/mono/scalable/actions/onetwomatrix.svgz
new file mode 100644
index 0000000..2b5c2d7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/onetwomatrix.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/online_status.svgz b/IconThemes/mono/scalable/actions/online_status.svgz
new file mode 100644
index 0000000..e5e2ba4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/online_status.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/open_stencilset.svgz b/IconThemes/mono/scalable/actions/open_stencilset.svgz
new file mode 100644
index 0000000..289718d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/open_stencilset.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/openftdown.svgz b/IconThemes/mono/scalable/actions/openftdown.svgz
new file mode 100644
index 0000000..5402994
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/openftdown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/openftup.svgz b/IconThemes/mono/scalable/actions/openftup.svgz
new file mode 100644
index 0000000..5721f03
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/openftup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/openterm.svgz b/IconThemes/mono/scalable/actions/openterm.svgz
new file mode 100644
index 0000000..62c6cff
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/openterm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/opentermblue.svgz b/IconThemes/mono/scalable/actions/opentermblue.svgz
new file mode 100644
index 0000000..87deaa4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/opentermblue.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/opentermred.svgz b/IconThemes/mono/scalable/actions/opentermred.svgz
new file mode 100644
index 0000000..1655281
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/opentermred.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/options.svgz b/IconThemes/mono/scalable/actions/options.svgz
new file mode 100644
index 0000000..c8da202
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/options.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/optvar.svgz b/IconThemes/mono/scalable/actions/optvar.svgz
new file mode 100644
index 0000000..4e6156a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/optvar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/optwildcards.svgz b/IconThemes/mono/scalable/actions/optwildcards.svgz
new file mode 100644
index 0000000..e6c9b2b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/optwildcards.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/orbits.svgz b/IconThemes/mono/scalable/actions/orbits.svgz
new file mode 100644
index 0000000..cd2964d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/orbits.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/organizer.svgz b/IconThemes/mono/scalable/actions/organizer.svgz
new file mode 100644
index 0000000..b770cd1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/organizer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/oscilloscope.svgz b/IconThemes/mono/scalable/actions/oscilloscope.svgz
new file mode 100644
index 0000000..89021d5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/oscilloscope.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/over.svgz b/IconThemes/mono/scalable/actions/over.svgz
new file mode 100644
index 0000000..9b12fe4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/over.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/overview.svgz b/IconThemes/mono/scalable/actions/overview.svgz
new file mode 100644
index 0000000..1f7d6cc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/overview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/page.svgz b/IconThemes/mono/scalable/actions/page.svgz
new file mode 100644
index 0000000..3eab312
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/page.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/paint.svgz b/IconThemes/mono/scalable/actions/paint.svgz
new file mode 100644
index 0000000..6efebd1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/paint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/paintbrush.svgz b/IconThemes/mono/scalable/actions/paintbrush.svgz
new file mode 100644
index 0000000..6efebd1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/paintbrush.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/palette_color.svgz b/IconThemes/mono/scalable/actions/palette_color.svgz
new file mode 100644
index 0000000..eb013cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/palette_color.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/palette_gray.svgz b/IconThemes/mono/scalable/actions/palette_gray.svgz
new file mode 100644
index 0000000..f6ba78d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/palette_gray.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/palette_halftone.svgz b/IconThemes/mono/scalable/actions/palette_halftone.svgz
new file mode 100644
index 0000000..572cf2b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/palette_halftone.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/palette_lineart.svgz b/IconThemes/mono/scalable/actions/palette_lineart.svgz
new file mode 100644
index 0000000..56260fc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/palette_lineart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/parabolabtp.svgz b/IconThemes/mono/scalable/actions/parabolabtp.svgz
new file mode 100644
index 0000000..bf19942
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/parabolabtp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/parallel.svgz b/IconThemes/mono/scalable/actions/parallel.svgz
new file mode 100644
index 0000000..efba4ea
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/parallel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/paren.svgz b/IconThemes/mono/scalable/actions/paren.svgz
new file mode 100644
index 0000000..9ea4b73
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/paren.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/party.svgz b/IconThemes/mono/scalable/actions/party.svgz
new file mode 100644
index 0000000..e7d9e99
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/party.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/paste.svgz b/IconThemes/mono/scalable/actions/paste.svgz
new file mode 100644
index 0000000..d4b1786
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/paste.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/paste_stencil.svgz b/IconThemes/mono/scalable/actions/paste_stencil.svgz
new file mode 100644
index 0000000..81a9ee6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/paste_stencil.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/patch.svgz b/IconThemes/mono/scalable/actions/patch.svgz
new file mode 100644
index 0000000..214075e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/patch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/path.svgz b/IconThemes/mono/scalable/actions/path.svgz
new file mode 100644
index 0000000..5e2d6ba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/path.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_style.svgz b/IconThemes/mono/scalable/actions/pen_style.svgz
new file mode 100644
index 0000000..1ac42b7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_style.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_style_dash.svgz b/IconThemes/mono/scalable/actions/pen_style_dash.svgz
new file mode 100644
index 0000000..2f9fcd3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_style_dash.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_style_dashdot.svgz b/IconThemes/mono/scalable/actions/pen_style_dashdot.svgz
new file mode 100644
index 0000000..db9ca68
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_style_dashdot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_style_dashdotdot.svgz b/IconThemes/mono/scalable/actions/pen_style_dashdotdot.svgz
new file mode 100644
index 0000000..865e1d1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_style_dashdotdot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_style_dot.svgz b/IconThemes/mono/scalable/actions/pen_style_dot.svgz
new file mode 100644
index 0000000..04f07f4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_style_dot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_style_nopen.svgz b/IconThemes/mono/scalable/actions/pen_style_nopen.svgz
new file mode 100644
index 0000000..df0c863
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_style_nopen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_style_solid.svgz b/IconThemes/mono/scalable/actions/pen_style_solid.svgz
new file mode 100644
index 0000000..41735a6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_style_solid.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width.svgz b/IconThemes/mono/scalable/actions/pen_width.svgz
new file mode 100644
index 0000000..0d44e6f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width1.svgz b/IconThemes/mono/scalable/actions/pen_width1.svgz
new file mode 100644
index 0000000..98ca099
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width10.svgz b/IconThemes/mono/scalable/actions/pen_width10.svgz
new file mode 100644
index 0000000..04b14bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width10.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width2.svgz b/IconThemes/mono/scalable/actions/pen_width2.svgz
new file mode 100644
index 0000000..c4efece
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width3.svgz b/IconThemes/mono/scalable/actions/pen_width3.svgz
new file mode 100644
index 0000000..2fbe764
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width4.svgz b/IconThemes/mono/scalable/actions/pen_width4.svgz
new file mode 100644
index 0000000..82b525e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width4.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width5.svgz b/IconThemes/mono/scalable/actions/pen_width5.svgz
new file mode 100644
index 0000000..a11fcac
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width5.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width6.svgz b/IconThemes/mono/scalable/actions/pen_width6.svgz
new file mode 100644
index 0000000..decf814
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width6.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width7.svgz b/IconThemes/mono/scalable/actions/pen_width7.svgz
new file mode 100644
index 0000000..f1da0d1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width7.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width8.svgz b/IconThemes/mono/scalable/actions/pen_width8.svgz
new file mode 100644
index 0000000..b6feffb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width8.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pen_width9.svgz b/IconThemes/mono/scalable/actions/pen_width9.svgz
new file mode 100644
index 0000000..d79d276
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pen_width9.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/penbrush.svgz b/IconThemes/mono/scalable/actions/penbrush.svgz
new file mode 100644
index 0000000..aa8561d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/penbrush.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pencil.svgz b/IconThemes/mono/scalable/actions/pencil.svgz
new file mode 100644
index 0000000..8328db2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pencil.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/percent.svgz b/IconThemes/mono/scalable/actions/percent.svgz
new file mode 100644
index 0000000..3c3457d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/percent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/perpendicular.svgz b/IconThemes/mono/scalable/actions/perpendicular.svgz
new file mode 100644
index 0000000..87bbc6b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/perpendicular.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pgnum.svgz b/IconThemes/mono/scalable/actions/pgnum.svgz
new file mode 100644
index 0000000..5e07200
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pgnum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pgp-keys.svgz b/IconThemes/mono/scalable/actions/pgp-keys.svgz
new file mode 100644
index 0000000..a118367
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pgp-keys.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrase.svgz b/IconThemes/mono/scalable/actions/phrase.svgz
new file mode 100644
index 0000000..aab6895
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrase.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrase_new.svgz b/IconThemes/mono/scalable/actions/phrase_new.svgz
new file mode 100644
index 0000000..4d6b9e5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrase_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrase_open.svgz b/IconThemes/mono/scalable/actions/phrase_open.svgz
new file mode 100644
index 0000000..3ff3dc5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrase_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrase_save.svgz b/IconThemes/mono/scalable/actions/phrase_save.svgz
new file mode 100644
index 0000000..8fe1978
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrase_save.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrasebook.svgz b/IconThemes/mono/scalable/actions/phrasebook.svgz
new file mode 100644
index 0000000..19db2f8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrasebook.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrasebook_closed.svgz b/IconThemes/mono/scalable/actions/phrasebook_closed.svgz
new file mode 100644
index 0000000..ef881c5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrasebook_closed.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrasebook_new.svgz b/IconThemes/mono/scalable/actions/phrasebook_new.svgz
new file mode 100644
index 0000000..16b40e9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrasebook_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrasebook_open.svgz b/IconThemes/mono/scalable/actions/phrasebook_open.svgz
new file mode 100644
index 0000000..dded934
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrasebook_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrasebook_save.svgz b/IconThemes/mono/scalable/actions/phrasebook_save.svgz
new file mode 100644
index 0000000..fcea24a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrasebook_save.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrasehistory_open.svgz b/IconThemes/mono/scalable/actions/phrasehistory_open.svgz
new file mode 100644
index 0000000..9d76aaa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrasehistory_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrasehistory_print.svgz b/IconThemes/mono/scalable/actions/phrasehistory_print.svgz
new file mode 100644
index 0000000..39fd3b0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrasehistory_print.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/phrasehistory_save.svgz b/IconThemes/mono/scalable/actions/phrasehistory_save.svgz
new file mode 100644
index 0000000..8265b3b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/phrasehistory_save.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/piano.svgz b/IconThemes/mono/scalable/actions/piano.svgz
new file mode 100644
index 0000000..6af2fde
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/piano.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pixmaplabel.svgz b/IconThemes/mono/scalable/actions/pixmaplabel.svgz
new file mode 100644
index 0000000..3aed8f8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pixmaplabel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_eject.svgz b/IconThemes/mono/scalable/actions/player_eject.svgz
new file mode 100644
index 0000000..b1c0eae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_eject.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_end.svgz b/IconThemes/mono/scalable/actions/player_end.svgz
new file mode 100644
index 0000000..ce31161
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_end.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_fwd.svgz b/IconThemes/mono/scalable/actions/player_fwd.svgz
new file mode 100644
index 0000000..d3c2242
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_fwd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_mute.svgz b/IconThemes/mono/scalable/actions/player_mute.svgz
new file mode 100644
index 0000000..4d6802a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_mute.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_pause.svgz b/IconThemes/mono/scalable/actions/player_pause.svgz
new file mode 100644
index 0000000..933ec5d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_pause.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_play.svgz b/IconThemes/mono/scalable/actions/player_play.svgz
new file mode 100644
index 0000000..8465849
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_play.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_playlist.svgz b/IconThemes/mono/scalable/actions/player_playlist.svgz
new file mode 100644
index 0000000..f71b673
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_playlist.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_playlist_2.svgz b/IconThemes/mono/scalable/actions/player_playlist_2.svgz
new file mode 100644
index 0000000..e00507a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_playlist_2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_record.svgz b/IconThemes/mono/scalable/actions/player_record.svgz
new file mode 100644
index 0000000..203aacc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_record.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_rew.svgz b/IconThemes/mono/scalable/actions/player_rew.svgz
new file mode 100644
index 0000000..87baec7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_rew.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_start.svgz b/IconThemes/mono/scalable/actions/player_start.svgz
new file mode 100644
index 0000000..a8b900e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_start.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_stop.svgz b/IconThemes/mono/scalable/actions/player_stop.svgz
new file mode 100644
index 0000000..d8e2c4c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_stop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_time.svgz b/IconThemes/mono/scalable/actions/player_time.svgz
new file mode 100644
index 0000000..fc3dece
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_time.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_volume.svgz b/IconThemes/mono/scalable/actions/player_volume.svgz
new file mode 100644
index 0000000..e7158c2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_volume.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_volume_down.svgz b/IconThemes/mono/scalable/actions/player_volume_down.svgz
new file mode 100644
index 0000000..a12e314
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_volume_down.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/player_volume_up.svgz b/IconThemes/mono/scalable/actions/player_volume_up.svgz
new file mode 100644
index 0000000..8c7b818
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/player_volume_up.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/playlist.svgz b/IconThemes/mono/scalable/actions/playlist.svgz
new file mode 100644
index 0000000..db72bd5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/playlist.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/playsound.svgz b/IconThemes/mono/scalable/actions/playsound.svgz
new file mode 100644
index 0000000..bc1609e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/playsound.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/plot.svgz b/IconThemes/mono/scalable/actions/plot.svgz
new file mode 100644
index 0000000..67c1014
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/plot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/podcast.svgz b/IconThemes/mono/scalable/actions/podcast.svgz
new file mode 100644
index 0000000..18a5c38
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/podcast.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/podcast_new.svgz b/IconThemes/mono/scalable/actions/podcast_new.svgz
new file mode 100644
index 0000000..227d2b2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/podcast_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/point.svgz b/IconThemes/mono/scalable/actions/point.svgz
new file mode 100644
index 0000000..c56e769
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/point.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pointOnLine.svgz b/IconThemes/mono/scalable/actions/pointOnLine.svgz
new file mode 100644
index 0000000..a12fa7a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pointOnLine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/pointxy.svgz b/IconThemes/mono/scalable/actions/pointxy.svgz
new file mode 100644
index 0000000..0c8de54
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/pointxy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/polygon.svgz b/IconThemes/mono/scalable/actions/polygon.svgz
new file mode 100644
index 0000000..4bcfd91
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/polygon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/polygonsides.svgz b/IconThemes/mono/scalable/actions/polygonsides.svgz
new file mode 100644
index 0000000..f7ae36e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/polygonsides.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/polygonvertices.svgz b/IconThemes/mono/scalable/actions/polygonvertices.svgz
new file mode 100644
index 0000000..c23dcec
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/polygonvertices.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/polyline.svgz b/IconThemes/mono/scalable/actions/polyline.svgz
new file mode 100644
index 0000000..9e0dfba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/polyline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/power.svgz b/IconThemes/mono/scalable/actions/power.svgz
new file mode 100644
index 0000000..b843478
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/power.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prec_minus.svgz b/IconThemes/mono/scalable/actions/prec_minus.svgz
new file mode 100644
index 0000000..ff6159a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prec_minus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prec_plus.svgz b/IconThemes/mono/scalable/actions/prec_plus.svgz
new file mode 100644
index 0000000..6515ebc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prec_plus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/precminus.svgz b/IconThemes/mono/scalable/actions/precminus.svgz
new file mode 100644
index 0000000..5165a58
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/precminus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/precplus.svgz b/IconThemes/mono/scalable/actions/precplus.svgz
new file mode 100644
index 0000000..28c84b0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/precplus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/preverror.svgz b/IconThemes/mono/scalable/actions/preverror.svgz
new file mode 100644
index 0000000..083f580
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/preverror.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prevfuzzy.svgz b/IconThemes/mono/scalable/actions/prevfuzzy.svgz
new file mode 100644
index 0000000..e78ff43
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prevfuzzy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prevfuzzyuntrans.svgz b/IconThemes/mono/scalable/actions/prevfuzzyuntrans.svgz
new file mode 100644
index 0000000..3d35f90
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prevfuzzyuntrans.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/previewprint.svgz b/IconThemes/mono/scalable/actions/previewprint.svgz
new file mode 100644
index 0000000..c51503f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/previewprint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/previous.svgz b/IconThemes/mono/scalable/actions/previous.svgz
new file mode 100644
index 0000000..907c264
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/previous.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prevmarked.svgz b/IconThemes/mono/scalable/actions/prevmarked.svgz
new file mode 100644
index 0000000..a2aab82
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prevmarked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prevpo.svgz b/IconThemes/mono/scalable/actions/prevpo.svgz
new file mode 100644
index 0000000..23d8393
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prevpo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prevtemplate.svgz b/IconThemes/mono/scalable/actions/prevtemplate.svgz
new file mode 100644
index 0000000..90393fd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prevtemplate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prevuntranslated.svgz b/IconThemes/mono/scalable/actions/prevuntranslated.svgz
new file mode 100644
index 0000000..088d411
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prevuntranslated.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/processor.svgz b/IconThemes/mono/scalable/actions/processor.svgz
new file mode 100644
index 0000000..081e570
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/processor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/prod.svgz b/IconThemes/mono/scalable/actions/prod.svgz
new file mode 100644
index 0000000..2a458b1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/prod.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/progress.svgz b/IconThemes/mono/scalable/actions/progress.svgz
new file mode 100644
index 0000000..197c083
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/progress.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/project_open.svgz b/IconThemes/mono/scalable/actions/project_open.svgz
new file mode 100644
index 0000000..643bcc4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/project_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/properties.svgz b/IconThemes/mono/scalable/actions/properties.svgz
new file mode 100644
index 0000000..a31a32f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/properties.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/python.svgz b/IconThemes/mono/scalable/actions/python.svgz
new file mode 100644
index 0000000..598db95
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/python.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/qa.svgz b/IconThemes/mono/scalable/actions/qa.svgz
new file mode 100644
index 0000000..d553fbe
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/qa.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/quadricbeziercurve.svgz b/IconThemes/mono/scalable/actions/quadricbeziercurve.svgz
new file mode 100644
index 0000000..2188903
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/quadricbeziercurve.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/queries.svgz b/IconThemes/mono/scalable/actions/queries.svgz
new file mode 100644
index 0000000..9193e1b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/queries.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/query.svgz b/IconThemes/mono/scalable/actions/query.svgz
new file mode 100644
index 0000000..587320b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/query.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/query_erase.svgz b/IconThemes/mono/scalable/actions/query_erase.svgz
new file mode 100644
index 0000000..29ccb43
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/query_erase.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/query_newobj.svgz b/IconThemes/mono/scalable/actions/query_newobj.svgz
new file mode 100644
index 0000000..2b33b7b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/query_newobj.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/question.svgz b/IconThemes/mono/scalable/actions/question.svgz
new file mode 100644
index 0000000..c988774
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/question.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/question_mark.svgz b/IconThemes/mono/scalable/actions/question_mark.svgz
new file mode 100644
index 0000000..815c63b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/question_mark.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/queue.svgz b/IconThemes/mono/scalable/actions/queue.svgz
new file mode 100644
index 0000000..41038cc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/queue.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/quick_start.svgz b/IconThemes/mono/scalable/actions/quick_start.svgz
new file mode 100644
index 0000000..14d3e4e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/quick_start.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/quiz.svgz b/IconThemes/mono/scalable/actions/quiz.svgz
new file mode 100644
index 0000000..f41b439
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/quiz.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/radicalline.svgz b/IconThemes/mono/scalable/actions/radicalline.svgz
new file mode 100644
index 0000000..6f43fdf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/radicalline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/radio.svgz b/IconThemes/mono/scalable/actions/radio.svgz
new file mode 100644
index 0000000..c44dd85
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/radio.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/raise.svgz b/IconThemes/mono/scalable/actions/raise.svgz
new file mode 100644
index 0000000..2ea7b38
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/raise.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/raiselayer.svgz b/IconThemes/mono/scalable/actions/raiselayer.svgz
new file mode 100644
index 0000000..f14afb9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/raiselayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/random.svgz b/IconThemes/mono/scalable/actions/random.svgz
new file mode 100644
index 0000000..1c3c0d9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/random.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ray.svgz b/IconThemes/mono/scalable/actions/ray.svgz
new file mode 100644
index 0000000..91c5ded
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ray.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rebuild.svgz b/IconThemes/mono/scalable/actions/rebuild.svgz
new file mode 100644
index 0000000..0d21229
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rebuild.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/reconcile.svgz b/IconThemes/mono/scalable/actions/reconcile.svgz
new file mode 100644
index 0000000..260f996
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/reconcile.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rectangle.svgz b/IconThemes/mono/scalable/actions/rectangle.svgz
new file mode 100644
index 0000000..57f4fff
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rectangle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/recur.svgz b/IconThemes/mono/scalable/actions/recur.svgz
new file mode 100644
index 0000000..098f0bc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/recur.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/recursive.svgz b/IconThemes/mono/scalable/actions/recursive.svgz
new file mode 100644
index 0000000..d01d945
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/recursive.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/red_ball.svgz b/IconThemes/mono/scalable/actions/red_ball.svgz
new file mode 100644
index 0000000..01ce3c8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/red_ball.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/redeyes.svgz b/IconThemes/mono/scalable/actions/redeyes.svgz
new file mode 100644
index 0000000..3412f0b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/redeyes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/redo.svgz b/IconThemes/mono/scalable/actions/redo.svgz
new file mode 100644
index 0000000..dd349c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/redo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/relation.svgz b/IconThemes/mono/scalable/actions/relation.svgz
new file mode 100644
index 0000000..48aa0cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/relation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/reload.svgz b/IconThemes/mono/scalable/actions/reload.svgz
new file mode 100644
index 0000000..46ff733
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/reload.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/reload3.svgz b/IconThemes/mono/scalable/actions/reload3.svgz
new file mode 100644
index 0000000..99ef79a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/reload3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/reload_all_tabs.svgz b/IconThemes/mono/scalable/actions/reload_all_tabs.svgz
new file mode 100644
index 0000000..6590649
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/reload_all_tabs.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/reload_page.svgz b/IconThemes/mono/scalable/actions/reload_page.svgz
new file mode 100644
index 0000000..162e419
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/reload_page.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/remcol.svgz b/IconThemes/mono/scalable/actions/remcol.svgz
new file mode 100644
index 0000000..1f55df4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/remcol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/remove.svgz b/IconThemes/mono/scalable/actions/remove.svgz
new file mode 100644
index 0000000..b0d3e52
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/removecell.svgz b/IconThemes/mono/scalable/actions/removecell.svgz
new file mode 100644
index 0000000..0bf286a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/removecell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/removecomment.svgz b/IconThemes/mono/scalable/actions/removecomment.svgz
new file mode 100644
index 0000000..d27d27c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/removecomment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/removepoint.svgz b/IconThemes/mono/scalable/actions/removepoint.svgz
new file mode 100644
index 0000000..63ad1e0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/removepoint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/remrow.svgz b/IconThemes/mono/scalable/actions/remrow.svgz
new file mode 100644
index 0000000..7d44aaa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/remrow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/repeat.svgz b/IconThemes/mono/scalable/actions/repeat.svgz
new file mode 100644
index 0000000..3ba311d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/repeat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/repeat_playlist.svgz b/IconThemes/mono/scalable/actions/repeat_playlist.svgz
new file mode 100644
index 0000000..e12e415
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/repeat_playlist.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/repeat_track.svgz b/IconThemes/mono/scalable/actions/repeat_track.svgz
new file mode 100644
index 0000000..b91c9a1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/repeat_track.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/report.svgz b/IconThemes/mono/scalable/actions/report.svgz
new file mode 100644
index 0000000..aeff06c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/report.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/report_newobj.svgz b/IconThemes/mono/scalable/actions/report_newobj.svgz
new file mode 100644
index 0000000..62f4102
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/report_newobj.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/reports.svgz b/IconThemes/mono/scalable/actions/reports.svgz
new file mode 100644
index 0000000..4878116
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/reports.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/resdiropen.svgz b/IconThemes/mono/scalable/actions/resdiropen.svgz
new file mode 100644
index 0000000..5290e02
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/resdiropen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/reset.svgz b/IconThemes/mono/scalable/actions/reset.svgz
new file mode 100644
index 0000000..980276a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/reset.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/resfiledel.svgz b/IconThemes/mono/scalable/actions/resfiledel.svgz
new file mode 100644
index 0000000..c4070af
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/resfiledel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/resfileedit.svgz b/IconThemes/mono/scalable/actions/resfileedit.svgz
new file mode 100644
index 0000000..726b85b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/resfileedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/resfileinfo.svgz b/IconThemes/mono/scalable/actions/resfileinfo.svgz
new file mode 100644
index 0000000..551f5bf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/resfileinfo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/resfileopen.svgz b/IconThemes/mono/scalable/actions/resfileopen.svgz
new file mode 100644
index 0000000..a4921be
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/resfileopen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/resize_image.svgz b/IconThemes/mono/scalable/actions/resize_image.svgz
new file mode 100644
index 0000000..c1864f8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/resize_image.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/resizecol.svgz b/IconThemes/mono/scalable/actions/resizecol.svgz
new file mode 100644
index 0000000..1e09c4a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/resizecol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/resizerow.svgz b/IconThemes/mono/scalable/actions/resizerow.svgz
new file mode 100644
index 0000000..5dc4526
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/resizerow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/restart.svgz b/IconThemes/mono/scalable/actions/restart.svgz
new file mode 100644
index 0000000..c3a3410
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/restart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/restore.svgz b/IconThemes/mono/scalable/actions/restore.svgz
new file mode 100644
index 0000000..1e0456d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/restore.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/revert.svgz b/IconThemes/mono/scalable/actions/revert.svgz
new file mode 100644
index 0000000..17bd95d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/revert.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rightjust.svgz b/IconThemes/mono/scalable/actions/rightjust.svgz
new file mode 100644
index 0000000..4c6e52c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rightjust.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/roll.svgz b/IconThemes/mono/scalable/actions/roll.svgz
new file mode 100644
index 0000000..03fad8b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/roll.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rotate.svgz b/IconThemes/mono/scalable/actions/rotate.svgz
new file mode 100644
index 0000000..e2e5faf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rotate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rotate_ccw.svgz b/IconThemes/mono/scalable/actions/rotate_ccw.svgz
new file mode 100644
index 0000000..cd246ff
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rotate_ccw.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rotate_cw.svgz b/IconThemes/mono/scalable/actions/rotate_cw.svgz
new file mode 100644
index 0000000..a1461cc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rotate_cw.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rotate_left.svgz b/IconThemes/mono/scalable/actions/rotate_left.svgz
new file mode 100644
index 0000000..92ccca0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rotate_left.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rotate_right.svgz b/IconThemes/mono/scalable/actions/rotate_right.svgz
new file mode 100644
index 0000000..083d2b9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rotate_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rotation.svgz b/IconThemes/mono/scalable/actions/rotation.svgz
new file mode 100644
index 0000000..109fd49
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rotation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rotation_acw.svgz b/IconThemes/mono/scalable/actions/rotation_acw.svgz
new file mode 100644
index 0000000..46bd03f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rotation_acw.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rotation_cw.svgz b/IconThemes/mono/scalable/actions/rotation_cw.svgz
new file mode 100644
index 0000000..94005fb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rotation_cw.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rowcol.svgz b/IconThemes/mono/scalable/actions/rowcol.svgz
new file mode 100644
index 0000000..0cd0524
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rowcol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rsibreak0.svgz b/IconThemes/mono/scalable/actions/rsibreak0.svgz
new file mode 100644
index 0000000..0b91808
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rsibreak0.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rsibreak1.svgz b/IconThemes/mono/scalable/actions/rsibreak1.svgz
new file mode 100644
index 0000000..15b6877
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rsibreak1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rsibreak2.svgz b/IconThemes/mono/scalable/actions/rsibreak2.svgz
new file mode 100644
index 0000000..065edb7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rsibreak2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rsibreak3.svgz b/IconThemes/mono/scalable/actions/rsibreak3.svgz
new file mode 100644
index 0000000..8bae053
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rsibreak3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rsibreak4.svgz b/IconThemes/mono/scalable/actions/rsibreak4.svgz
new file mode 100644
index 0000000..7fa1e8a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rsibreak4.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rsibreakx.svgz b/IconThemes/mono/scalable/actions/rsibreakx.svgz
new file mode 100644
index 0000000..d705064
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rsibreakx.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rss_tag.svgz b/IconThemes/mono/scalable/actions/rss_tag.svgz
new file mode 100644
index 0000000..23f9704
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rss_tag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rsub.svgz b/IconThemes/mono/scalable/actions/rsub.svgz
new file mode 100644
index 0000000..a272aa1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rsub.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/rsup.svgz b/IconThemes/mono/scalable/actions/rsup.svgz
new file mode 100644
index 0000000..cae1e9c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/rsup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/run.svgz b/IconThemes/mono/scalable/actions/run.svgz
new file mode 100644
index 0000000..798ff0f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/run.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/run_bounding.svgz b/IconThemes/mono/scalable/actions/run_bounding.svgz
new file mode 100644
index 0000000..ec0cc94
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/run_bounding.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/run_not.svgz b/IconThemes/mono/scalable/actions/run_not.svgz
new file mode 100644
index 0000000..976d7e0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/run_not.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/run_skip.svgz b/IconThemes/mono/scalable/actions/run_skip.svgz
new file mode 100644
index 0000000..6d941ca
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/run_skip.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/runprog.svgz b/IconThemes/mono/scalable/actions/runprog.svgz
new file mode 100644
index 0000000..4cfc643
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/runprog.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/saturation.svgz b/IconThemes/mono/scalable/actions/saturation.svgz
new file mode 100644
index 0000000..b50de76
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/saturation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/save.svgz b/IconThemes/mono/scalable/actions/save.svgz
new file mode 100644
index 0000000..a709a5f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/save.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/save_all.svgz b/IconThemes/mono/scalable/actions/save_all.svgz
new file mode 100644
index 0000000..18ead6b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/save_all.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/saveall.svgz b/IconThemes/mono/scalable/actions/saveall.svgz
new file mode 100644
index 0000000..ea378bf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/saveall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scale.svgz b/IconThemes/mono/scalable/actions/scale.svgz
new file mode 100644
index 0000000..92ec704
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scale.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scaleorig.svgz b/IconThemes/mono/scalable/actions/scaleorig.svgz
new file mode 100644
index 0000000..263e2a6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scaleorig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scaletoheight.svgz b/IconThemes/mono/scalable/actions/scaletoheight.svgz
new file mode 100644
index 0000000..7a4354f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scaletoheight.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scaletowidth.svgz b/IconThemes/mono/scalable/actions/scaletowidth.svgz
new file mode 100644
index 0000000..fb6ee2c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scaletowidth.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scaling.svgz b/IconThemes/mono/scalable/actions/scaling.svgz
new file mode 100644
index 0000000..d0f5b3d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scaling.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scheme_acoustic.svgz b/IconThemes/mono/scalable/actions/scheme_acoustic.svgz
new file mode 100644
index 0000000..0fea837
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scheme_acoustic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scheme_advanced_powersave.svgz b/IconThemes/mono/scalable/actions/scheme_advanced_powersave.svgz
new file mode 100644
index 0000000..a8015ad
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scheme_advanced_powersave.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scheme_power.svgz b/IconThemes/mono/scalable/actions/scheme_power.svgz
new file mode 100644
index 0000000..40e80dc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scheme_power.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scheme_powersave.svgz b/IconThemes/mono/scalable/actions/scheme_powersave.svgz
new file mode 100644
index 0000000..42c2eb0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scheme_powersave.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/scheme_presentation.svgz b/IconThemes/mono/scalable/actions/scheme_presentation.svgz
new file mode 100644
index 0000000..62af9b5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/scheme_presentation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/search.svgz b/IconThemes/mono/scalable/actions/search.svgz
new file mode 100644
index 0000000..5dba128
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/search.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/search2msgstr.svgz b/IconThemes/mono/scalable/actions/search2msgstr.svgz
new file mode 100644
index 0000000..fa16f9d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/search2msgstr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/segment.svgz b/IconThemes/mono/scalable/actions/segment.svgz
new file mode 100644
index 0000000..395ee2d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/segment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/segment_midpoint.svgz b/IconThemes/mono/scalable/actions/segment_midpoint.svgz
new file mode 100644
index 0000000..d145bb6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/segment_midpoint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/segmentaxis.svgz b/IconThemes/mono/scalable/actions/segmentaxis.svgz
new file mode 100644
index 0000000..69e6719
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/segmentaxis.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/select.svgz b/IconThemes/mono/scalable/actions/select.svgz
new file mode 100644
index 0000000..e187df7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/select.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/select_item.svgz b/IconThemes/mono/scalable/actions/select_item.svgz
new file mode 100644
index 0000000..206911f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/select_item.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/selectcircle.svgz b/IconThemes/mono/scalable/actions/selectcircle.svgz
new file mode 100644
index 0000000..7774e91
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/selectcircle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/selectrect.svgz b/IconThemes/mono/scalable/actions/selectrect.svgz
new file mode 100644
index 0000000..d1e546d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/selectrect.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/send_backward.svgz b/IconThemes/mono/scalable/actions/send_backward.svgz
new file mode 100644
index 0000000..b6a1e3f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/send_backward.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/send_stencil_to_back.svgz b/IconThemes/mono/scalable/actions/send_stencil_to_back.svgz
new file mode 100644
index 0000000..fdfc060
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/send_stencil_to_back.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/series.svgz b/IconThemes/mono/scalable/actions/series.svgz
new file mode 100644
index 0000000..15d280b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/series.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/server.svgz b/IconThemes/mono/scalable/actions/server.svgz
new file mode 100644
index 0000000..734ec42
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/server.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/services.svgz b/IconThemes/mono/scalable/actions/services.svgz
new file mode 100644
index 0000000..fd5dce0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/services.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadow.svgz b/IconThemes/mono/scalable/actions/shadow.svgz
new file mode 100644
index 0000000..c32d5ad
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadowB.svgz b/IconThemes/mono/scalable/actions/shadowB.svgz
new file mode 100644
index 0000000..9f65a5b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadowB.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadowL.svgz b/IconThemes/mono/scalable/actions/shadowL.svgz
new file mode 100644
index 0000000..21206ad
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadowL.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadowLB.svgz b/IconThemes/mono/scalable/actions/shadowLB.svgz
new file mode 100644
index 0000000..14ab452
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadowLB.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadowLU.svgz b/IconThemes/mono/scalable/actions/shadowLU.svgz
new file mode 100644
index 0000000..dc44f15
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadowLU.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadowR.svgz b/IconThemes/mono/scalable/actions/shadowR.svgz
new file mode 100644
index 0000000..3775675
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadowR.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadowRB.svgz b/IconThemes/mono/scalable/actions/shadowRB.svgz
new file mode 100644
index 0000000..080310a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadowRB.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadowRU.svgz b/IconThemes/mono/scalable/actions/shadowRU.svgz
new file mode 100644
index 0000000..9e041ed
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadowRU.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shadowU.svgz b/IconThemes/mono/scalable/actions/shadowU.svgz
new file mode 100644
index 0000000..bb3262e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shadowU.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/share.svgz b/IconThemes/mono/scalable/actions/share.svgz
new file mode 100644
index 0000000..201a10a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/share.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shear.svgz b/IconThemes/mono/scalable/actions/shear.svgz
new file mode 100644
index 0000000..1f2e2ce
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shear.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/show_offliners.svgz b/IconThemes/mono/scalable/actions/show_offliners.svgz
new file mode 100644
index 0000000..1925fae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/show_offliners.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/show_table_column.svgz b/IconThemes/mono/scalable/actions/show_table_column.svgz
new file mode 100644
index 0000000..2cfa2e9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/show_table_column.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/show_table_row.svgz b/IconThemes/mono/scalable/actions/show_table_row.svgz
new file mode 100644
index 0000000..42e4dbd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/show_table_row.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/showmenu.svgz b/IconThemes/mono/scalable/actions/showmenu.svgz
new file mode 100644
index 0000000..3dd1205
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/showmenu.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/shuffle.svgz b/IconThemes/mono/scalable/actions/shuffle.svgz
new file mode 100644
index 0000000..b5ebb1c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/shuffle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sidebar.svgz b/IconThemes/mono/scalable/actions/sidebar.svgz
new file mode 100644
index 0000000..e8512d9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sidebar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/signalslot.svgz b/IconThemes/mono/scalable/actions/signalslot.svgz
new file mode 100644
index 0000000..056cb46
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/signalslot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/signature.svgz b/IconThemes/mono/scalable/actions/signature.svgz
new file mode 100644
index 0000000..4f21da9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/signature.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/similitude.svgz b/IconThemes/mono/scalable/actions/similitude.svgz
new file mode 100644
index 0000000..31f25a9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/similitude.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sizer.svgz b/IconThemes/mono/scalable/actions/sizer.svgz
new file mode 100644
index 0000000..33c508d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sizer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/slide.svgz b/IconThemes/mono/scalable/actions/slide.svgz
new file mode 100644
index 0000000..134c4f4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/slide.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/slider.svgz b/IconThemes/mono/scalable/actions/slider.svgz
new file mode 100644
index 0000000..26c6ee9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/slider.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/slideshow.svgz b/IconThemes/mono/scalable/actions/slideshow.svgz
new file mode 100644
index 0000000..c11963e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/slideshow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/slope.svgz b/IconThemes/mono/scalable/actions/slope.svgz
new file mode 100644
index 0000000..d83ee94
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/slope.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/smallcal.svgz b/IconThemes/mono/scalable/actions/smallcal.svgz
new file mode 100644
index 0000000..8a71b55
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/smallcal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/smallclock.svgz b/IconThemes/mono/scalable/actions/smallclock.svgz
new file mode 100644
index 0000000..1df1cda
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/smallclock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/smallthumbnails.svgz b/IconThemes/mono/scalable/actions/smallthumbnails.svgz
new file mode 100644
index 0000000..33cc60c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/smallthumbnails.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/solarizetool.svgz b/IconThemes/mono/scalable/actions/solarizetool.svgz
new file mode 100644
index 0000000..dff05a8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/solarizetool.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sort_az.svgz b/IconThemes/mono/scalable/actions/sort_az.svgz
new file mode 100644
index 0000000..569b822
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sort_az.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sort_decrease.svgz b/IconThemes/mono/scalable/actions/sort_decrease.svgz
new file mode 100644
index 0000000..ab67242
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sort_decrease.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sort_incr.svgz b/IconThemes/mono/scalable/actions/sort_incr.svgz
new file mode 100644
index 0000000..0f7d51d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sort_incr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sort_za.svgz b/IconThemes/mono/scalable/actions/sort_za.svgz
new file mode 100644
index 0000000..cf7eff3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sort_za.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/soulseekdown.svgz b/IconThemes/mono/scalable/actions/soulseekdown.svgz
new file mode 100644
index 0000000..b2ccd76
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/soulseekdown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/soulseekup.svgz b/IconThemes/mono/scalable/actions/soulseekup.svgz
new file mode 100644
index 0000000..8c2f32c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/soulseekup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/speak.svgz b/IconThemes/mono/scalable/actions/speak.svgz
new file mode 100644
index 0000000..64ba3d3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/speak.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/speaker.svgz b/IconThemes/mono/scalable/actions/speaker.svgz
new file mode 100644
index 0000000..58a88f6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/speaker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/special_paste.svgz b/IconThemes/mono/scalable/actions/special_paste.svgz
new file mode 100644
index 0000000..1b5866d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/special_paste.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spectrum.svgz b/IconThemes/mono/scalable/actions/spectrum.svgz
new file mode 100644
index 0000000..8c073d1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spectrum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spellcheck.svgz b/IconThemes/mono/scalable/actions/spellcheck.svgz
new file mode 100644
index 0000000..662da36
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spellcheck.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spellcheck_actual.svgz b/IconThemes/mono/scalable/actions/spellcheck_actual.svgz
new file mode 100644
index 0000000..c144942
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spellcheck_actual.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spellcheck_from_cursor.svgz b/IconThemes/mono/scalable/actions/spellcheck_from_cursor.svgz
new file mode 100644
index 0000000..002173f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spellcheck_from_cursor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spellcheck_selected.svgz b/IconThemes/mono/scalable/actions/spellcheck_selected.svgz
new file mode 100644
index 0000000..56aefb4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spellcheck_selected.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spin.svgz b/IconThemes/mono/scalable/actions/spin.svgz
new file mode 100644
index 0000000..090df64
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spnewgame.svgz b/IconThemes/mono/scalable/actions/spnewgame.svgz
new file mode 100644
index 0000000..ef19e97
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spnewgame.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spnewround.svgz b/IconThemes/mono/scalable/actions/spnewround.svgz
new file mode 100644
index 0000000..0146741
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spnewround.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sppausegame.svgz b/IconThemes/mono/scalable/actions/sppausegame.svgz
new file mode 100644
index 0000000..3f47cb8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sppausegame.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/spring.svgz b/IconThemes/mono/scalable/actions/spring.svgz
new file mode 100644
index 0000000..db580b0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/spring.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sqrt.svgz b/IconThemes/mono/scalable/actions/sqrt.svgz
new file mode 100644
index 0000000..4af797c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sqrt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/square.svgz b/IconThemes/mono/scalable/actions/square.svgz
new file mode 100644
index 0000000..6ba8e45
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/square.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/stamp.svgz b/IconThemes/mono/scalable/actions/stamp.svgz
new file mode 100644
index 0000000..7d40578
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/stamp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/stand_by.svgz b/IconThemes/mono/scalable/actions/stand_by.svgz
new file mode 100644
index 0000000..92b1a97
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/stand_by.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/start.svgz b/IconThemes/mono/scalable/actions/start.svgz
new file mode 100644
index 0000000..99dfc09
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/start.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/state_data.svgz b/IconThemes/mono/scalable/actions/state_data.svgz
new file mode 100644
index 0000000..e22de5b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/state_data.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/state_edit.svgz b/IconThemes/mono/scalable/actions/state_edit.svgz
new file mode 100644
index 0000000..5f5e57b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/state_edit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/state_sql.svgz b/IconThemes/mono/scalable/actions/state_sql.svgz
new file mode 100644
index 0000000..cb5daa8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/state_sql.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/state_text.svgz b/IconThemes/mono/scalable/actions/state_text.svgz
new file mode 100644
index 0000000..93dc3d8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/state_text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/statematter.svgz b/IconThemes/mono/scalable/actions/statematter.svgz
new file mode 100644
index 0000000..d15dcdb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/statematter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/statistics.svgz b/IconThemes/mono/scalable/actions/statistics.svgz
new file mode 100644
index 0000000..a0fa0a8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/statistics.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/step.svgz b/IconThemes/mono/scalable/actions/step.svgz
new file mode 100644
index 0000000..6f2ae14
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/step.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/stop.svgz b/IconThemes/mono/scalable/actions/stop.svgz
new file mode 100644
index 0000000..78285bd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/stop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/strempty.svgz b/IconThemes/mono/scalable/actions/strempty.svgz
new file mode 100644
index 0000000..ccf9502
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/strempty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/stretch.svgz b/IconThemes/mono/scalable/actions/stretch.svgz
new file mode 100644
index 0000000..9659adf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/stretch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/strikethrough.svgz b/IconThemes/mono/scalable/actions/strikethrough.svgz
new file mode 100644
index 0000000..6e3cf42
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/strikethrough.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/strokedocker.svgz b/IconThemes/mono/scalable/actions/strokedocker.svgz
new file mode 100644
index 0000000..65085f0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/strokedocker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/styledocker.svgz b/IconThemes/mono/scalable/actions/styledocker.svgz
new file mode 100644
index 0000000..ba7ff07
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/styledocker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sub.svgz b/IconThemes/mono/scalable/actions/sub.svgz
new file mode 100644
index 0000000..5f9c3e9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sub.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/submit.svgz b/IconThemes/mono/scalable/actions/submit.svgz
new file mode 100644
index 0000000..7c88b9a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/submit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/sum.svgz b/IconThemes/mono/scalable/actions/sum.svgz
new file mode 100644
index 0000000..641dd06
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/sum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/super.svgz b/IconThemes/mono/scalable/actions/super.svgz
new file mode 100644
index 0000000..69331eb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/super.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/superimpose.svgz b/IconThemes/mono/scalable/actions/superimpose.svgz
new file mode 100644
index 0000000..670b2e3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/superimpose.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/suspend.svgz b/IconThemes/mono/scalable/actions/suspend.svgz
new file mode 100644
index 0000000..cf6dab3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/suspend.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/suspend_to_disk.svgz b/IconThemes/mono/scalable/actions/suspend_to_disk.svgz
new file mode 100644
index 0000000..83f79bc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/suspend_to_disk.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/suspend_to_ram.svgz b/IconThemes/mono/scalable/actions/suspend_to_ram.svgz
new file mode 100644
index 0000000..cf6dab3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/suspend_to_ram.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/svn_add.svgz b/IconThemes/mono/scalable/actions/svn_add.svgz
new file mode 100644
index 0000000..8741f9e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/svn_add.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/svn_branch.svgz b/IconThemes/mono/scalable/actions/svn_branch.svgz
new file mode 100644
index 0000000..cc37d46
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/svn_branch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/svn_merge.svgz b/IconThemes/mono/scalable/actions/svn_merge.svgz
new file mode 100644
index 0000000..1c16442
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/svn_merge.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/svn_remove.svgz b/IconThemes/mono/scalable/actions/svn_remove.svgz
new file mode 100644
index 0000000..e583ba8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/svn_remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/svn_status.svgz b/IconThemes/mono/scalable/actions/svn_status.svgz
new file mode 100644
index 0000000..373369b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/svn_status.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/svn_switch.svgz b/IconThemes/mono/scalable/actions/svn_switch.svgz
new file mode 100644
index 0000000..4ad5f7c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/svn_switch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/switchuser.svgz b/IconThemes/mono/scalable/actions/switchuser.svgz
new file mode 100644
index 0000000..a17a39a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/switchuser.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/syntax.svgz b/IconThemes/mono/scalable/actions/syntax.svgz
new file mode 100644
index 0000000..da79765
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/syntax.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_breakoff.svgz b/IconThemes/mono/scalable/actions/tab_breakoff.svgz
new file mode 100644
index 0000000..b350662
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_breakoff.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_duplicate.svgz b/IconThemes/mono/scalable/actions/tab_duplicate.svgz
new file mode 100644
index 0000000..6679da6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_duplicate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_first.svgz b/IconThemes/mono/scalable/actions/tab_first.svgz
new file mode 100644
index 0000000..7bdc022
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_first.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_last.svgz b/IconThemes/mono/scalable/actions/tab_last.svgz
new file mode 100644
index 0000000..799cc4b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_last.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_left.svgz b/IconThemes/mono/scalable/actions/tab_left.svgz
new file mode 100644
index 0000000..0578f04
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_left.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_new.svgz b/IconThemes/mono/scalable/actions/tab_new.svgz
new file mode 100644
index 0000000..52da9bf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_new_raised.svgz b/IconThemes/mono/scalable/actions/tab_new_raised.svgz
new file mode 100644
index 0000000..5fddab7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_new_raised.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_remove.svgz b/IconThemes/mono/scalable/actions/tab_remove.svgz
new file mode 100644
index 0000000..236454c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tab_right.svgz b/IconThemes/mono/scalable/actions/tab_right.svgz
new file mode 100644
index 0000000..e0be4b7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tab_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/table.svgz b/IconThemes/mono/scalable/actions/table.svgz
new file mode 100644
index 0000000..f082451
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/table.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/table_newobj.svgz b/IconThemes/mono/scalable/actions/table_newobj.svgz
new file mode 100644
index 0000000..1db6d6e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/table_newobj.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tables.svgz b/IconThemes/mono/scalable/actions/tables.svgz
new file mode 100644
index 0000000..258cca5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tables.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tabwidget.svgz b/IconThemes/mono/scalable/actions/tabwidget.svgz
new file mode 100644
index 0000000..bbd261d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tabwidget.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag-folder.svgz b/IconThemes/mono/scalable/actions/tag-folder.svgz
new file mode 100644
index 0000000..d15c7ff
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag-folder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_a.svgz b/IconThemes/mono/scalable/actions/tag_a.svgz
new file mode 100644
index 0000000..5994f22
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_a.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_bold.svgz b/IconThemes/mono/scalable/actions/tag_bold.svgz
new file mode 100644
index 0000000..f0c44a3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_bold.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_br.svgz b/IconThemes/mono/scalable/actions/tag_br.svgz
new file mode 100644
index 0000000..5f22b0a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_br.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_i.svgz b/IconThemes/mono/scalable/actions/tag_i.svgz
new file mode 100644
index 0000000..00c4025
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_i.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_image.svgz b/IconThemes/mono/scalable/actions/tag_image.svgz
new file mode 100644
index 0000000..bd00208
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_image.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_li.svgz b/IconThemes/mono/scalable/actions/tag_li.svgz
new file mode 100644
index 0000000..d63e563
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_li.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_mail.svgz b/IconThemes/mono/scalable/actions/tag_mail.svgz
new file mode 100644
index 0000000..07ae726
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_mail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_ol.svgz b/IconThemes/mono/scalable/actions/tag_ol.svgz
new file mode 100644
index 0000000..d63e563
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_ol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_sub.svgz b/IconThemes/mono/scalable/actions/tag_sub.svgz
new file mode 100644
index 0000000..5f9c3e9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_sub.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_sup.svgz b/IconThemes/mono/scalable/actions/tag_sup.svgz
new file mode 100644
index 0000000..69331eb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_sup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_u.svgz b/IconThemes/mono/scalable/actions/tag_u.svgz
new file mode 100644
index 0000000..2639691
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_u.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_ul.svgz b/IconThemes/mono/scalable/actions/tag_ul.svgz
new file mode 100644
index 0000000..1ad5bcd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_ul.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tag_ulink.svgz b/IconThemes/mono/scalable/actions/tag_ulink.svgz
new file mode 100644
index 0000000..c2ae85c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tag_ulink.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tangent.svgz b/IconThemes/mono/scalable/actions/tangent.svgz
new file mode 100644
index 0000000..4dec06e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tangent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tea_anim1.svgz b/IconThemes/mono/scalable/actions/tea_anim1.svgz
new file mode 100644
index 0000000..0ee2c8a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tea_anim1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tea_anim2.svgz b/IconThemes/mono/scalable/actions/tea_anim2.svgz
new file mode 100644
index 0000000..45dfa4d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tea_anim2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tea_not_ready.svgz b/IconThemes/mono/scalable/actions/tea_not_ready.svgz
new file mode 100644
index 0000000..09eb9ed
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tea_not_ready.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_a4.svgz b/IconThemes/mono/scalable/actions/template_a4.svgz
new file mode 100644
index 0000000..2f465d8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_a4.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_balancesheet.svgz b/IconThemes/mono/scalable/actions/template_balancesheet.svgz
new file mode 100644
index 0000000..2f5c234
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_balancesheet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_barchart.svgz b/IconThemes/mono/scalable/actions/template_barchart.svgz
new file mode 100644
index 0000000..5d16c74
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_barchart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_basicworkflow.svgz b/IconThemes/mono/scalable/actions/template_basicworkflow.svgz
new file mode 100644
index 0000000..7d5df78
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_basicworkflow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_bmi.svgz b/IconThemes/mono/scalable/actions/template_bmi.svgz
new file mode 100644
index 0000000..85822d3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_bmi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_businesscards10.svgz b/IconThemes/mono/scalable/actions/template_businesscards10.svgz
new file mode 100644
index 0000000..c13bf55
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_businesscards10.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_businesscards16.svgz b/IconThemes/mono/scalable/actions/template_businesscards16.svgz
new file mode 100644
index 0000000..96e8496
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_businesscards16.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_cmyk_empty.svgz b/IconThemes/mono/scalable/actions/template_cmyk_empty.svgz
new file mode 100644
index 0000000..2ebb3a4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_cmyk_empty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_creditcardtracker.svgz b/IconThemes/mono/scalable/actions/template_creditcardtracker.svgz
new file mode 100644
index 0000000..2c02443
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_creditcardtracker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_empty.svgz b/IconThemes/mono/scalable/actions/template_empty.svgz
new file mode 100644
index 0000000..af40e88
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_empty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_emptylandscape.svgz b/IconThemes/mono/scalable/actions/template_emptylandscape.svgz
new file mode 100644
index 0000000..9314c79
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_emptylandscape.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_emptyportrait.svgz b/IconThemes/mono/scalable/actions/template_emptyportrait.svgz
new file mode 100644
index 0000000..82c5ff8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_emptyportrait.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_envelopec6.svgz b/IconThemes/mono/scalable/actions/template_envelopec6.svgz
new file mode 100644
index 0000000..678fd46
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_envelopec6.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_envelopedl.svgz b/IconThemes/mono/scalable/actions/template_envelopedl.svgz
new file mode 100644
index 0000000..5d26a80
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_envelopedl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_expensereport.svgz b/IconThemes/mono/scalable/actions/template_expensereport.svgz
new file mode 100644
index 0000000..7b69c25
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_expensereport.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_fax.svgz b/IconThemes/mono/scalable/actions/template_fax.svgz
new file mode 100644
index 0000000..d355897
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_fax.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_gray_empty.svgz b/IconThemes/mono/scalable/actions/template_gray_empty.svgz
new file mode 100644
index 0000000..e882dfc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_gray_empty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_invoice.svgz b/IconThemes/mono/scalable/actions/template_invoice.svgz
new file mode 100644
index 0000000..ebb5b03
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_invoice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_iso.svgz b/IconThemes/mono/scalable/actions/template_iso.svgz
new file mode 100644
index 0000000..e750cc2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_iso.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_letter.svgz b/IconThemes/mono/scalable/actions/template_letter.svgz
new file mode 100644
index 0000000..39345d5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_letter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_memo.svgz b/IconThemes/mono/scalable/actions/template_memo.svgz
new file mode 100644
index 0000000..5447a68
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_memo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_menuplan.svgz b/IconThemes/mono/scalable/actions/template_menuplan.svgz
new file mode 100644
index 0000000..8d31603
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_menuplan.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_onecolumnlandscape.svgz b/IconThemes/mono/scalable/actions/template_onecolumnlandscape.svgz
new file mode 100644
index 0000000..d2c7f0c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_onecolumnlandscape.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_onecolumnportrait.svgz b/IconThemes/mono/scalable/actions/template_onecolumnportrait.svgz
new file mode 100644
index 0000000..dced194
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_onecolumnportrait.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_packingslip.svgz b/IconThemes/mono/scalable/actions/template_packingslip.svgz
new file mode 100644
index 0000000..65a8017
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_packingslip.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_plaintext.svgz b/IconThemes/mono/scalable/actions/template_plaintext.svgz
new file mode 100644
index 0000000..222c26f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_plaintext.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_pricequotation.svgz b/IconThemes/mono/scalable/actions/template_pricequotation.svgz
new file mode 100644
index 0000000..98d295e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_pricequotation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_rgb_empty.svgz b/IconThemes/mono/scalable/actions/template_rgb_empty.svgz
new file mode 100644
index 0000000..9b09942
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_rgb_empty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_simplelayout.svgz b/IconThemes/mono/scalable/actions/template_simplelayout.svgz
new file mode 100644
index 0000000..91734a9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_simplelayout.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_studentidcard.svgz b/IconThemes/mono/scalable/actions/template_studentidcard.svgz
new file mode 100644
index 0000000..b65efcd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_studentidcard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_timechart.svgz b/IconThemes/mono/scalable/actions/template_timechart.svgz
new file mode 100644
index 0000000..dc94e28
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_timechart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_titlelandscape.svgz b/IconThemes/mono/scalable/actions/template_titlelandscape.svgz
new file mode 100644
index 0000000..5b4e4af
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_titlelandscape.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_titleportrait.svgz b/IconThemes/mono/scalable/actions/template_titleportrait.svgz
new file mode 100644
index 0000000..644aea0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_titleportrait.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_twocolumnlandscape.svgz b/IconThemes/mono/scalable/actions/template_twocolumnlandscape.svgz
new file mode 100644
index 0000000..bb24682
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_twocolumnlandscape.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_twocolumnportrait.svgz b/IconThemes/mono/scalable/actions/template_twocolumnportrait.svgz
new file mode 100644
index 0000000..0681b50
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_twocolumnportrait.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_twocolumns.svgz b/IconThemes/mono/scalable/actions/template_twocolumns.svgz
new file mode 100644
index 0000000..7087203
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_twocolumns.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_us.svgz b/IconThemes/mono/scalable/actions/template_us.svgz
new file mode 100644
index 0000000..a5734c1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_us.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_vacationchecklist.svgz b/IconThemes/mono/scalable/actions/template_vacationchecklist.svgz
new file mode 100644
index 0000000..ad3f4ba
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_vacationchecklist.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/template_worksheet.svgz b/IconThemes/mono/scalable/actions/template_worksheet.svgz
new file mode 100644
index 0000000..28a110d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/template_worksheet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/test.svgz b/IconThemes/mono/scalable/actions/test.svgz
new file mode 100644
index 0000000..d859383
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/test.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/test_it.svgz b/IconThemes/mono/scalable/actions/test_it.svgz
new file mode 100644
index 0000000..6c7d206
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/test_it.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/testcollinear.svgz b/IconThemes/mono/scalable/actions/testcollinear.svgz
new file mode 100644
index 0000000..90d6ad2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/testcollinear.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/testcontains.svgz b/IconThemes/mono/scalable/actions/testcontains.svgz
new file mode 100644
index 0000000..0179cf3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/testcontains.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/testdistance.svgz b/IconThemes/mono/scalable/actions/testdistance.svgz
new file mode 100644
index 0000000..f4eb02f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/testdistance.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/testorthogonal.svgz b/IconThemes/mono/scalable/actions/testorthogonal.svgz
new file mode 100644
index 0000000..f1ac78f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/testorthogonal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/testparallel.svgz b/IconThemes/mono/scalable/actions/testparallel.svgz
new file mode 100644
index 0000000..8d088a7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/testparallel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text.svgz b/IconThemes/mono/scalable/actions/text.svgz
new file mode 100644
index 0000000..ef43828
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_block.svgz b/IconThemes/mono/scalable/actions/text_block.svgz
new file mode 100644
index 0000000..683949d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_block.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_bold.svgz b/IconThemes/mono/scalable/actions/text_bold.svgz
new file mode 100644
index 0000000..188cb9d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_bold.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_bottom.svgz b/IconThemes/mono/scalable/actions/text_bottom.svgz
new file mode 100644
index 0000000..db412fe
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_bottom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_center.svgz b/IconThemes/mono/scalable/actions/text_center.svgz
new file mode 100644
index 0000000..51f686b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_center.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_italic.svgz b/IconThemes/mono/scalable/actions/text_italic.svgz
new file mode 100644
index 0000000..7188b2a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_italic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_left.svgz b/IconThemes/mono/scalable/actions/text_left.svgz
new file mode 100644
index 0000000..e9b60bf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_left.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_right.svgz b/IconThemes/mono/scalable/actions/text_right.svgz
new file mode 100644
index 0000000..111a129
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_strike.svgz b/IconThemes/mono/scalable/actions/text_strike.svgz
new file mode 100644
index 0000000..7c6d67c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_strike.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_sub.svgz b/IconThemes/mono/scalable/actions/text_sub.svgz
new file mode 100644
index 0000000..39ae0a2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_sub.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_super.svgz b/IconThemes/mono/scalable/actions/text_super.svgz
new file mode 100644
index 0000000..09f14b6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_super.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_top.svgz b/IconThemes/mono/scalable/actions/text_top.svgz
new file mode 100644
index 0000000..cae3832
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_top.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_under.svgz b/IconThemes/mono/scalable/actions/text_under.svgz
new file mode 100644
index 0000000..3aeca16
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_under.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/text_underline.svgz b/IconThemes/mono/scalable/actions/text_underline.svgz
new file mode 100644
index 0000000..32e8907
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/text_underline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/textcolor.svgz b/IconThemes/mono/scalable/actions/textcolor.svgz
new file mode 100644
index 0000000..6a0b0ea
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/textcolor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/textedit.svgz b/IconThemes/mono/scalable/actions/textedit.svgz
new file mode 100644
index 0000000..d982da3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/textedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/textwaterfall.svgz b/IconThemes/mono/scalable/actions/textwaterfall.svgz
new file mode 100644
index 0000000..2113315
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/textwaterfall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/thumbnail.svgz b/IconThemes/mono/scalable/actions/thumbnail.svgz
new file mode 100644
index 0000000..02c92bf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/thumbnail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/timeedit.svgz b/IconThemes/mono/scalable/actions/timeedit.svgz
new file mode 100644
index 0000000..052e3f3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/timeedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/timeline.svgz b/IconThemes/mono/scalable/actions/timeline.svgz
new file mode 100644
index 0000000..30a78c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/timeline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/timespan.svgz b/IconThemes/mono/scalable/actions/timespan.svgz
new file mode 100644
index 0000000..80ecf0b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/timespan.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/timings.svgz b/IconThemes/mono/scalable/actions/timings.svgz
new file mode 100644
index 0000000..7537b1b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/timings.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/today.svgz b/IconThemes/mono/scalable/actions/today.svgz
new file mode 100644
index 0000000..15571e5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/today.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/todo.svgz b/IconThemes/mono/scalable/actions/todo.svgz
new file mode 100644
index 0000000..41f01c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/todo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/toggle_log.svgz b/IconThemes/mono/scalable/actions/toggle_log.svgz
new file mode 100644
index 0000000..68ddbb1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/toggle_log.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/togglefuzzy.svgz b/IconThemes/mono/scalable/actions/togglefuzzy.svgz
new file mode 100644
index 0000000..ec5940b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/togglefuzzy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_brush.svgz b/IconThemes/mono/scalable/actions/tool_brush.svgz
new file mode 100644
index 0000000..2eaf1aa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_brush.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_brush_selection.svgz b/IconThemes/mono/scalable/actions/tool_brush_selection.svgz
new file mode 100644
index 0000000..7a04309
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_brush_selection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_clipboard.svgz b/IconThemes/mono/scalable/actions/tool_clipboard.svgz
new file mode 100644
index 0000000..15273db
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_clipboard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_color_picker.svgz b/IconThemes/mono/scalable/actions/tool_color_picker.svgz
new file mode 100644
index 0000000..b51b601
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_color_picker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_color_washer.svgz b/IconThemes/mono/scalable/actions/tool_color_washer.svgz
new file mode 100644
index 0000000..9c233ad
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_color_washer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_curve.svgz b/IconThemes/mono/scalable/actions/tool_curve.svgz
new file mode 100644
index 0000000..850656f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_curve.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_delay.svgz b/IconThemes/mono/scalable/actions/tool_delay.svgz
new file mode 100644
index 0000000..597c5ae
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_delay.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_delete.svgz b/IconThemes/mono/scalable/actions/tool_delete.svgz
new file mode 100644
index 0000000..a8f439d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_delete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_disconnect.svgz b/IconThemes/mono/scalable/actions/tool_disconnect.svgz
new file mode 100644
index 0000000..4a2c99e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_disconnect.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_dock.svgz b/IconThemes/mono/scalable/actions/tool_dock.svgz
new file mode 100644
index 0000000..a43d9c3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_dock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_drop_target.svgz b/IconThemes/mono/scalable/actions/tool_drop_target.svgz
new file mode 100644
index 0000000..cb11241
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_drop_target.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_ellipse.svgz b/IconThemes/mono/scalable/actions/tool_ellipse.svgz
new file mode 100644
index 0000000..7b08dde
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_ellipse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_elliptical_selection.svgz b/IconThemes/mono/scalable/actions/tool_elliptical_selection.svgz
new file mode 100644
index 0000000..a333672
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_elliptical_selection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_eraser.svgz b/IconThemes/mono/scalable/actions/tool_eraser.svgz
new file mode 100644
index 0000000..8b5c40e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_eraser.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_eraser_selection.svgz b/IconThemes/mono/scalable/actions/tool_eraser_selection.svgz
new file mode 100644
index 0000000..1d41c77
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_eraser_selection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_expert.svgz b/IconThemes/mono/scalable/actions/tool_expert.svgz
new file mode 100644
index 0000000..4a41a96
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_expert.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_flood_fill.svgz b/IconThemes/mono/scalable/actions/tool_flood_fill.svgz
new file mode 100644
index 0000000..0a32517
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_flood_fill.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_free_form_selection.svgz b/IconThemes/mono/scalable/actions/tool_free_form_selection.svgz
new file mode 100644
index 0000000..a042d44
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_free_form_selection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_freehand.svgz b/IconThemes/mono/scalable/actions/tool_freehand.svgz
new file mode 100644
index 0000000..8328db2
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_freehand.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_line.svgz b/IconThemes/mono/scalable/actions/tool_line.svgz
new file mode 100644
index 0000000..0cbd74f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_line.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_logwindow.svgz b/IconThemes/mono/scalable/actions/tool_logwindow.svgz
new file mode 100644
index 0000000..4437baa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_logwindow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_normal.svgz b/IconThemes/mono/scalable/actions/tool_normal.svgz
new file mode 100644
index 0000000..44bcb67
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_normal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_offline_mode_off.svgz b/IconThemes/mono/scalable/actions/tool_offline_mode_off.svgz
new file mode 100644
index 0000000..b7fe8fd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_offline_mode_off.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_offline_mode_on.svgz b/IconThemes/mono/scalable/actions/tool_offline_mode_on.svgz
new file mode 100644
index 0000000..4e53514
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_offline_mode_on.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_pan.svgz b/IconThemes/mono/scalable/actions/tool_pan.svgz
new file mode 100644
index 0000000..2d8b683
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_pan.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_paste.svgz b/IconThemes/mono/scalable/actions/tool_paste.svgz
new file mode 100644
index 0000000..8479220
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_paste.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_pause.svgz b/IconThemes/mono/scalable/actions/tool_pause.svgz
new file mode 100644
index 0000000..3802db3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_pause.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_pen.svgz b/IconThemes/mono/scalable/actions/tool_pen.svgz
new file mode 100644
index 0000000..d181e4f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_pen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_picker_selection.svgz b/IconThemes/mono/scalable/actions/tool_picker_selection.svgz
new file mode 100644
index 0000000..7018792
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_picker_selection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_polygon.svgz b/IconThemes/mono/scalable/actions/tool_polygon.svgz
new file mode 100644
index 0000000..419f255
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_polygon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_polygonal_selection.svgz b/IconThemes/mono/scalable/actions/tool_polygonal_selection.svgz
new file mode 100644
index 0000000..fdbc9d0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_polygonal_selection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_polyline.svgz b/IconThemes/mono/scalable/actions/tool_polyline.svgz
new file mode 100644
index 0000000..dc4a12a
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_polyline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_preferences.svgz b/IconThemes/mono/scalable/actions/tool_preferences.svgz
new file mode 100644
index 0000000..c83c88d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_preferences.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_queue.svgz b/IconThemes/mono/scalable/actions/tool_queue.svgz
new file mode 100644
index 0000000..fcb886c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_queue.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_rect_selection.svgz b/IconThemes/mono/scalable/actions/tool_rect_selection.svgz
new file mode 100644
index 0000000..9667c14
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_rect_selection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_rectangle.svgz b/IconThemes/mono/scalable/actions/tool_rectangle.svgz
new file mode 100644
index 0000000..6f944b3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_rectangle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_restart.svgz b/IconThemes/mono/scalable/actions/tool_restart.svgz
new file mode 100644
index 0000000..fd3819e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_restart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_resume.svgz b/IconThemes/mono/scalable/actions/tool_resume.svgz
new file mode 100644
index 0000000..ee289fa
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_resume.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_rounded_rectangle.svgz b/IconThemes/mono/scalable/actions/tool_rounded_rectangle.svgz
new file mode 100644
index 0000000..f3bea7b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_rounded_rectangle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_shutdown.svgz b/IconThemes/mono/scalable/actions/tool_shutdown.svgz
new file mode 100644
index 0000000..8217835
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_shutdown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_spraycan.svgz b/IconThemes/mono/scalable/actions/tool_spraycan.svgz
new file mode 100644
index 0000000..3f418a6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_spraycan.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_star.svgz b/IconThemes/mono/scalable/actions/tool_star.svgz
new file mode 100644
index 0000000..07f2627
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_star.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_text.svgz b/IconThemes/mono/scalable/actions/tool_text.svgz
new file mode 100644
index 0000000..bca793d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_timer.svgz b/IconThemes/mono/scalable/actions/tool_timer.svgz
new file mode 100644
index 0000000..c614315
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_timer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_uselastdir.svgz b/IconThemes/mono/scalable/actions/tool_uselastdir.svgz
new file mode 100644
index 0000000..6e7aa34
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_uselastdir.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tool_wizard_selection.svgz b/IconThemes/mono/scalable/actions/tool_wizard_selection.svgz
new file mode 100644
index 0000000..9fc2db1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tool_wizard_selection.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tooltip.svgz b/IconThemes/mono/scalable/actions/tooltip.svgz
new file mode 100644
index 0000000..2cb910e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tooltip.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/top.svgz b/IconThemes/mono/scalable/actions/top.svgz
new file mode 100644
index 0000000..97ad012
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/top.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/transaction_export.svgz b/IconThemes/mono/scalable/actions/transaction_export.svgz
new file mode 100644
index 0000000..555af57
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/transaction_export.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/transaction_find.svgz b/IconThemes/mono/scalable/actions/transaction_find.svgz
new file mode 100644
index 0000000..ab58119
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/transaction_find.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/transaction_import.svgz b/IconThemes/mono/scalable/actions/transaction_import.svgz
new file mode 100644
index 0000000..33ac79e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/transaction_import.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/transform.svgz b/IconThemes/mono/scalable/actions/transform.svgz
new file mode 100644
index 0000000..bee96c8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/transform.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/translate.svgz b/IconThemes/mono/scalable/actions/translate.svgz
new file mode 100644
index 0000000..c5c6199
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/translate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/translation.svgz b/IconThemes/mono/scalable/actions/translation.svgz
new file mode 100644
index 0000000..df37994
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/translation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/transsearch.svgz b/IconThemes/mono/scalable/actions/transsearch.svgz
new file mode 100644
index 0000000..964fec8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/transsearch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tree_arrange.svgz b/IconThemes/mono/scalable/actions/tree_arrange.svgz
new file mode 100644
index 0000000..c18722d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tree_arrange.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/triangle.svgz b/IconThemes/mono/scalable/actions/triangle.svgz
new file mode 100644
index 0000000..47407c6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/triangle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/tux.svgz b/IconThemes/mono/scalable/actions/tux.svgz
new file mode 100644
index 0000000..961bb0e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/tux.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/under.svgz b/IconThemes/mono/scalable/actions/under.svgz
new file mode 100644
index 0000000..28c9348
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/under.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/underline.svgz b/IconThemes/mono/scalable/actions/underline.svgz
new file mode 100644
index 0000000..2639691
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/underline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/undo.svgz b/IconThemes/mono/scalable/actions/undo.svgz
new file mode 100644
index 0000000..d0b3549
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/undo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ungroup.svgz b/IconThemes/mono/scalable/actions/ungroup.svgz
new file mode 100644
index 0000000..f5f7426
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ungroup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/ungroup_stencils.svgz b/IconThemes/mono/scalable/actions/ungroup_stencils.svgz
new file mode 100644
index 0000000..03b9efc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/ungroup_stencils.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/unindent.svgz b/IconThemes/mono/scalable/actions/unindent.svgz
new file mode 100644
index 0000000..5ab0e43
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/unindent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/unlinked.svgz b/IconThemes/mono/scalable/actions/unlinked.svgz
new file mode 100644
index 0000000..2cbb3d0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/unlinked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/unlock.svgz b/IconThemes/mono/scalable/actions/unlock.svgz
new file mode 100644
index 0000000..edee3d8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/unlock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/unlocked.svgz b/IconThemes/mono/scalable/actions/unlocked.svgz
new file mode 100644
index 0000000..a2ae8f4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/unlocked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/unmarkasblank.svgz b/IconThemes/mono/scalable/actions/unmarkasblank.svgz
new file mode 100644
index 0000000..c9c730f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/unmarkasblank.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/unsortedList.svgz b/IconThemes/mono/scalable/actions/unsortedList.svgz
new file mode 100644
index 0000000..1ad5bcd
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/unsortedList.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/up.svgz b/IconThemes/mono/scalable/actions/up.svgz
new file mode 100644
index 0000000..97157c6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/up.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/urlrequest.svgz b/IconThemes/mono/scalable/actions/urlrequest.svgz
new file mode 100644
index 0000000..c4bf013
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/urlrequest.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/validators.svgz b/IconThemes/mono/scalable/actions/validators.svgz
new file mode 100644
index 0000000..d922783
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/validators.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vcs_add.svgz b/IconThemes/mono/scalable/actions/vcs_add.svgz
new file mode 100644
index 0000000..8741f9e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vcs_add.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vcs_commit.svgz b/IconThemes/mono/scalable/actions/vcs_commit.svgz
new file mode 100644
index 0000000..1c16442
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vcs_commit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vcs_diff.svgz b/IconThemes/mono/scalable/actions/vcs_diff.svgz
new file mode 100644
index 0000000..4ad5f7c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vcs_diff.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vcs_remove.svgz b/IconThemes/mono/scalable/actions/vcs_remove.svgz
new file mode 100644
index 0000000..e583ba8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vcs_remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vcs_status.svgz b/IconThemes/mono/scalable/actions/vcs_status.svgz
new file mode 100644
index 0000000..373369b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vcs_status.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vcs_update.svgz b/IconThemes/mono/scalable/actions/vcs_update.svgz
new file mode 100644
index 0000000..e92d5b8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vcs_update.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vector.svgz b/IconThemes/mono/scalable/actions/vector.svgz
new file mode 100644
index 0000000..8158ab7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vector.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vectordifference.svgz b/IconThemes/mono/scalable/actions/vectordifference.svgz
new file mode 100644
index 0000000..59ec3f0
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vectordifference.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vectorsum.svgz b/IconThemes/mono/scalable/actions/vectorsum.svgz
new file mode 100644
index 0000000..6c32799
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vectorsum.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/vertical_text.svgz b/IconThemes/mono/scalable/actions/vertical_text.svgz
new file mode 100644
index 0000000..a1c4778
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/vertical_text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_bottom.svgz b/IconThemes/mono/scalable/actions/view_bottom.svgz
new file mode 100644
index 0000000..d0a96c8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_bottom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_choose.svgz b/IconThemes/mono/scalable/actions/view_choose.svgz
new file mode 100644
index 0000000..f3aa14d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_choose.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_detailed.svgz b/IconThemes/mono/scalable/actions/view_detailed.svgz
new file mode 100644
index 0000000..fd56a90
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_detailed.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_grid.svgz b/IconThemes/mono/scalable/actions/view_grid.svgz
new file mode 100644
index 0000000..ad5c0b8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_grid.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_guides.svgz b/IconThemes/mono/scalable/actions/view_guides.svgz
new file mode 100644
index 0000000..2e84d2b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_guides.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_icon.svgz b/IconThemes/mono/scalable/actions/view_icon.svgz
new file mode 100644
index 0000000..0a25f86
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_icon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_left_right.svgz b/IconThemes/mono/scalable/actions/view_left_right.svgz
new file mode 100644
index 0000000..72c875f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_left_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_margins.svgz b/IconThemes/mono/scalable/actions/view_margins.svgz
new file mode 100644
index 0000000..82aead4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_margins.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_multicolumn.svgz b/IconThemes/mono/scalable/actions/view_multicolumn.svgz
new file mode 100644
index 0000000..c38c125
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_multicolumn.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_orientation.svgz b/IconThemes/mono/scalable/actions/view_orientation.svgz
new file mode 100644
index 0000000..cd5448e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_orientation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_pageborder.svgz b/IconThemes/mono/scalable/actions/view_pageborder.svgz
new file mode 100644
index 0000000..007d326
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_pageborder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_remove.svgz b/IconThemes/mono/scalable/actions/view_remove.svgz
new file mode 100644
index 0000000..3eb568c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_remove.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_right.svgz b/IconThemes/mono/scalable/actions/view_right.svgz
new file mode 100644
index 0000000..aa9ec88
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_right.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_ruler.svgz b/IconThemes/mono/scalable/actions/view_ruler.svgz
new file mode 100644
index 0000000..ee1e080
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_ruler.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_sidetree.svgz b/IconThemes/mono/scalable/actions/view_sidetree.svgz
new file mode 100644
index 0000000..e0ab190
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_sidetree.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_split.svgz b/IconThemes/mono/scalable/actions/view_split.svgz
new file mode 100644
index 0000000..91df787
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_split.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_text.svgz b/IconThemes/mono/scalable/actions/view_text.svgz
new file mode 100644
index 0000000..62aa2bc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_top_bottom.svgz b/IconThemes/mono/scalable/actions/view_top_bottom.svgz
new file mode 100644
index 0000000..7b6880c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_top_bottom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/view_tree.svgz b/IconThemes/mono/scalable/actions/view_tree.svgz
new file mode 100644
index 0000000..1d538e9
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/view_tree.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag+.svgz b/IconThemes/mono/scalable/actions/viewmag+.svgz
new file mode 100644
index 0000000..f534bd7
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag+.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag-.svgz b/IconThemes/mono/scalable/actions/viewmag-.svgz
new file mode 100644
index 0000000..b86ba97
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag-.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag.svgz b/IconThemes/mono/scalable/actions/viewmag.svgz
new file mode 100644
index 0000000..a5b9f2e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag1.svgz b/IconThemes/mono/scalable/actions/viewmag1.svgz
new file mode 100644
index 0000000..8ccb061
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_bis+.svgz b/IconThemes/mono/scalable/actions/viewmag_bis+.svgz
new file mode 100644
index 0000000..b3b86e1
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_bis+.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_bis-.svgz b/IconThemes/mono/scalable/actions/viewmag_bis-.svgz
new file mode 100644
index 0000000..836bb5d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_bis-.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_enlarge.svgz b/IconThemes/mono/scalable/actions/viewmag_enlarge.svgz
new file mode 100644
index 0000000..54e8219
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_enlarge.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_factor.svgz b/IconThemes/mono/scalable/actions/viewmag_factor.svgz
new file mode 100644
index 0000000..b232c20
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_factor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_full.svgz b/IconThemes/mono/scalable/actions/viewmag_full.svgz
new file mode 100644
index 0000000..96e9349
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_full.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_h.svgz b/IconThemes/mono/scalable/actions/viewmag_h.svgz
new file mode 100644
index 0000000..d722d71
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_h.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_lock.svgz b/IconThemes/mono/scalable/actions/viewmag_lock.svgz
new file mode 100644
index 0000000..fec515f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_lock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_no.svgz b/IconThemes/mono/scalable/actions/viewmag_no.svgz
new file mode 100644
index 0000000..123b335
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_no.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_shrink.svgz b/IconThemes/mono/scalable/actions/viewmag_shrink.svgz
new file mode 100644
index 0000000..ef565cf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_shrink.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmag_w.svgz b/IconThemes/mono/scalable/actions/viewmag_w.svgz
new file mode 100644
index 0000000..919cc9f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmag_w.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/viewmagfit.svgz b/IconThemes/mono/scalable/actions/viewmagfit.svgz
new file mode 100644
index 0000000..425d91b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/viewmagfit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/visible.svgz b/IconThemes/mono/scalable/actions/visible.svgz
new file mode 100644
index 0000000..a2a1852
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/visible.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/visualizations.svgz b/IconThemes/mono/scalable/actions/visualizations.svgz
new file mode 100644
index 0000000..37632fc
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/visualizations.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/voicecall.svgz b/IconThemes/mono/scalable/actions/voicecall.svgz
new file mode 100644
index 0000000..53e64ad
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/voicecall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/volume.svgz b/IconThemes/mono/scalable/actions/volume.svgz
new file mode 100644
index 0000000..3df24a3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/volume.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/w.svgz b/IconThemes/mono/scalable/actions/w.svgz
new file mode 100644
index 0000000..4364f7e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/w.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/wallet_closed.svgz b/IconThemes/mono/scalable/actions/wallet_closed.svgz
new file mode 100644
index 0000000..eab47b3
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/wallet_closed.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/wallet_open.svgz b/IconThemes/mono/scalable/actions/wallet_open.svgz
new file mode 100644
index 0000000..9523cc6
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/wallet_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/warning.svgz b/IconThemes/mono/scalable/actions/warning.svgz
new file mode 100644
index 0000000..c1f9cc8
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/warning.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/webarchiver.svgz b/IconThemes/mono/scalable/actions/webarchiver.svgz
new file mode 100644
index 0000000..c8131b4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/webarchiver.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/webcamreceive.svgz b/IconThemes/mono/scalable/actions/webcamreceive.svgz
new file mode 100644
index 0000000..a12e314
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/webcamreceive.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/webcamsend.svgz b/IconThemes/mono/scalable/actions/webcamsend.svgz
new file mode 100644
index 0000000..8c7b818
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/webcamsend.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/webexport.svgz b/IconThemes/mono/scalable/actions/webexport.svgz
new file mode 100644
index 0000000..ac34e94
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/webexport.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/webpres.svgz b/IconThemes/mono/scalable/actions/webpres.svgz
new file mode 100644
index 0000000..bb34701
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/webpres.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/whatsnext.svgz b/IconThemes/mono/scalable/actions/whatsnext.svgz
new file mode 100644
index 0000000..e2f537e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/whatsnext.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/widgetstack.svgz b/IconThemes/mono/scalable/actions/widgetstack.svgz
new file mode 100644
index 0000000..beaa890
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/widgetstack.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/wiki.svgz b/IconThemes/mono/scalable/actions/wiki.svgz
new file mode 100644
index 0000000..4364f7e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/wiki.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/window.svgz b/IconThemes/mono/scalable/actions/window.svgz
new file mode 100644
index 0000000..e236adb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/window.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/window_duplicate.svgz b/IconThemes/mono/scalable/actions/window_duplicate.svgz
new file mode 100644
index 0000000..15cb8d4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/window_duplicate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/window_fullscreen.svgz b/IconThemes/mono/scalable/actions/window_fullscreen.svgz
new file mode 100644
index 0000000..4b2bfe4
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/window_fullscreen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/window_new.svgz b/IconThemes/mono/scalable/actions/window_new.svgz
new file mode 100644
index 0000000..fae7e3b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/window_new.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/window_nofullscreen.svgz b/IconThemes/mono/scalable/actions/window_nofullscreen.svgz
new file mode 100644
index 0000000..3248e9c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/window_nofullscreen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/window_suppressed.svgz b/IconThemes/mono/scalable/actions/window_suppressed.svgz
new file mode 100644
index 0000000..3acea74
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/window_suppressed.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/wired.svgz b/IconThemes/mono/scalable/actions/wired.svgz
new file mode 100644
index 0000000..7c4a1a5
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/wired.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/wireless.svgz b/IconThemes/mono/scalable/actions/wireless.svgz
new file mode 100644
index 0000000..e8d9e25
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/wireless.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/wizard.svgz b/IconThemes/mono/scalable/actions/wizard.svgz
new file mode 100644
index 0000000..14d3e4e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/wizard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xdays.svgz b/IconThemes/mono/scalable/actions/xdays.svgz
new file mode 100644
index 0000000..6ffb249
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xdays.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_break.svgz b/IconThemes/mono/scalable/actions/xsldbg_break.svgz
new file mode 100644
index 0000000..69e527f
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_break.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_data.svgz b/IconThemes/mono/scalable/actions/xsldbg_data.svgz
new file mode 100644
index 0000000..2184251
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_data.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_delete.svgz b/IconThemes/mono/scalable/actions/xsldbg_delete.svgz
new file mode 100644
index 0000000..84f4b7e
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_delete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_enable.svgz b/IconThemes/mono/scalable/actions/xsldbg_enable.svgz
new file mode 100644
index 0000000..c48d822
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_enable.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_output.svgz b/IconThemes/mono/scalable/actions/xsldbg_output.svgz
new file mode 100644
index 0000000..2644b28
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_output.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_refresh.svgz b/IconThemes/mono/scalable/actions/xsldbg_refresh.svgz
new file mode 100644
index 0000000..81e5456
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_refresh.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_source.svgz b/IconThemes/mono/scalable/actions/xsldbg_source.svgz
new file mode 100644
index 0000000..c1338bb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_source.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_stepdown.svgz b/IconThemes/mono/scalable/actions/xsldbg_stepdown.svgz
new file mode 100644
index 0000000..4c6120c
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_stepdown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/xsldbg_stepup.svgz b/IconThemes/mono/scalable/actions/xsldbg_stepup.svgz
new file mode 100644
index 0000000..b7ae123
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/xsldbg_stepup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/yahoo_away.svgz b/IconThemes/mono/scalable/actions/yahoo_away.svgz
new file mode 100644
index 0000000..d67e3cb
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/yahoo_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/yahoo_mobile.svgz b/IconThemes/mono/scalable/actions/yahoo_mobile.svgz
new file mode 100644
index 0000000..f668d92
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/yahoo_mobile.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/yahoo_protocol.svgz b/IconThemes/mono/scalable/actions/yahoo_protocol.svgz
new file mode 100644
index 0000000..e277a08
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/yahoo_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/yellow_ball.svgz b/IconThemes/mono/scalable/actions/yellow_ball.svgz
new file mode 100644
index 0000000..d1e4cdf
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/yellow_ball.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/yellowinfo.svgz b/IconThemes/mono/scalable/actions/yellowinfo.svgz
new file mode 100644
index 0000000..da4670d
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/yellowinfo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/yesno.svgz b/IconThemes/mono/scalable/actions/yesno.svgz
new file mode 100644
index 0000000..ff9d89b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/yesno.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/zoom_disabled.svgz b/IconThemes/mono/scalable/actions/zoom_disabled.svgz
new file mode 100644
index 0000000..bb5ad4b
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/zoom_disabled.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/actions/zoom_enabled.svgz b/IconThemes/mono/scalable/actions/zoom_enabled.svgz
new file mode 100644
index 0000000..5be2f41
--- /dev/null
+++ b/IconThemes/mono/scalable/actions/zoom_enabled.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/001_star_butterfly.svgz b/IconThemes/mono/scalable/apps/001_star_butterfly.svgz
new file mode 100644
index 0000000..3c74b9f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/001_star_butterfly.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/002_text_document.svgz b/IconThemes/mono/scalable/apps/002_text_document.svgz
new file mode 100644
index 0000000..e06aebd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/002_text_document.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/005_spreadsheet_document.svgz b/IconThemes/mono/scalable/apps/005_spreadsheet_document.svgz
new file mode 100644
index 0000000..f0309e9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/005_spreadsheet_document.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/006_drawing_document.svgz b/IconThemes/mono/scalable/apps/006_drawing_document.svgz
new file mode 100644
index 0000000..9138616
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/006_drawing_document.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/008_presentation_document.svgz b/IconThemes/mono/scalable/apps/008_presentation_document.svgz
new file mode 100644
index 0000000..36e687a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/008_presentation_document.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/009_presentation_document.svgz b/IconThemes/mono/scalable/apps/009_presentation_document.svgz
new file mode 100644
index 0000000..a6bcead
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/009_presentation_document.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/010_presentation_compressed.svgz b/IconThemes/mono/scalable/apps/010_presentation_compressed.svgz
new file mode 100644
index 0000000..1339df3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/010_presentation_compressed.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/012_html_document.svgz b/IconThemes/mono/scalable/apps/012_html_document.svgz
new file mode 100644
index 0000000..74c1420
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/012_html_document.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/015_math_document.svgz b/IconThemes/mono/scalable/apps/015_math_document.svgz
new file mode 100644
index 0000000..df2f843
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/015_math_document.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/016_template.svgz b/IconThemes/mono/scalable/apps/016_template.svgz
new file mode 100644
index 0000000..920caf1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/016_template.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/500_setup.svgz b/IconThemes/mono/scalable/apps/500_setup.svgz
new file mode 100644
index 0000000..d527c18
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/500_setup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/501_printeradmin.svgz b/IconThemes/mono/scalable/apps/501_printeradmin.svgz
new file mode 100644
index 0000000..5102bd1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/501_printeradmin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/CD-Rom.svgz b/IconThemes/mono/scalable/apps/CD-Rom.svgz
new file mode 100644
index 0000000..f6a1fbc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/CD-Rom.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/FaxRecieving.svgz b/IconThemes/mono/scalable/apps/FaxRecieving.svgz
new file mode 100644
index 0000000..3f86ba3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/FaxRecieving.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/LabPlot.svgz b/IconThemes/mono/scalable/apps/LabPlot.svgz
new file mode 100644
index 0000000..1e760e3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/LabPlot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/YaST.svgz b/IconThemes/mono/scalable/apps/YaST.svgz
new file mode 100644
index 0000000..f7de9db
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/YaST.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/Ym.svgz b/IconThemes/mono/scalable/apps/Ym.svgz
new file mode 100644
index 0000000..e2ea51a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/Ym.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/abakus.svgz b/IconThemes/mono/scalable/apps/abakus.svgz
new file mode 100644
index 0000000..9f6825d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/abakus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/abiword.svgz b/IconThemes/mono/scalable/apps/abiword.svgz
new file mode 100644
index 0000000..b0bad24
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/abiword.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/access.svgz b/IconThemes/mono/scalable/apps/access.svgz
new file mode 100644
index 0000000..e973967
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/access.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/accessibility_section.svgz b/IconThemes/mono/scalable/apps/accessibility_section.svgz
new file mode 100644
index 0000000..42cff7c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/accessibility_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/acroread.svgz b/IconThemes/mono/scalable/apps/acroread.svgz
new file mode 100644
index 0000000..a1d39bb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/acroread.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/addressbook.svgz b/IconThemes/mono/scalable/apps/addressbook.svgz
new file mode 100644
index 0000000..0c3e534
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/addressbook.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/agent.svgz b/IconThemes/mono/scalable/apps/agent.svgz
new file mode 100644
index 0000000..622ace6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/agent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/aim.svgz b/IconThemes/mono/scalable/apps/aim.svgz
new file mode 100644
index 0000000..f1729c3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/aim.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/aim_protocol.svgz b/IconThemes/mono/scalable/apps/aim_protocol.svgz
new file mode 100644
index 0000000..bea6507
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/aim_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/akregator.svgz b/IconThemes/mono/scalable/apps/akregator.svgz
new file mode 100644
index 0000000..2845e2a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/akregator.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/akregator_empty.svgz b/IconThemes/mono/scalable/apps/akregator_empty.svgz
new file mode 100644
index 0000000..0f8e4d5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/akregator_empty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/aktion.svgz b/IconThemes/mono/scalable/apps/aktion.svgz
new file mode 100644
index 0000000..548d030
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/aktion.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/alevt.svgz b/IconThemes/mono/scalable/apps/alevt.svgz
new file mode 100644
index 0000000..827837f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/alevt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/amarok.svgz b/IconThemes/mono/scalable/apps/amarok.svgz
new file mode 100644
index 0000000..f889bca
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/amarok.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/amor.svgz b/IconThemes/mono/scalable/apps/amor.svgz
new file mode 100644
index 0000000..d058a6d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/amor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/antivirus.svgz b/IconThemes/mono/scalable/apps/antivirus.svgz
new file mode 100644
index 0000000..2d4557b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/antivirus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/apollon.svgz b/IconThemes/mono/scalable/apps/apollon.svgz
new file mode 100644
index 0000000..ccd5df6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/apollon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/applixware.svgz b/IconThemes/mono/scalable/apps/applixware.svgz
new file mode 100644
index 0000000..6970636
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/applixware.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/apport.svgz b/IconThemes/mono/scalable/apps/apport.svgz
new file mode 100644
index 0000000..c1f9cc8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/apport.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ark.svgz b/IconThemes/mono/scalable/apps/ark.svgz
new file mode 100644
index 0000000..a148891
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ark.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/arts.svgz b/IconThemes/mono/scalable/apps/arts.svgz
new file mode 100644
index 0000000..df2185f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/arts.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/artsbuilder.svgz b/IconThemes/mono/scalable/apps/artsbuilder.svgz
new file mode 100644
index 0000000..a1451b0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/artsbuilder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/artscontrol.svgz b/IconThemes/mono/scalable/apps/artscontrol.svgz
new file mode 100644
index 0000000..20d4285
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/artscontrol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/assistant.svgz b/IconThemes/mono/scalable/apps/assistant.svgz
new file mode 100644
index 0000000..28687e9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/assistant.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/atlantik.svgz b/IconThemes/mono/scalable/apps/atlantik.svgz
new file mode 100644
index 0000000..5ab3bfc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/atlantik.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/atlantikdesigner.svgz b/IconThemes/mono/scalable/apps/atlantikdesigner.svgz
new file mode 100644
index 0000000..e8da155
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/atlantikdesigner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/audacity.svgz b/IconThemes/mono/scalable/apps/audacity.svgz
new file mode 100644
index 0000000..a836a2f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/audacity.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/background.svgz b/IconThemes/mono/scalable/apps/background.svgz
new file mode 100644
index 0000000..5793d98
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/background.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/basket.svgz b/IconThemes/mono/scalable/apps/basket.svgz
new file mode 100644
index 0000000..4ef0b13
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/basket.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/bell.svgz b/IconThemes/mono/scalable/apps/bell.svgz
new file mode 100644
index 0000000..f6023e1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/bell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/blender.svgz b/IconThemes/mono/scalable/apps/blender.svgz
new file mode 100644
index 0000000..785e17c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/blender.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/blinken.svgz b/IconThemes/mono/scalable/apps/blinken.svgz
new file mode 100644
index 0000000..72f457e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/blinken.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/bluefish.svgz b/IconThemes/mono/scalable/apps/bluefish.svgz
new file mode 100644
index 0000000..2f7f1a0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/bluefish.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/bookcase.svgz b/IconThemes/mono/scalable/apps/bookcase.svgz
new file mode 100644
index 0000000..f9285c5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/bookcase.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/browser.svgz b/IconThemes/mono/scalable/apps/browser.svgz
new file mode 100644
index 0000000..220f204
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/browser.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/bug.svgz b/IconThemes/mono/scalable/apps/bug.svgz
new file mode 100644
index 0000000..9422d8d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/bug.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/bzflag.svgz b/IconThemes/mono/scalable/apps/bzflag.svgz
new file mode 100644
index 0000000..36efd87
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/bzflag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/cache.svgz b/IconThemes/mono/scalable/apps/cache.svgz
new file mode 100644
index 0000000..a042954
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/cache.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/calc.svgz b/IconThemes/mono/scalable/apps/calc.svgz
new file mode 100644
index 0000000..6e3927a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/calc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/camera.svgz b/IconThemes/mono/scalable/apps/camera.svgz
new file mode 100644
index 0000000..638b9e5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/camera.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/catalogmanager.svgz b/IconThemes/mono/scalable/apps/catalogmanager.svgz
new file mode 100644
index 0000000..dd4e581
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/catalogmanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/categories.svgz b/IconThemes/mono/scalable/apps/categories.svgz
new file mode 100644
index 0000000..926a01d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/categories.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/celestia.svgz b/IconThemes/mono/scalable/apps/celestia.svgz
new file mode 100644
index 0000000..004a221
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/celestia.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/cervisia.svgz b/IconThemes/mono/scalable/apps/cervisia.svgz
new file mode 100644
index 0000000..c0387e4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/cervisia.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/charselect.svgz b/IconThemes/mono/scalable/apps/charselect.svgz
new file mode 100644
index 0000000..1f9e28b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/charselect.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/chat_section.svgz b/IconThemes/mono/scalable/apps/chat_section.svgz
new file mode 100644
index 0000000..197af65
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/chat_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/civworld.svgz b/IconThemes/mono/scalable/apps/civworld.svgz
new file mode 100644
index 0000000..2c3cea6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/civworld.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/clanbomber.svgz b/IconThemes/mono/scalable/apps/clanbomber.svgz
new file mode 100644
index 0000000..5822909
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/clanbomber.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/clock.svgz b/IconThemes/mono/scalable/apps/clock.svgz
new file mode 100644
index 0000000..f25299a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/clock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/codeine.svgz b/IconThemes/mono/scalable/apps/codeine.svgz
new file mode 100644
index 0000000..c704a4f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/codeine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/colorpicker.svgz b/IconThemes/mono/scalable/apps/colorpicker.svgz
new file mode 100644
index 0000000..8ba5723
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/colorpicker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/colors.svgz b/IconThemes/mono/scalable/apps/colors.svgz
new file mode 100644
index 0000000..89a4245
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/colors.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/computer.svgz b/IconThemes/mono/scalable/apps/computer.svgz
new file mode 100644
index 0000000..de8a624
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/computer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/cookie.svgz b/IconThemes/mono/scalable/apps/cookie.svgz
new file mode 100644
index 0000000..413b39f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/cookie.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/core.svgz b/IconThemes/mono/scalable/apps/core.svgz
new file mode 100644
index 0000000..10483de
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/core.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/cpufreq_applet.svgz b/IconThemes/mono/scalable/apps/cpufreq_applet.svgz
new file mode 100644
index 0000000..87d998d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/cpufreq_applet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/daemon.svgz b/IconThemes/mono/scalable/apps/daemon.svgz
new file mode 100644
index 0000000..75b07d1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/daemon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/daemons.svgz b/IconThemes/mono/scalable/apps/daemons.svgz
new file mode 100644
index 0000000..75b07d1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/daemons.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/date.svgz b/IconThemes/mono/scalable/apps/date.svgz
new file mode 100644
index 0000000..aa98e8b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/date.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/dcgui-qt.svgz b/IconThemes/mono/scalable/apps/dcgui-qt.svgz
new file mode 100644
index 0000000..f3c61a0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/dcgui-qt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/default-applications-capplet.svgz b/IconThemes/mono/scalable/apps/default-applications-capplet.svgz
new file mode 100644
index 0000000..98fc8d4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/default-applications-capplet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/designer.svgz b/IconThemes/mono/scalable/apps/designer.svgz
new file mode 100644
index 0000000..3299efe
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/designer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/dia.svgz b/IconThemes/mono/scalable/apps/dia.svgz
new file mode 100644
index 0000000..53b6d41
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/dia.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/dia_gnome_icon.svgz b/IconThemes/mono/scalable/apps/dia_gnome_icon.svgz
new file mode 100644
index 0000000..f0bf207
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/dia_gnome_icon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/digikam.svgz b/IconThemes/mono/scalable/apps/digikam.svgz
new file mode 100644
index 0000000..47a08b3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/digikam.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/digikamcameraclient.svgz b/IconThemes/mono/scalable/apps/digikamcameraclient.svgz
new file mode 100644
index 0000000..7b419ef
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/digikamcameraclient.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/digikamimageplugins.svgz b/IconThemes/mono/scalable/apps/digikamimageplugins.svgz
new file mode 100644
index 0000000..a6c805b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/digikamimageplugins.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/display.svgz b/IconThemes/mono/scalable/apps/display.svgz
new file mode 100644
index 0000000..106920f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/display.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/displayconfig.svgz b/IconThemes/mono/scalable/apps/displayconfig.svgz
new file mode 100644
index 0000000..5db5666
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/displayconfig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/dlgedit.svgz b/IconThemes/mono/scalable/apps/dlgedit.svgz
new file mode 100644
index 0000000..ed03633
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/dlgedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/dopewars-pill.svgz b/IconThemes/mono/scalable/apps/dopewars-pill.svgz
new file mode 100644
index 0000000..462a2ff
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/dopewars-pill.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/download_manager.svgz b/IconThemes/mono/scalable/apps/download_manager.svgz
new file mode 100644
index 0000000..4439b16
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/download_manager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/dsl.svgz b/IconThemes/mono/scalable/apps/dsl.svgz
new file mode 100644
index 0000000..4183644
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/dsl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/eclipse.svgz b/IconThemes/mono/scalable/apps/eclipse.svgz
new file mode 100644
index 0000000..69ffb9c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/eclipse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/edu_languages.svgz b/IconThemes/mono/scalable/apps/edu_languages.svgz
new file mode 100644
index 0000000..0831581
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/edu_languages.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/edu_mathematics.svgz b/IconThemes/mono/scalable/apps/edu_mathematics.svgz
new file mode 100644
index 0000000..006011b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/edu_mathematics.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/edu_miscellaneous.svgz b/IconThemes/mono/scalable/apps/edu_miscellaneous.svgz
new file mode 100644
index 0000000..ac9e3dc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/edu_miscellaneous.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/edu_science.svgz b/IconThemes/mono/scalable/apps/edu_science.svgz
new file mode 100644
index 0000000..03aa1e7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/edu_science.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/emacs.svgz b/IconThemes/mono/scalable/apps/emacs.svgz
new file mode 100644
index 0000000..48ff683
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/emacs.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/email.svgz b/IconThemes/mono/scalable/apps/email.svgz
new file mode 100644
index 0000000..0fcc3ae
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/email.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/energy.svgz b/IconThemes/mono/scalable/apps/energy.svgz
new file mode 100644
index 0000000..5aa3cea
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/energy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/energy_star.svgz b/IconThemes/mono/scalable/apps/energy_star.svgz
new file mode 100644
index 0000000..2881c40
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/energy_star.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/enhanced_browsing.svgz b/IconThemes/mono/scalable/apps/enhanced_browsing.svgz
new file mode 100644
index 0000000..961d2f5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/enhanced_browsing.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/enigma.svgz b/IconThemes/mono/scalable/apps/enigma.svgz
new file mode 100644
index 0000000..a20f166
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/enigma.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/eog.svgz b/IconThemes/mono/scalable/apps/eog.svgz
new file mode 100644
index 0000000..74f78c7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/eog.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/error.svgz b/IconThemes/mono/scalable/apps/error.svgz
new file mode 100644
index 0000000..faa408c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/error.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ethereal.svgz b/IconThemes/mono/scalable/apps/ethereal.svgz
new file mode 100644
index 0000000..2c4100a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ethereal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/eventwatcher.svgz b/IconThemes/mono/scalable/apps/eventwatcher.svgz
new file mode 100644
index 0000000..78cc48e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/eventwatcher.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/evolution.svgz b/IconThemes/mono/scalable/apps/evolution.svgz
new file mode 100644
index 0000000..b1f0263
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/evolution.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/exec_wine.svgz b/IconThemes/mono/scalable/apps/exec_wine.svgz
new file mode 100644
index 0000000..d3575de
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/exec_wine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/exit.svgz b/IconThemes/mono/scalable/apps/exit.svgz
new file mode 100644
index 0000000..802ed30
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/exit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/falconseye.svgz b/IconThemes/mono/scalable/apps/falconseye.svgz
new file mode 100644
index 0000000..0b2c4e8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/falconseye.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/fax.svgz b/IconThemes/mono/scalable/apps/fax.svgz
new file mode 100644
index 0000000..f60bed9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/fax.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/fifteenpieces.svgz b/IconThemes/mono/scalable/apps/fifteenpieces.svgz
new file mode 100644
index 0000000..bcade2b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/fifteenpieces.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/filelight.svgz b/IconThemes/mono/scalable/apps/filelight.svgz
new file mode 100644
index 0000000..8b99a3c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/filelight.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/fileshare.svgz b/IconThemes/mono/scalable/apps/fileshare.svgz
new file mode 100644
index 0000000..80cee4a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/fileshare.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/filetypes.svgz b/IconThemes/mono/scalable/apps/filetypes.svgz
new file mode 100644
index 0000000..073dc66
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/filetypes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/finances_section.svgz b/IconThemes/mono/scalable/apps/finances_section.svgz
new file mode 100644
index 0000000..11f8571
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/finances_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/firefox.svgz b/IconThemes/mono/scalable/apps/firefox.svgz
new file mode 100644
index 0000000..cb86568
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/firefox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/flashkard.svgz b/IconThemes/mono/scalable/apps/flashkard.svgz
new file mode 100644
index 0000000..c873287
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/flashkard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/fonts.svgz b/IconThemes/mono/scalable/apps/fonts.svgz
new file mode 100644
index 0000000..76d4fcf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/fonts.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/fsview.svgz b/IconThemes/mono/scalable/apps/fsview.svgz
new file mode 100644
index 0000000..cc83502
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/fsview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gabber.svgz b/IconThemes/mono/scalable/apps/gabber.svgz
new file mode 100644
index 0000000..7e7270b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gabber.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gaim.svgz b/IconThemes/mono/scalable/apps/gaim.svgz
new file mode 100644
index 0000000..4b70f52
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gaim.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/galeon.svgz b/IconThemes/mono/scalable/apps/galeon.svgz
new file mode 100644
index 0000000..f40eb3e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/galeon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gfloppy.svgz b/IconThemes/mono/scalable/apps/gfloppy.svgz
new file mode 100644
index 0000000..ef89875
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gfloppy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gimp.svgz b/IconThemes/mono/scalable/apps/gimp.svgz
new file mode 100644
index 0000000..a24e062
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gimp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gkrellm.svgz b/IconThemes/mono/scalable/apps/gkrellm.svgz
new file mode 100644
index 0000000..da67517
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gkrellm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gksu.svgz b/IconThemes/mono/scalable/apps/gksu.svgz
new file mode 100644
index 0000000..d6aaf32
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gksu.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/glade.svgz b/IconThemes/mono/scalable/apps/glade.svgz
new file mode 100644
index 0000000..7da7764
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/glade.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/globe.svgz b/IconThemes/mono/scalable/apps/globe.svgz
new file mode 100644
index 0000000..98ca279
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/globe.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome-about-logo.svgz b/IconThemes/mono/scalable/apps/gnome-about-logo.svgz
new file mode 100644
index 0000000..1c8cfb3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome-about-logo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome-error.svgz b/IconThemes/mono/scalable/apps/gnome-error.svgz
new file mode 100644
index 0000000..8ebe67d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome-error.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome-starthere.svgz b/IconThemes/mono/scalable/apps/gnome-starthere.svgz
new file mode 100644
index 0000000..c891bcd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome-starthere.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome-terminal.svgz b/IconThemes/mono/scalable/apps/gnome-terminal.svgz
new file mode 100644
index 0000000..183d0c2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome-terminal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome-warning.svgz b/IconThemes/mono/scalable/apps/gnome-warning.svgz
new file mode 100644
index 0000000..af11350
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome-warning.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome.svgz b/IconThemes/mono/scalable/apps/gnome.svgz
new file mode 100644
index 0000000..6b7f16d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome2.svgz b/IconThemes/mono/scalable/apps/gnome2.svgz
new file mode 100644
index 0000000..d988e6b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome_apps.svgz b/IconThemes/mono/scalable/apps/gnome_apps.svgz
new file mode 100644
index 0000000..7cb0f94
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome_apps.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome_info.svgz b/IconThemes/mono/scalable/apps/gnome_info.svgz
new file mode 100644
index 0000000..5b58e97
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome_info.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnome_question.svgz b/IconThemes/mono/scalable/apps/gnome_question.svgz
new file mode 100644
index 0000000..f37f83b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnome_question.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnomemeeting.svgz b/IconThemes/mono/scalable/apps/gnomemeeting.svgz
new file mode 100644
index 0000000..2ce8073
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnomemeeting.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnucash.svgz b/IconThemes/mono/scalable/apps/gnucash.svgz
new file mode 100644
index 0000000..339f88a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnucash.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnumeric.svgz b/IconThemes/mono/scalable/apps/gnumeric.svgz
new file mode 100644
index 0000000..1cd6372
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnumeric.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gnutella.svgz b/IconThemes/mono/scalable/apps/gnutella.svgz
new file mode 100644
index 0000000..a097c3e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gnutella.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/go.svgz b/IconThemes/mono/scalable/apps/go.svgz
new file mode 100644
index 0000000..7682c1d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/go.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gpg.svgz b/IconThemes/mono/scalable/apps/gpg.svgz
new file mode 100644
index 0000000..5581091
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gpg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gpgsm.svgz b/IconThemes/mono/scalable/apps/gpgsm.svgz
new file mode 100644
index 0000000..04ff776
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gpgsm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/groupwise_protocol.svgz b/IconThemes/mono/scalable/apps/groupwise_protocol.svgz
new file mode 100644
index 0000000..9c189e2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/groupwise_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gsnes9x-icon.svgz b/IconThemes/mono/scalable/apps/gsnes9x-icon.svgz
new file mode 100644
index 0000000..4c776f7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gsnes9x-icon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gtk_camera.svgz b/IconThemes/mono/scalable/apps/gtk_camera.svgz
new file mode 100644
index 0000000..13b1b12
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gtk_camera.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/guarddog.svgz b/IconThemes/mono/scalable/apps/guarddog.svgz
new file mode 100644
index 0000000..3142c4e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/guarddog.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gv.svgz b/IconThemes/mono/scalable/apps/gv.svgz
new file mode 100644
index 0000000..93876fc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gvdirpart.svgz b/IconThemes/mono/scalable/apps/gvdirpart.svgz
new file mode 100644
index 0000000..d9f75ff
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gvdirpart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gvim.svgz b/IconThemes/mono/scalable/apps/gvim.svgz
new file mode 100644
index 0000000..aa47f28
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gvim.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gwenview.svgz b/IconThemes/mono/scalable/apps/gwenview.svgz
new file mode 100644
index 0000000..496a456
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gwenview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gxmame.svgz b/IconThemes/mono/scalable/apps/gxmame.svgz
new file mode 100644
index 0000000..ba96fbe
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gxmame.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/gxmessage.svgz b/IconThemes/mono/scalable/apps/gxmessage.svgz
new file mode 100644
index 0000000..de33424
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/gxmessage.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/harddrive.svgz b/IconThemes/mono/scalable/apps/harddrive.svgz
new file mode 100644
index 0000000..fb6efab
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/harddrive.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/hardware.svgz b/IconThemes/mono/scalable/apps/hardware.svgz
new file mode 100644
index 0000000..96d0686
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/hardware.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/hardware_info.svgz b/IconThemes/mono/scalable/apps/hardware_info.svgz
new file mode 100644
index 0000000..94626f1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/hardware_info.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/hd.svgz b/IconThemes/mono/scalable/apps/hd.svgz
new file mode 100644
index 0000000..ebd76b0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/hd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/help.svgz b/IconThemes/mono/scalable/apps/help.svgz
new file mode 100644
index 0000000..b100121
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/help.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/help_index.svgz b/IconThemes/mono/scalable/apps/help_index.svgz
new file mode 100644
index 0000000..c48176b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/help_index.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/highlight.svgz b/IconThemes/mono/scalable/apps/highlight.svgz
new file mode 100644
index 0000000..5006766
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/highlight.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/home.svgz b/IconThemes/mono/scalable/apps/home.svgz
new file mode 100644
index 0000000..35548c5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/home.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/hw_unknown.svgz b/IconThemes/mono/scalable/apps/hw_unknown.svgz
new file mode 100644
index 0000000..833e178
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/hw_unknown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/hwinfo.svgz b/IconThemes/mono/scalable/apps/hwinfo.svgz
new file mode 100644
index 0000000..716edf0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/hwinfo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/icewm.svgz b/IconThemes/mono/scalable/apps/icewm.svgz
new file mode 100644
index 0000000..35b8cb5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/icewm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/icons.svgz b/IconThemes/mono/scalable/apps/icons.svgz
new file mode 100644
index 0000000..c0a44ae
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/icons.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/iconthemes.svgz b/IconThemes/mono/scalable/apps/iconthemes.svgz
new file mode 100644
index 0000000..831dbb9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/iconthemes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/icq_protocol.svgz b/IconThemes/mono/scalable/apps/icq_protocol.svgz
new file mode 100644
index 0000000..1c9e046
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/icq_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ieee1394.svgz b/IconThemes/mono/scalable/apps/ieee1394.svgz
new file mode 100644
index 0000000..2e5b099
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ieee1394.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/im-aim.svgz b/IconThemes/mono/scalable/apps/im-aim.svgz
new file mode 100644
index 0000000..7ce7d7b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/im-aim.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/im-icq.svgz b/IconThemes/mono/scalable/apps/im-icq.svgz
new file mode 100644
index 0000000..61bac79
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/im-icq.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/im-jabber.svgz b/IconThemes/mono/scalable/apps/im-jabber.svgz
new file mode 100644
index 0000000..7ecd9a9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/im-jabber.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/im-msn.svgz b/IconThemes/mono/scalable/apps/im-msn.svgz
new file mode 100644
index 0000000..fb866b9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/im-msn.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/im-yahoo.svgz b/IconThemes/mono/scalable/apps/im-yahoo.svgz
new file mode 100644
index 0000000..b4ce78c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/im-yahoo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/imagegallery.svgz b/IconThemes/mono/scalable/apps/imagegallery.svgz
new file mode 100644
index 0000000..4ac282f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/imagegallery.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/inetd.svgz b/IconThemes/mono/scalable/apps/inetd.svgz
new file mode 100644
index 0000000..e4b75ee
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/inetd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/inkscape.svgz b/IconThemes/mono/scalable/apps/inkscape.svgz
new file mode 100644
index 0000000..b1b6964
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/inkscape.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/input_devices_settings.svgz b/IconThemes/mono/scalable/apps/input_devices_settings.svgz
new file mode 100644
index 0000000..7e06ab7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/input_devices_settings.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/irc_protocol.svgz b/IconThemes/mono/scalable/apps/irc_protocol.svgz
new file mode 100644
index 0000000..0f2475e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/irc_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/irkick.svgz b/IconThemes/mono/scalable/apps/irkick.svgz
new file mode 100644
index 0000000..32bdf20
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/irkick.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/isdn-config.svgz b/IconThemes/mono/scalable/apps/isdn-config.svgz
new file mode 100644
index 0000000..e7e7607
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/isdn-config.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/isp-disabled.svgz b/IconThemes/mono/scalable/apps/isp-disabled.svgz
new file mode 100644
index 0000000..7e9cbbe
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/isp-disabled.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/isp.svgz b/IconThemes/mono/scalable/apps/isp.svgz
new file mode 100644
index 0000000..e5e2ba4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/isp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/jabber_protocol.svgz b/IconThemes/mono/scalable/apps/jabber_protocol.svgz
new file mode 100644
index 0000000..336e1bd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/jabber_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/joystick.svgz b/IconThemes/mono/scalable/apps/joystick.svgz
new file mode 100644
index 0000000..32e051c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/joystick.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/juk.svgz b/IconThemes/mono/scalable/apps/juk.svgz
new file mode 100644
index 0000000..a901d3c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/juk.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/k3b.svgz b/IconThemes/mono/scalable/apps/k3b.svgz
new file mode 100644
index 0000000..0a5d33e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/k3b.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kaboodle.svgz b/IconThemes/mono/scalable/apps/kaboodle.svgz
new file mode 100644
index 0000000..62fe337
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kaboodle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kaddressbook.svgz b/IconThemes/mono/scalable/apps/kaddressbook.svgz
new file mode 100644
index 0000000..9518c60
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kaddressbook.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kaffeine-pause.svgz b/IconThemes/mono/scalable/apps/kaffeine-pause.svgz
new file mode 100644
index 0000000..490642d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kaffeine-pause.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kaffeine-play.svgz b/IconThemes/mono/scalable/apps/kaffeine-play.svgz
new file mode 100644
index 0000000..b08b029
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kaffeine-play.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kaffeine-record.svgz b/IconThemes/mono/scalable/apps/kaffeine-record.svgz
new file mode 100644
index 0000000..3c297f0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kaffeine-record.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kaffeine.svgz b/IconThemes/mono/scalable/apps/kaffeine.svgz
new file mode 100644
index 0000000..d90a6b0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kaffeine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kalarm.svgz b/IconThemes/mono/scalable/apps/kalarm.svgz
new file mode 100644
index 0000000..597c5ae
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kalarm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kalzium.svgz b/IconThemes/mono/scalable/apps/kalzium.svgz
new file mode 100644
index 0000000..531e1b2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kalzium.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kamix.svgz b/IconThemes/mono/scalable/apps/kamix.svgz
new file mode 100644
index 0000000..69bc5cd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kamix.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kanagram.svgz b/IconThemes/mono/scalable/apps/kanagram.svgz
new file mode 100644
index 0000000..1462a8c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kanagram.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kappfinder.svgz b/IconThemes/mono/scalable/apps/kappfinder.svgz
new file mode 100644
index 0000000..90c1f27
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kappfinder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/karbon.svgz b/IconThemes/mono/scalable/apps/karbon.svgz
new file mode 100644
index 0000000..31fd912
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/karbon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/karchiver.svgz b/IconThemes/mono/scalable/apps/karchiver.svgz
new file mode 100644
index 0000000..eeee2ed
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/karchiver.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kard.svgz b/IconThemes/mono/scalable/apps/kard.svgz
new file mode 100644
index 0000000..26077f4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/karm.svgz b/IconThemes/mono/scalable/apps/karm.svgz
new file mode 100644
index 0000000..d6318d6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/karm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kasteroids.svgz b/IconThemes/mono/scalable/apps/kasteroids.svgz
new file mode 100644
index 0000000..86ed371
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kasteroids.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kate.svgz b/IconThemes/mono/scalable/apps/kate.svgz
new file mode 100644
index 0000000..3c9830d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kate2.svgz b/IconThemes/mono/scalable/apps/kate2.svgz
new file mode 100644
index 0000000..3c9830d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kate2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/katomic.svgz b/IconThemes/mono/scalable/apps/katomic.svgz
new file mode 100644
index 0000000..686dc0a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/katomic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kaudiocreator.svgz b/IconThemes/mono/scalable/apps/kaudiocreator.svgz
new file mode 100644
index 0000000..c7edbbb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kaudiocreator.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kazaa.svgz b/IconThemes/mono/scalable/apps/kazaa.svgz
new file mode 100644
index 0000000..8b4690a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kazaa.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbabel.svgz b/IconThemes/mono/scalable/apps/kbabel.svgz
new file mode 100644
index 0000000..14aadc6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbabel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbabeldict.svgz b/IconThemes/mono/scalable/apps/kbabeldict.svgz
new file mode 100644
index 0000000..8b64c73
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbabeldict.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbackgammon.svgz b/IconThemes/mono/scalable/apps/kbackgammon.svgz
new file mode 100644
index 0000000..07deca5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbackgammon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbackgammon_engine.svgz b/IconThemes/mono/scalable/apps/kbackgammon_engine.svgz
new file mode 100644
index 0000000..b15d5bc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbackgammon_engine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbatterymonitor.svgz b/IconThemes/mono/scalable/apps/kbatterymonitor.svgz
new file mode 100644
index 0000000..0585591
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbatterymonitor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbattleship.svgz b/IconThemes/mono/scalable/apps/kbattleship.svgz
new file mode 100644
index 0000000..1c4c80c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbattleship.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbear.svgz b/IconThemes/mono/scalable/apps/kbear.svgz
new file mode 100644
index 0000000..d45abcf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbear.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbiff.svgz b/IconThemes/mono/scalable/apps/kbiff.svgz
new file mode 100644
index 0000000..06f7329
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbiff.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbinaryclock.svgz b/IconThemes/mono/scalable/apps/kbinaryclock.svgz
new file mode 100644
index 0000000..93ac2b1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbinaryclock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kblackbox.svgz b/IconThemes/mono/scalable/apps/kblackbox.svgz
new file mode 100644
index 0000000..849c2a1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kblackbox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbluetoothd.svgz b/IconThemes/mono/scalable/apps/kbluetoothd.svgz
new file mode 100644
index 0000000..3f2e843
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbluetoothd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbounce.svgz b/IconThemes/mono/scalable/apps/kbounce.svgz
new file mode 100644
index 0000000..f6435a6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbounce.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbruch.svgz b/IconThemes/mono/scalable/apps/kbruch.svgz
new file mode 100644
index 0000000..39e530d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbruch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbtobexclient.svgz b/IconThemes/mono/scalable/apps/kbtobexclient.svgz
new file mode 100644
index 0000000..3f2e843
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbtobexclient.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbtserialchat.svgz b/IconThemes/mono/scalable/apps/kbtserialchat.svgz
new file mode 100644
index 0000000..3f2e843
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbtserialchat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kbugbuster.svgz b/IconThemes/mono/scalable/apps/kbugbuster.svgz
new file mode 100644
index 0000000..080932d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kbugbuster.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcachegrind.svgz b/IconThemes/mono/scalable/apps/kcachegrind.svgz
new file mode 100644
index 0000000..5e35121
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcachegrind.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcalc.svgz b/IconThemes/mono/scalable/apps/kcalc.svgz
new file mode 100644
index 0000000..3a59ef6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcalc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcdlabel.svgz b/IconThemes/mono/scalable/apps/kcdlabel.svgz
new file mode 100644
index 0000000..119947e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcdlabel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcfgcreator.svgz b/IconThemes/mono/scalable/apps/kcfgcreator.svgz
new file mode 100644
index 0000000..21e55cd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcfgcreator.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcharselect.svgz b/IconThemes/mono/scalable/apps/kcharselect.svgz
new file mode 100644
index 0000000..b6e3994
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcharselect.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kchart.svgz b/IconThemes/mono/scalable/apps/kchart.svgz
new file mode 100644
index 0000000..5edd5b6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kchart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmdevices.svgz b/IconThemes/mono/scalable/apps/kcmdevices.svgz
new file mode 100644
index 0000000..afbdc76
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmdevices.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmdf.svgz b/IconThemes/mono/scalable/apps/kcmdf.svgz
new file mode 100644
index 0000000..3a51473
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmdf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmdrkonqi.svgz b/IconThemes/mono/scalable/apps/kcmdrkonqi.svgz
new file mode 100644
index 0000000..0e4db68
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmdrkonqi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmfontinst.svgz b/IconThemes/mono/scalable/apps/kcmfontinst.svgz
new file mode 100644
index 0000000..13a185c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmfontinst.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmkicker.svgz b/IconThemes/mono/scalable/apps/kcmkicker.svgz
new file mode 100644
index 0000000..74bea13
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmkicker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmkwm.svgz b/IconThemes/mono/scalable/apps/kcmkwm.svgz
new file mode 100644
index 0000000..15cb8d4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmkwm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmmemory.svgz b/IconThemes/mono/scalable/apps/kcmmemory.svgz
new file mode 100644
index 0000000..a6fdad2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmmemory.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmmidi.svgz b/IconThemes/mono/scalable/apps/kcmmidi.svgz
new file mode 100644
index 0000000..b073bfc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmmidi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmopengl.svgz b/IconThemes/mono/scalable/apps/kcmopengl.svgz
new file mode 100644
index 0000000..8008488
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmopengl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmpartitions.svgz b/IconThemes/mono/scalable/apps/kcmpartitions.svgz
new file mode 100644
index 0000000..51e3774
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmpartitions.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmpci.svgz b/IconThemes/mono/scalable/apps/kcmpci.svgz
new file mode 100644
index 0000000..884045e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmpci.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmprocessor.svgz b/IconThemes/mono/scalable/apps/kcmprocessor.svgz
new file mode 100644
index 0000000..87d998d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmprocessor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmsambaconf.svgz b/IconThemes/mono/scalable/apps/kcmsambaconf.svgz
new file mode 100644
index 0000000..add5f77
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmsambaconf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmscsi.svgz b/IconThemes/mono/scalable/apps/kcmscsi.svgz
new file mode 100644
index 0000000..6332aa3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmscsi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmsound.svgz b/IconThemes/mono/scalable/apps/kcmsound.svgz
new file mode 100644
index 0000000..42f98fc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmsound.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmsystem.svgz b/IconThemes/mono/scalable/apps/kcmsystem.svgz
new file mode 100644
index 0000000..43d9da6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmsystem.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcmx.svgz b/IconThemes/mono/scalable/apps/kcmx.svgz
new file mode 100644
index 0000000..34006b3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcmx.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcolorchooser.svgz b/IconThemes/mono/scalable/apps/kcolorchooser.svgz
new file mode 100644
index 0000000..faaadc9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcolorchooser.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcoloredit.svgz b/IconThemes/mono/scalable/apps/kcoloredit.svgz
new file mode 100644
index 0000000..dd55cb8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcoloredit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kconfigure.svgz b/IconThemes/mono/scalable/apps/kconfigure.svgz
new file mode 100644
index 0000000..16e702f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kconfigure.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcontrol.svgz b/IconThemes/mono/scalable/apps/kcontrol.svgz
new file mode 100644
index 0000000..8075b3a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcontrol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcpuload.svgz b/IconThemes/mono/scalable/apps/kcpuload.svgz
new file mode 100644
index 0000000..1c47380
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcpuload.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kcron.svgz b/IconThemes/mono/scalable/apps/kcron.svgz
new file mode 100644
index 0000000..518f528
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kcron.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdat.svgz b/IconThemes/mono/scalable/apps/kdat.svgz
new file mode 100644
index 0000000..4831c68
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdbg.svgz b/IconThemes/mono/scalable/apps/kdbg.svgz
new file mode 100644
index 0000000..927e86c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdbg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdeapp.svgz b/IconThemes/mono/scalable/apps/kdeapp.svgz
new file mode 100644
index 0000000..2d71ee2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdeapp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdebluetooth.svgz b/IconThemes/mono/scalable/apps/kdebluetooth.svgz
new file mode 100644
index 0000000..3f2e843
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdebluetooth.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdenlive.svgz b/IconThemes/mono/scalable/apps/kdenlive.svgz
new file mode 100644
index 0000000..fbaa7e6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdenlive.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdeprint_printer.svgz b/IconThemes/mono/scalable/apps/kdeprint_printer.svgz
new file mode 100644
index 0000000..b8186db
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdeprint_printer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdeprint_printer_class.svgz b/IconThemes/mono/scalable/apps/kdeprint_printer_class.svgz
new file mode 100644
index 0000000..73b76b5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdeprint_printer_class.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdeprintfax.svgz b/IconThemes/mono/scalable/apps/kdeprintfax.svgz
new file mode 100644
index 0000000..546217e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdeprintfax.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdesvn.svgz b/IconThemes/mono/scalable/apps/kdesvn.svgz
new file mode 100644
index 0000000..c0387e4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdesvn.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdetv.svgz b/IconThemes/mono/scalable/apps/kdetv.svgz
new file mode 100644
index 0000000..bafd923
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdetv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdevassistant.svgz b/IconThemes/mono/scalable/apps/kdevassistant.svgz
new file mode 100644
index 0000000..a5a6dc4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdevassistant.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdevdesigner.svgz b/IconThemes/mono/scalable/apps/kdevdesigner.svgz
new file mode 100644
index 0000000..33c94c9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdevdesigner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdevelop.svgz b/IconThemes/mono/scalable/apps/kdevelop.svgz
new file mode 100644
index 0000000..17a23c1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdevelop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdevelop3.svgz b/IconThemes/mono/scalable/apps/kdevelop3.svgz
new file mode 100644
index 0000000..a9c65a4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdevelop3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdf.svgz b/IconThemes/mono/scalable/apps/kdf.svgz
new file mode 100644
index 0000000..435c070
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdict.svgz b/IconThemes/mono/scalable/apps/kdict.svgz
new file mode 100644
index 0000000..2e9bce5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdict.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdiff3.svgz b/IconThemes/mono/scalable/apps/kdiff3.svgz
new file mode 100644
index 0000000..7448fe0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdiff3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdisknav.svgz b/IconThemes/mono/scalable/apps/kdisknav.svgz
new file mode 100644
index 0000000..0f42965
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdisknav.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdmconfig.svgz b/IconThemes/mono/scalable/apps/kdmconfig.svgz
new file mode 100644
index 0000000..62b574c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdmconfig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kdvi.svgz b/IconThemes/mono/scalable/apps/kdvi.svgz
new file mode 100644
index 0000000..0d7828b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kdvi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kedit.svgz b/IconThemes/mono/scalable/apps/kedit.svgz
new file mode 100644
index 0000000..bb653de
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keditbookmarks.svgz b/IconThemes/mono/scalable/apps/keditbookmarks.svgz
new file mode 100644
index 0000000..8ada64f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keditbookmarks.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keduca.svgz b/IconThemes/mono/scalable/apps/keduca.svgz
new file mode 100644
index 0000000..ce809278
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keduca.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keep.svgz b/IconThemes/mono/scalable/apps/keep.svgz
new file mode 100644
index 0000000..4cdf5f3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keep.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kenolaba.svgz b/IconThemes/mono/scalable/apps/kenolaba.svgz
new file mode 100644
index 0000000..a0a961d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kenolaba.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kerberos-client.svgz b/IconThemes/mono/scalable/apps/kerberos-client.svgz
new file mode 100644
index 0000000..abf7418
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kerberos-client.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kernel.svgz b/IconThemes/mono/scalable/apps/kernel.svgz
new file mode 100644
index 0000000..03eb5d6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kernel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keurocalc.svgz b/IconThemes/mono/scalable/apps/keurocalc.svgz
new file mode 100644
index 0000000..24696f3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keurocalc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kexi.svgz b/IconThemes/mono/scalable/apps/kexi.svgz
new file mode 100644
index 0000000..5c22f34
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kexi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/key_bindings.svgz b/IconThemes/mono/scalable/apps/key_bindings.svgz
new file mode 100644
index 0000000..0eb2088
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/key_bindings.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keyboard-capplet.svgz b/IconThemes/mono/scalable/apps/keyboard-capplet.svgz
new file mode 100644
index 0000000..14dd839
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keyboard-capplet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keyboard-shortcut.svgz b/IconThemes/mono/scalable/apps/keyboard-shortcut.svgz
new file mode 100644
index 0000000..2e550ad
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keyboard-shortcut.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keyboard.svgz b/IconThemes/mono/scalable/apps/keyboard.svgz
new file mode 100644
index 0000000..36bb613
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keyboard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keyboard_layout.svgz b/IconThemes/mono/scalable/apps/keyboard_layout.svgz
new file mode 100644
index 0000000..5c4ac34
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keyboard_layout.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/keyboardlayout.svgz b/IconThemes/mono/scalable/apps/keyboardlayout.svgz
new file mode 100644
index 0000000..f9522a1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/keyboardlayout.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfax.svgz b/IconThemes/mono/scalable/apps/kfax.svgz
new file mode 100644
index 0000000..dd9b1e6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfax.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfaxview.svgz b/IconThemes/mono/scalable/apps/kfaxview.svgz
new file mode 100644
index 0000000..f60bed9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfaxview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfilereplace.svgz b/IconThemes/mono/scalable/apps/kfilereplace.svgz
new file mode 100644
index 0000000..bd81768
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfilereplace.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfind.svgz b/IconThemes/mono/scalable/apps/kfind.svgz
new file mode 100644
index 0000000..eedef89
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfind.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kflog.svgz b/IconThemes/mono/scalable/apps/kflog.svgz
new file mode 100644
index 0000000..0920fe0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kflog.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfloppy.svgz b/IconThemes/mono/scalable/apps/kfloppy.svgz
new file mode 100644
index 0000000..98ad6c2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfloppy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfm.svgz b/IconThemes/mono/scalable/apps/kfm.svgz
new file mode 100644
index 0000000..9f64b3c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfm_home.svgz b/IconThemes/mono/scalable/apps/kfm_home.svgz
new file mode 100644
index 0000000..a06ff1e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfm_home.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfocus.svgz b/IconThemes/mono/scalable/apps/kfocus.svgz
new file mode 100644
index 0000000..910ab0e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfocus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfontview.svgz b/IconThemes/mono/scalable/apps/kfontview.svgz
new file mode 100644
index 0000000..9721193
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfontview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kformdesigner.svgz b/IconThemes/mono/scalable/apps/kformdesigner.svgz
new file mode 100644
index 0000000..f203297
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kformdesigner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kformula.svgz b/IconThemes/mono/scalable/apps/kformula.svgz
new file mode 100644
index 0000000..4bac835
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kformula.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kfouleggs.svgz b/IconThemes/mono/scalable/apps/kfouleggs.svgz
new file mode 100644
index 0000000..77b067f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kfouleggs.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kftpgrabber.svgz b/IconThemes/mono/scalable/apps/kftpgrabber.svgz
new file mode 100644
index 0000000..f4c1f27
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kftpgrabber.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kgamma.svgz b/IconThemes/mono/scalable/apps/kgamma.svgz
new file mode 100644
index 0000000..4c572d9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kgamma.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kgeo.svgz b/IconThemes/mono/scalable/apps/kgeo.svgz
new file mode 100644
index 0000000..41ec1e0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kgeo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kgeography.svgz b/IconThemes/mono/scalable/apps/kgeography.svgz
new file mode 100644
index 0000000..8683c1f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kgeography.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kget.svgz b/IconThemes/mono/scalable/apps/kget.svgz
new file mode 100644
index 0000000..a26b1fe
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kget.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kggz.svgz b/IconThemes/mono/scalable/apps/kggz.svgz
new file mode 100644
index 0000000..64ae6fb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kggz.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kghostview.svgz b/IconThemes/mono/scalable/apps/kghostview.svgz
new file mode 100644
index 0000000..6f1ef2b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kghostview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kgoldrunner.svgz b/IconThemes/mono/scalable/apps/kgoldrunner.svgz
new file mode 100644
index 0000000..603a08f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kgoldrunner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kgpg.svgz b/IconThemes/mono/scalable/apps/kgpg.svgz
new file mode 100644
index 0000000..7340fbf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kgpg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kgpg_docked.svgz b/IconThemes/mono/scalable/apps/kgpg_docked.svgz
new file mode 100644
index 0000000..7b1a293
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kgpg_docked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/khangman.svgz b/IconThemes/mono/scalable/apps/khangman.svgz
new file mode 100644
index 0000000..fe3315d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/khangman.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/khelpcenter.svgz b/IconThemes/mono/scalable/apps/khelpcenter.svgz
new file mode 100644
index 0000000..7a4e1d3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/khelpcenter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/khexedit.svgz b/IconThemes/mono/scalable/apps/khexedit.svgz
new file mode 100644
index 0000000..bfcfc18
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/khexedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/khotkeys.svgz b/IconThemes/mono/scalable/apps/khotkeys.svgz
new file mode 100644
index 0000000..48986e1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/khotkeys.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kicker.svgz b/IconThemes/mono/scalable/apps/kicker.svgz
new file mode 100644
index 0000000..1cee075
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kicker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kiconedit.svgz b/IconThemes/mono/scalable/apps/kiconedit.svgz
new file mode 100644
index 0000000..a50415c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kiconedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kid3.svgz b/IconThemes/mono/scalable/apps/kid3.svgz
new file mode 100644
index 0000000..eca0d1f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kid3.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kig.svgz b/IconThemes/mono/scalable/apps/kig.svgz
new file mode 100644
index 0000000..94b5261
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kile.svgz b/IconThemes/mono/scalable/apps/kile.svgz
new file mode 100644
index 0000000..8651497
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kile.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kimagemapeditor.svgz b/IconThemes/mono/scalable/apps/kimagemapeditor.svgz
new file mode 100644
index 0000000..4c42949
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kimagemapeditor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kimdaba.svgz b/IconThemes/mono/scalable/apps/kimdaba.svgz
new file mode 100644
index 0000000..4f29419
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kimdaba.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kinternet.svgz b/IconThemes/mono/scalable/apps/kinternet.svgz
new file mode 100644
index 0000000..96a1233
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kinternet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kio_uiserver.svgz b/IconThemes/mono/scalable/apps/kio_uiserver.svgz
new file mode 100644
index 0000000..43cda0b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kio_uiserver.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kiosktool.svgz b/IconThemes/mono/scalable/apps/kiosktool.svgz
new file mode 100644
index 0000000..35eac21
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kiosktool.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kipi.svgz b/IconThemes/mono/scalable/apps/kipi.svgz
new file mode 100644
index 0000000..d2394b3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kipi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kitchensync.svgz b/IconThemes/mono/scalable/apps/kitchensync.svgz
new file mode 100644
index 0000000..e9052b7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kitchensync.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kiten.svgz b/IconThemes/mono/scalable/apps/kiten.svgz
new file mode 100644
index 0000000..59bf279
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kiten.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kivio.svgz b/IconThemes/mono/scalable/apps/kivio.svgz
new file mode 100644
index 0000000..c8b4bac
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kivio.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kjobviewer.svgz b/IconThemes/mono/scalable/apps/kjobviewer.svgz
new file mode 100644
index 0000000..afee9c7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kjobviewer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kjots.svgz b/IconThemes/mono/scalable/apps/kjots.svgz
new file mode 100644
index 0000000..b341ccb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kjots.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kjumpingcube.svgz b/IconThemes/mono/scalable/apps/kjumpingcube.svgz
new file mode 100644
index 0000000..0963d52
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kjumpingcube.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klaptopdaemon.svgz b/IconThemes/mono/scalable/apps/klaptopdaemon.svgz
new file mode 100644
index 0000000..0585591
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klaptopdaemon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klatin.svgz b/IconThemes/mono/scalable/apps/klatin.svgz
new file mode 100644
index 0000000..80c8a2a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klatin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klettres.svgz b/IconThemes/mono/scalable/apps/klettres.svgz
new file mode 100644
index 0000000..4120a8c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klettres.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klickety.svgz b/IconThemes/mono/scalable/apps/klickety.svgz
new file mode 100644
index 0000000..03416aa
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klickety.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klines.svgz b/IconThemes/mono/scalable/apps/klines.svgz
new file mode 100644
index 0000000..6e5a5b9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klines.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klinkstatus.svgz b/IconThemes/mono/scalable/apps/klinkstatus.svgz
new file mode 100644
index 0000000..4e5ce2f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klinkstatus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klipper.svgz b/IconThemes/mono/scalable/apps/klipper.svgz
new file mode 100644
index 0000000..2a5b314
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klipper.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klipper_doc.svgz b/IconThemes/mono/scalable/apps/klipper_doc.svgz
new file mode 100644
index 0000000..d4951ac
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klipper_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/klpq.svgz b/IconThemes/mono/scalable/apps/klpq.svgz
new file mode 100644
index 0000000..d9dbfe7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/klpq.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmag.svgz b/IconThemes/mono/scalable/apps/kmag.svgz
new file mode 100644
index 0000000..1501770
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmahjongg.svgz b/IconThemes/mono/scalable/apps/kmahjongg.svgz
new file mode 100644
index 0000000..75f9c7f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmahjongg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmail.svgz b/IconThemes/mono/scalable/apps/kmail.svgz
new file mode 100644
index 0000000..b88e750
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmailcvt.svgz b/IconThemes/mono/scalable/apps/kmailcvt.svgz
new file mode 100644
index 0000000..b07f784
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmailcvt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmaillight.svgz b/IconThemes/mono/scalable/apps/kmaillight.svgz
new file mode 100644
index 0000000..6ab0adb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmaillight.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmameleon.svgz b/IconThemes/mono/scalable/apps/kmameleon.svgz
new file mode 100644
index 0000000..c79cbe2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmameleon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmathtool.svgz b/IconThemes/mono/scalable/apps/kmathtool.svgz
new file mode 100644
index 0000000..3969101
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmathtool.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmdr-editor.svgz b/IconThemes/mono/scalable/apps/kmdr-editor.svgz
new file mode 100644
index 0000000..a289522
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmdr-editor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmdr_editor.svgz b/IconThemes/mono/scalable/apps/kmdr_editor.svgz
new file mode 100644
index 0000000..a289522
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmdr_editor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmdr_executor.svgz b/IconThemes/mono/scalable/apps/kmdr_executor.svgz
new file mode 100644
index 0000000..3ad9a16
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmdr_executor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmenu.svgz b/IconThemes/mono/scalable/apps/kmenu.svgz
new file mode 100644
index 0000000..7682c1d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmenu.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmenuedit.svgz b/IconThemes/mono/scalable/apps/kmenuedit.svgz
new file mode 100644
index 0000000..027cce7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmenuedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmerlin.svgz b/IconThemes/mono/scalable/apps/kmerlin.svgz
new file mode 100644
index 0000000..f0eac4b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmerlin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmid.svgz b/IconThemes/mono/scalable/apps/kmid.svgz
new file mode 100644
index 0000000..60c2827
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmid.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmidi.svgz b/IconThemes/mono/scalable/apps/kmidi.svgz
new file mode 100644
index 0000000..5867fa0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmidi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmines.svgz b/IconThemes/mono/scalable/apps/kmines.svgz
new file mode 100644
index 0000000..8efce16
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmines.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmix.svgz b/IconThemes/mono/scalable/apps/kmix.svgz
new file mode 100644
index 0000000..d66af47
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmix.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmixdocked.svgz b/IconThemes/mono/scalable/apps/kmixdocked.svgz
new file mode 100644
index 0000000..3a7cbfb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmixdocked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmixdocked_error.svgz b/IconThemes/mono/scalable/apps/kmixdocked_error.svgz
new file mode 100644
index 0000000..faa408c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmixdocked_error.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmixdocked_mute.svgz b/IconThemes/mono/scalable/apps/kmixdocked_mute.svgz
new file mode 100644
index 0000000..b85a9de
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmixdocked_mute.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmldonkey.svgz b/IconThemes/mono/scalable/apps/kmldonkey.svgz
new file mode 100644
index 0000000..4a27460
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmldonkey.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmoon.svgz b/IconThemes/mono/scalable/apps/kmoon.svgz
new file mode 100644
index 0000000..de60ef2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmoon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmousetool.svgz b/IconThemes/mono/scalable/apps/kmousetool.svgz
new file mode 100644
index 0000000..95f1e3a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmousetool.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmouth.svgz b/IconThemes/mono/scalable/apps/kmouth.svgz
new file mode 100644
index 0000000..dbb030c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmouth.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmplayer.svgz b/IconThemes/mono/scalable/apps/kmplayer.svgz
new file mode 100644
index 0000000..c704a4f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmplayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmplot.svgz b/IconThemes/mono/scalable/apps/kmplot.svgz
new file mode 100644
index 0000000..67c1014
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmplot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmyfirewall.svgz b/IconThemes/mono/scalable/apps/kmyfirewall.svgz
new file mode 100644
index 0000000..fa0af15
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmyfirewall.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kmymoney2.svgz b/IconThemes/mono/scalable/apps/kmymoney2.svgz
new file mode 100644
index 0000000..8aec0df
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kmymoney2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knetattach.svgz b/IconThemes/mono/scalable/apps/knetattach.svgz
new file mode 100644
index 0000000..3043816
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knetattach.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knetload.svgz b/IconThemes/mono/scalable/apps/knetload.svgz
new file mode 100644
index 0000000..56b4d6e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knetload.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knetwalk.svgz b/IconThemes/mono/scalable/apps/knetwalk.svgz
new file mode 100644
index 0000000..22df4d9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knetwalk.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knetworkconf.svgz b/IconThemes/mono/scalable/apps/knetworkconf.svgz
new file mode 100644
index 0000000..e5e2ba4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knetworkconf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knetworkmanager.svgz b/IconThemes/mono/scalable/apps/knetworkmanager.svgz
new file mode 100644
index 0000000..38084cb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knetworkmanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knewsticker.svgz b/IconThemes/mono/scalable/apps/knewsticker.svgz
new file mode 100644
index 0000000..e860e3b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knewsticker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knoda.svgz b/IconThemes/mono/scalable/apps/knoda.svgz
new file mode 100644
index 0000000..5a2dbad
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knoda.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knode.svgz b/IconThemes/mono/scalable/apps/knode.svgz
new file mode 100644
index 0000000..60bcf3a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knode.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knode2.svgz b/IconThemes/mono/scalable/apps/knode2.svgz
new file mode 100644
index 0000000..6490888
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knode2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knoppix-penguin.svgz b/IconThemes/mono/scalable/apps/knoppix-penguin.svgz
new file mode 100644
index 0000000..8f9d5b4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knoppix-penguin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knotes.svgz b/IconThemes/mono/scalable/apps/knotes.svgz
new file mode 100644
index 0000000..0f4662d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knotes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/knotify.svgz b/IconThemes/mono/scalable/apps/knotify.svgz
new file mode 100644
index 0000000..757b3f1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/knotify.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kodo.svgz b/IconThemes/mono/scalable/apps/kodo.svgz
new file mode 100644
index 0000000..9f7567c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kodo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kolf.svgz b/IconThemes/mono/scalable/apps/kolf.svgz
new file mode 100644
index 0000000..1a77bc6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kolf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kolourpaint.svgz b/IconThemes/mono/scalable/apps/kolourpaint.svgz
new file mode 100644
index 0000000..e16abce
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kolourpaint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kommander.svgz b/IconThemes/mono/scalable/apps/kommander.svgz
new file mode 100644
index 0000000..43e37e4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kommander.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kommando.svgz b/IconThemes/mono/scalable/apps/kommando.svgz
new file mode 100644
index 0000000..d373ed8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kommando.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/komparator.svgz b/IconThemes/mono/scalable/apps/komparator.svgz
new file mode 100644
index 0000000..06f4453
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/komparator.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kompare.svgz b/IconThemes/mono/scalable/apps/kompare.svgz
new file mode 100644
index 0000000..06f4453
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kompare.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kompose.svgz b/IconThemes/mono/scalable/apps/kompose.svgz
new file mode 100644
index 0000000..74f2ad7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kompose.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konqsidebar_mediaplayer.svgz b/IconThemes/mono/scalable/apps/konqsidebar_mediaplayer.svgz
new file mode 100644
index 0000000..53c8927
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konqsidebar_mediaplayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konqsidebar_news.svgz b/IconThemes/mono/scalable/apps/konqsidebar_news.svgz
new file mode 100644
index 0000000..116a092
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konqsidebar_news.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konqueror.svgz b/IconThemes/mono/scalable/apps/konqueror.svgz
new file mode 100644
index 0000000..a40cfc6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konqueror.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konquest.svgz b/IconThemes/mono/scalable/apps/konquest.svgz
new file mode 100644
index 0000000..438803b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konquest.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konserve.svgz b/IconThemes/mono/scalable/apps/konserve.svgz
new file mode 100644
index 0000000..911bcad
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konserve.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konsole.svgz b/IconThemes/mono/scalable/apps/konsole.svgz
new file mode 100644
index 0000000..2f505f2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konsole.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konsolekalendar.svgz b/IconThemes/mono/scalable/apps/konsolekalendar.svgz
new file mode 100644
index 0000000..b2b5dcc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konsolekalendar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kontact.svgz b/IconThemes/mono/scalable/apps/kontact.svgz
new file mode 100644
index 0000000..cfd377d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kontact.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konversation.svgz b/IconThemes/mono/scalable/apps/konversation.svgz
new file mode 100644
index 0000000..cb0e74d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konversation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/konverter.svgz b/IconThemes/mono/scalable/apps/konverter.svgz
new file mode 100644
index 0000000..a39fc3f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/konverter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kooka.svgz b/IconThemes/mono/scalable/apps/kooka.svgz
new file mode 100644
index 0000000..b7faa89
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kooka.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kopete.svgz b/IconThemes/mono/scalable/apps/kopete.svgz
new file mode 100644
index 0000000..ddf3a00
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kopete.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kopete2.svgz b/IconThemes/mono/scalable/apps/kopete2.svgz
new file mode 100644
index 0000000..ddf3a00
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kopete2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kopete_all_away.svgz b/IconThemes/mono/scalable/apps/kopete_all_away.svgz
new file mode 100644
index 0000000..868a9de
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kopete_all_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kopete_avdevice.svgz b/IconThemes/mono/scalable/apps/kopete_avdevice.svgz
new file mode 100644
index 0000000..f1901a8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kopete_avdevice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kopete_offline.svgz b/IconThemes/mono/scalable/apps/kopete_offline.svgz
new file mode 100644
index 0000000..9275a68
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kopete_offline.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kopete_some_away.svgz b/IconThemes/mono/scalable/apps/kopete_some_away.svgz
new file mode 100644
index 0000000..f689a49
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kopete_some_away.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kopete_some_online.svgz b/IconThemes/mono/scalable/apps/kopete_some_online.svgz
new file mode 100644
index 0000000..2fdaf61
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kopete_some_online.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/korganizer.svgz b/IconThemes/mono/scalable/apps/korganizer.svgz
new file mode 100644
index 0000000..7d9926d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/korganizer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/korganizer_todo.svgz b/IconThemes/mono/scalable/apps/korganizer_todo.svgz
new file mode 100644
index 0000000..75ed091
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/korganizer_todo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/korn.svgz b/IconThemes/mono/scalable/apps/korn.svgz
new file mode 100644
index 0000000..8b79e13
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/korn.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/koshell.svgz b/IconThemes/mono/scalable/apps/koshell.svgz
new file mode 100644
index 0000000..ccef0b5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/koshell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpackage.svgz b/IconThemes/mono/scalable/apps/kpackage.svgz
new file mode 100644
index 0000000..77e7f75
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpackage.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpager.svgz b/IconThemes/mono/scalable/apps/kpager.svgz
new file mode 100644
index 0000000..786225e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpaint.svgz b/IconThemes/mono/scalable/apps/kpaint.svgz
new file mode 100644
index 0000000..e16abce
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpaint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpalmdoc.svgz b/IconThemes/mono/scalable/apps/kpalmdoc.svgz
new file mode 100644
index 0000000..d491f2b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpalmdoc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpat.svgz b/IconThemes/mono/scalable/apps/kpat.svgz
new file mode 100644
index 0000000..833447f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpdf.svgz b/IconThemes/mono/scalable/apps/kpdf.svgz
new file mode 100644
index 0000000..0750e63
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpdf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpercentage.svgz b/IconThemes/mono/scalable/apps/kpercentage.svgz
new file mode 100644
index 0000000..06eb67a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpercentage.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpersonalizer.svgz b/IconThemes/mono/scalable/apps/kpersonalizer.svgz
new file mode 100644
index 0000000..a404cdf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpersonalizer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpf.svgz b/IconThemes/mono/scalable/apps/kpf.svgz
new file mode 100644
index 0000000..f2bc73d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpilot.svgz b/IconThemes/mono/scalable/apps/kpilot.svgz
new file mode 100644
index 0000000..f475dc1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpilot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpilotDaemon.svgz b/IconThemes/mono/scalable/apps/kpilotDaemon.svgz
new file mode 100644
index 0000000..f475dc1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpilotDaemon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kplato.svgz b/IconThemes/mono/scalable/apps/kplato.svgz
new file mode 100644
index 0000000..98a0a73
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kplato.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kplayer.svgz b/IconThemes/mono/scalable/apps/kplayer.svgz
new file mode 100644
index 0000000..29a7d02
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kplayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpoker.svgz b/IconThemes/mono/scalable/apps/kpoker.svgz
new file mode 100644
index 0000000..01cc3f1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpoker.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpovmodeler.svgz b/IconThemes/mono/scalable/apps/kpovmodeler.svgz
new file mode 100644
index 0000000..3a69b21
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpovmodeler.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpowersave.svgz b/IconThemes/mono/scalable/apps/kpowersave.svgz
new file mode 100644
index 0000000..7c9820a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpowersave.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kppp.svgz b/IconThemes/mono/scalable/apps/kppp.svgz
new file mode 100644
index 0000000..e4e81d5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kppp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kpresenter.svgz b/IconThemes/mono/scalable/apps/kpresenter.svgz
new file mode 100644
index 0000000..9fed0af
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kpresenter.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kprintfax.svgz b/IconThemes/mono/scalable/apps/kprintfax.svgz
new file mode 100644
index 0000000..990e317
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kprintfax.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kprof.svgz b/IconThemes/mono/scalable/apps/kprof.svgz
new file mode 100644
index 0000000..cb80ced
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kprof.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/krdc.svgz b/IconThemes/mono/scalable/apps/krdc.svgz
new file mode 100644
index 0000000..6afbd7e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/krdc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/krec.svgz b/IconThemes/mono/scalable/apps/krec.svgz
new file mode 100644
index 0000000..7c9ccb5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/krec.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/krecipes.svgz b/IconThemes/mono/scalable/apps/krecipes.svgz
new file mode 100644
index 0000000..1340dd9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/krecipes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kregexpeditor.svgz b/IconThemes/mono/scalable/apps/kregexpeditor.svgz
new file mode 100644
index 0000000..6cc206b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kregexpeditor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/krename.svgz b/IconThemes/mono/scalable/apps/krename.svgz
new file mode 100644
index 0000000..944898e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/krename.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kreversi.svgz b/IconThemes/mono/scalable/apps/kreversi.svgz
new file mode 100644
index 0000000..244db93
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kreversi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/krfb.svgz b/IconThemes/mono/scalable/apps/krfb.svgz
new file mode 100644
index 0000000..22df4d9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/krfb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/krita.svgz b/IconThemes/mono/scalable/apps/krita.svgz
new file mode 100644
index 0000000..283661c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/krita.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kruler.svgz b/IconThemes/mono/scalable/apps/kruler.svgz
new file mode 100644
index 0000000..229bbed
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kruler.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksame.svgz b/IconThemes/mono/scalable/apps/ksame.svgz
new file mode 100644
index 0000000..e576900
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksame.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksayit.svgz b/IconThemes/mono/scalable/apps/ksayit.svgz
new file mode 100644
index 0000000..961631f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksayit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksayit_clipempty.svgz b/IconThemes/mono/scalable/apps/ksayit_clipempty.svgz
new file mode 100644
index 0000000..7d806a6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksayit_clipempty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksayit_talking.svgz b/IconThemes/mono/scalable/apps/ksayit_talking.svgz
new file mode 100644
index 0000000..f9f332c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksayit_talking.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kscd.svgz b/IconThemes/mono/scalable/apps/kscd.svgz
new file mode 100644
index 0000000..03e9492
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kscd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kscreensaver.svgz b/IconThemes/mono/scalable/apps/kscreensaver.svgz
new file mode 100644
index 0000000..68ac06c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kscreensaver.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksensors.svgz b/IconThemes/mono/scalable/apps/ksensors.svgz
new file mode 100644
index 0000000..184cdbf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksensors.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kservices.svgz b/IconThemes/mono/scalable/apps/kservices.svgz
new file mode 100644
index 0000000..3a1a27c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kservices.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kshisen.svgz b/IconThemes/mono/scalable/apps/kshisen.svgz
new file mode 100644
index 0000000..22b116e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kshisen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kshutdown.svgz b/IconThemes/mono/scalable/apps/kshutdown.svgz
new file mode 100644
index 0000000..802ed30
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kshutdown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksig.svgz b/IconThemes/mono/scalable/apps/ksig.svgz
new file mode 100644
index 0000000..8113b2d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksim.svgz b/IconThemes/mono/scalable/apps/ksim.svgz
new file mode 100644
index 0000000..be4617c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksim.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksirc.svgz b/IconThemes/mono/scalable/apps/ksirc.svgz
new file mode 100644
index 0000000..51cf442
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksirc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksirtet.svgz b/IconThemes/mono/scalable/apps/ksirtet.svgz
new file mode 100644
index 0000000..8bf9efc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksirtet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksmiletris.svgz b/IconThemes/mono/scalable/apps/ksmiletris.svgz
new file mode 100644
index 0000000..64bc0fd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksmiletris.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksnake.svgz b/IconThemes/mono/scalable/apps/ksnake.svgz
new file mode 100644
index 0000000..8ddfef5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksnake.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksnapshot.svgz b/IconThemes/mono/scalable/apps/ksnapshot.svgz
new file mode 100644
index 0000000..fa6c80d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksnapshot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksokoban.svgz b/IconThemes/mono/scalable/apps/ksokoban.svgz
new file mode 100644
index 0000000..4501070
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksokoban.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kspaceduel.svgz b/IconThemes/mono/scalable/apps/kspaceduel.svgz
new file mode 100644
index 0000000..f329bf7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kspaceduel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksplash.svgz b/IconThemes/mono/scalable/apps/ksplash.svgz
new file mode 100644
index 0000000..0462e73
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksplash.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kspread.svgz b/IconThemes/mono/scalable/apps/kspread.svgz
new file mode 100644
index 0000000..5198332
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kspread.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kstars.svgz b/IconThemes/mono/scalable/apps/kstars.svgz
new file mode 100644
index 0000000..2fefba4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kstars.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kstreamripper.svgz b/IconThemes/mono/scalable/apps/kstreamripper.svgz
new file mode 100644
index 0000000..b997762
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kstreamripper.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksysguard.svgz b/IconThemes/mono/scalable/apps/ksysguard.svgz
new file mode 100644
index 0000000..beaff79
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksysguard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksysguardd.svgz b/IconThemes/mono/scalable/apps/ksysguardd.svgz
new file mode 100644
index 0000000..cf3f67d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksysguardd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ksysv.svgz b/IconThemes/mono/scalable/apps/ksysv.svgz
new file mode 100644
index 0000000..fa365fe
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ksysv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktalkd.svgz b/IconThemes/mono/scalable/apps/ktalkd.svgz
new file mode 100644
index 0000000..50d6f56
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktalkd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kteatime.svgz b/IconThemes/mono/scalable/apps/kteatime.svgz
new file mode 100644
index 0000000..d369ef9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kteatime.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktechlab.svgz b/IconThemes/mono/scalable/apps/ktechlab.svgz
new file mode 100644
index 0000000..f9b23c1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktechlab.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kthememgr.svgz b/IconThemes/mono/scalable/apps/kthememgr.svgz
new file mode 100644
index 0000000..37db41f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kthememgr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kthesaurus.svgz b/IconThemes/mono/scalable/apps/kthesaurus.svgz
new file mode 100644
index 0000000..889e265
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kthesaurus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktimemon.svgz b/IconThemes/mono/scalable/apps/ktimemon.svgz
new file mode 100644
index 0000000..f69a6db
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktimemon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktimer.svgz b/IconThemes/mono/scalable/apps/ktimer.svgz
new file mode 100644
index 0000000..95da9d2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktimer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktip.svgz b/IconThemes/mono/scalable/apps/ktip.svgz
new file mode 100644
index 0000000..7112a67
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktip.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktnef.svgz b/IconThemes/mono/scalable/apps/ktnef.svgz
new file mode 100644
index 0000000..187a80c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktnef.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktorrent.svgz b/IconThemes/mono/scalable/apps/ktorrent.svgz
new file mode 100644
index 0000000..90151e5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktorrent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktouch.svgz b/IconThemes/mono/scalable/apps/ktouch.svgz
new file mode 100644
index 0000000..a8c0db2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktouch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktron.svgz b/IconThemes/mono/scalable/apps/ktron.svgz
new file mode 100644
index 0000000..c9220ed
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktron.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kttsd.svgz b/IconThemes/mono/scalable/apps/kttsd.svgz
new file mode 100644
index 0000000..ffaf78e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kttsd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktuberling.svgz b/IconThemes/mono/scalable/apps/ktuberling.svgz
new file mode 100644
index 0000000..e4099bf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktuberling.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kturtle.svgz b/IconThemes/mono/scalable/apps/kturtle.svgz
new file mode 100644
index 0000000..6fac79f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kturtle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ktux.svgz b/IconThemes/mono/scalable/apps/ktux.svgz
new file mode 100644
index 0000000..961bb0e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ktux.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kudesigner.svgz b/IconThemes/mono/scalable/apps/kudesigner.svgz
new file mode 100644
index 0000000..e069a19
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kudesigner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kugar.svgz b/IconThemes/mono/scalable/apps/kugar.svgz
new file mode 100644
index 0000000..ef134f3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kugar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kuickshow.svgz b/IconThemes/mono/scalable/apps/kuickshow.svgz
new file mode 100644
index 0000000..0d8459b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kuickshow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kuiviewer.svgz b/IconThemes/mono/scalable/apps/kuiviewer.svgz
new file mode 100644
index 0000000..911e337
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kuiviewer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kuser.svgz b/IconThemes/mono/scalable/apps/kuser.svgz
new file mode 100644
index 0000000..a7b3a3b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kuser.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kverbos.svgz b/IconThemes/mono/scalable/apps/kverbos.svgz
new file mode 100644
index 0000000..e54b06f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kverbos.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kview.svgz b/IconThemes/mono/scalable/apps/kview.svgz
new file mode 100644
index 0000000..f3ca22e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kviewshell.svgz b/IconThemes/mono/scalable/apps/kviewshell.svgz
new file mode 100644
index 0000000..de4dc65
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kviewshell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kvim.svgz b/IconThemes/mono/scalable/apps/kvim.svgz
new file mode 100644
index 0000000..0e35a8f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kvim.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kvirc.svgz b/IconThemes/mono/scalable/apps/kvirc.svgz
new file mode 100644
index 0000000..536a73f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kvirc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kvoctrain.svgz b/IconThemes/mono/scalable/apps/kvoctrain.svgz
new file mode 100644
index 0000000..2e204e3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kvoctrain.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwallet.svgz b/IconThemes/mono/scalable/apps/kwallet.svgz
new file mode 100644
index 0000000..9523cc6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwallet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwalletmanager.svgz b/IconThemes/mono/scalable/apps/kwalletmanager.svgz
new file mode 100644
index 0000000..9523cc6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwalletmanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwave.svgz b/IconThemes/mono/scalable/apps/kwave.svgz
new file mode 100644
index 0000000..a370c62
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwave.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwavecontrol.svgz b/IconThemes/mono/scalable/apps/kwavecontrol.svgz
new file mode 100644
index 0000000..ca3ae6a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwavecontrol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kweather.svgz b/IconThemes/mono/scalable/apps/kweather.svgz
new file mode 100644
index 0000000..8ecfca0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kweather.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwifimanager.svgz b/IconThemes/mono/scalable/apps/kwifimanager.svgz
new file mode 100644
index 0000000..81a4935
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwifimanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwikdisk.svgz b/IconThemes/mono/scalable/apps/kwikdisk.svgz
new file mode 100644
index 0000000..18a103e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwikdisk.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwin.svgz b/IconThemes/mono/scalable/apps/kwin.svgz
new file mode 100644
index 0000000..6eb77cc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwin4.svgz b/IconThemes/mono/scalable/apps/kwin4.svgz
new file mode 100644
index 0000000..251b7be
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwin4.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kword.svgz b/IconThemes/mono/scalable/apps/kword.svgz
new file mode 100644
index 0000000..4b728f3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kword.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwordquiz.svgz b/IconThemes/mono/scalable/apps/kwordquiz.svgz
new file mode 100644
index 0000000..bec43a9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwordquiz.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kworldclock.svgz b/IconThemes/mono/scalable/apps/kworldclock.svgz
new file mode 100644
index 0000000..41a5641
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kworldclock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwrite.svgz b/IconThemes/mono/scalable/apps/kwrite.svgz
new file mode 100644
index 0000000..7dc8688
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwrite.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kwrite2.svgz b/IconThemes/mono/scalable/apps/kwrite2.svgz
new file mode 100644
index 0000000..7dc8688
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kwrite2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kxconfig.svgz b/IconThemes/mono/scalable/apps/kxconfig.svgz
new file mode 100644
index 0000000..515cd8a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kxconfig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kxkb.svgz b/IconThemes/mono/scalable/apps/kxkb.svgz
new file mode 100644
index 0000000..df37f42
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kxkb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kxsldbg.svgz b/IconThemes/mono/scalable/apps/kxsldbg.svgz
new file mode 100644
index 0000000..f5f8020
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kxsldbg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kynaptic.svgz b/IconThemes/mono/scalable/apps/kynaptic.svgz
new file mode 100644
index 0000000..20656dd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kynaptic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/kzenexplorer.svgz b/IconThemes/mono/scalable/apps/kzenexplorer.svgz
new file mode 100644
index 0000000..61698ce
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/kzenexplorer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/laptop_battery.svgz b/IconThemes/mono/scalable/apps/laptop_battery.svgz
new file mode 100644
index 0000000..f2f20e2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/laptop_battery.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/laptop_pcmcia.svgz b/IconThemes/mono/scalable/apps/laptop_pcmcia.svgz
new file mode 100644
index 0000000..a6cb06e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/laptop_pcmcia.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/lbreakout.svgz b/IconThemes/mono/scalable/apps/lbreakout.svgz
new file mode 100644
index 0000000..50219c2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/lbreakout.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ldap_client.svgz b/IconThemes/mono/scalable/apps/ldap_client.svgz
new file mode 100644
index 0000000..10f0508
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ldap_client.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ledger.svgz b/IconThemes/mono/scalable/apps/ledger.svgz
new file mode 100644
index 0000000..04ac10a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ledger.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/licq.svgz b/IconThemes/mono/scalable/apps/licq.svgz
new file mode 100644
index 0000000..2627e0d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/licq.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/limewire.svgz b/IconThemes/mono/scalable/apps/limewire.svgz
new file mode 100644
index 0000000..2bd4520
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/limewire.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/linguist.svgz b/IconThemes/mono/scalable/apps/linguist.svgz
new file mode 100644
index 0000000..53fc805
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/linguist.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/linuxconf.svgz b/IconThemes/mono/scalable/apps/linuxconf.svgz
new file mode 100644
index 0000000..4931fb3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/linuxconf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/locale.svgz b/IconThemes/mono/scalable/apps/locale.svgz
new file mode 100644
index 0000000..b695a27
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/locale.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/lockscreen.svgz b/IconThemes/mono/scalable/apps/lockscreen.svgz
new file mode 100644
index 0000000..186703a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/lockscreen.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/logjam.svgz b/IconThemes/mono/scalable/apps/logjam.svgz
new file mode 100644
index 0000000..2badcd5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/logjam.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/logout.svgz b/IconThemes/mono/scalable/apps/logout.svgz
new file mode 100644
index 0000000..5caca4d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/logout.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/looknfeel.svgz b/IconThemes/mono/scalable/apps/looknfeel.svgz
new file mode 100644
index 0000000..89a4245
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/looknfeel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/lskat.svgz b/IconThemes/mono/scalable/apps/lskat.svgz
new file mode 100644
index 0000000..24291d6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/lskat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/lvm.svgz b/IconThemes/mono/scalable/apps/lvm.svgz
new file mode 100644
index 0000000..8ee7071
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/lvm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/lyx.svgz b/IconThemes/mono/scalable/apps/lyx.svgz
new file mode 100644
index 0000000..34c00b7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/lyx.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mac.svgz b/IconThemes/mono/scalable/apps/mac.svgz
new file mode 100644
index 0000000..e6f3d50
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mac.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mail.svgz b/IconThemes/mono/scalable/apps/mail.svgz
new file mode 100644
index 0000000..a56a21b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mail_section.svgz b/IconThemes/mono/scalable/apps/mail_section.svgz
new file mode 100644
index 0000000..1f19f9b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mail_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mathematica.svgz b/IconThemes/mono/scalable/apps/mathematica.svgz
new file mode 100644
index 0000000..c00faca
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mathematica.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/media-player-48.svgz b/IconThemes/mono/scalable/apps/media-player-48.svgz
new file mode 100644
index 0000000..5140570
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/media-player-48.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/megami.svgz b/IconThemes/mono/scalable/apps/megami.svgz
new file mode 100644
index 0000000..79ffe77
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/megami.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/menubar.svgz b/IconThemes/mono/scalable/apps/menubar.svgz
new file mode 100644
index 0000000..d317446
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/menubar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/misc2.svgz b/IconThemes/mono/scalable/apps/misc2.svgz
new file mode 100644
index 0000000..4f0fc37
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/misc2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mldonkey.svgz b/IconThemes/mono/scalable/apps/mldonkey.svgz
new file mode 100644
index 0000000..7c768ca
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mldonkey.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/modem.svgz b/IconThemes/mono/scalable/apps/modem.svgz
new file mode 100644
index 0000000..6017a39
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/modem.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/monop_board.svgz b/IconThemes/mono/scalable/apps/monop_board.svgz
new file mode 100644
index 0000000..41eb533
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/monop_board.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mouse-capplet.svgz b/IconThemes/mono/scalable/apps/mouse-capplet.svgz
new file mode 100644
index 0000000..0596488
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mouse-capplet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mouse.svgz b/IconThemes/mono/scalable/apps/mouse.svgz
new file mode 100644
index 0000000..eaea1e4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mouse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mozilla-firefox.svgz b/IconThemes/mono/scalable/apps/mozilla-firefox.svgz
new file mode 100644
index 0000000..5f8b08a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mozilla-firefox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mozilla-navigator.svgz b/IconThemes/mono/scalable/apps/mozilla-navigator.svgz
new file mode 100644
index 0000000..293bb98
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mozilla-navigator.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mozilla-thunderbird.svgz b/IconThemes/mono/scalable/apps/mozilla-thunderbird.svgz
new file mode 100644
index 0000000..2c32efc
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mozilla-thunderbird.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mozilla.svgz b/IconThemes/mono/scalable/apps/mozilla.svgz
new file mode 100644
index 0000000..76c24f7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mozilla.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mozilla_m.svgz b/IconThemes/mono/scalable/apps/mozilla_m.svgz
new file mode 100644
index 0000000..ace3db1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mozilla_m.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mozilla_mail.svgz b/IconThemes/mono/scalable/apps/mozilla_mail.svgz
new file mode 100644
index 0000000..86380b0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mozilla_mail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mozilla_mailnews.svgz b/IconThemes/mono/scalable/apps/mozilla_mailnews.svgz
new file mode 100644
index 0000000..76fbb68
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mozilla_mailnews.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mplayer.svgz b/IconThemes/mono/scalable/apps/mplayer.svgz
new file mode 100644
index 0000000..07a7c6b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mplayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/msn.svgz b/IconThemes/mono/scalable/apps/msn.svgz
new file mode 100644
index 0000000..1b9ea35
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/msn.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/msn_protocol.svgz b/IconThemes/mono/scalable/apps/msn_protocol.svgz
new file mode 100644
index 0000000..566119e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/msn_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/multihead.svgz b/IconThemes/mono/scalable/apps/multihead.svgz
new file mode 100644
index 0000000..4641342
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/multihead.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/multimedia.svgz b/IconThemes/mono/scalable/apps/multimedia.svgz
new file mode 100644
index 0000000..8478363
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/multimedia.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/multisynk.svgz b/IconThemes/mono/scalable/apps/multisynk.svgz
new file mode 100644
index 0000000..5cea78f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/multisynk.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/my_mac.svgz b/IconThemes/mono/scalable/apps/my_mac.svgz
new file mode 100644
index 0000000..cd245c2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/my_mac.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mycomp.svgz b/IconThemes/mono/scalable/apps/mycomp.svgz
new file mode 100644
index 0000000..db85f50
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mycomp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mycomputer.svgz b/IconThemes/mono/scalable/apps/mycomputer.svgz
new file mode 100644
index 0000000..6e2b020
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mycomputer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/mymac.svgz b/IconThemes/mono/scalable/apps/mymac.svgz
new file mode 100644
index 0000000..a9bc9ba
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/mymac.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/napster.svgz b/IconThemes/mono/scalable/apps/napster.svgz
new file mode 100644
index 0000000..0b3348d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/napster.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/nedit.svgz b/IconThemes/mono/scalable/apps/nedit.svgz
new file mode 100644
index 0000000..a2a05f0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/nedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/netscape.svgz b/IconThemes/mono/scalable/apps/netscape.svgz
new file mode 100644
index 0000000..3461463
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/netscape.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/network.svgz b/IconThemes/mono/scalable/apps/network.svgz
new file mode 100644
index 0000000..e5e2ba4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/network.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/network_advanced.svgz b/IconThemes/mono/scalable/apps/network_advanced.svgz
new file mode 100644
index 0000000..2aaa95b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/network_advanced.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/nfs.svgz b/IconThemes/mono/scalable/apps/nfs.svgz
new file mode 100644
index 0000000..9c8cd69
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/nfs.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/noatun.svgz b/IconThemes/mono/scalable/apps/noatun.svgz
new file mode 100644
index 0000000..8f317a0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/noatun.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ntp-client.svgz b/IconThemes/mono/scalable/apps/ntp-client.svgz
new file mode 100644
index 0000000..741631e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ntp-client.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/nvu.svgz b/IconThemes/mono/scalable/apps/nvu.svgz
new file mode 100644
index 0000000..7a367af
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/nvu.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/okle.svgz b/IconThemes/mono/scalable/apps/okle.svgz
new file mode 100644
index 0000000..9f928fa
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/okle.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_calc.svgz b/IconThemes/mono/scalable/apps/ooo_calc.svgz
new file mode 100644
index 0000000..93d0de4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_calc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_calc_tpl.svgz b/IconThemes/mono/scalable/apps/ooo_calc_tpl.svgz
new file mode 100644
index 0000000..37fea09
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_calc_tpl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_chart.svgz b/IconThemes/mono/scalable/apps/ooo_chart.svgz
new file mode 100644
index 0000000..7a8a247
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_chart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_draw.svgz b/IconThemes/mono/scalable/apps/ooo_draw.svgz
new file mode 100644
index 0000000..78e87ab
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_draw.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_gulls.svgz b/IconThemes/mono/scalable/apps/ooo_gulls.svgz
new file mode 100644
index 0000000..1d11252
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_gulls.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_impress.svgz b/IconThemes/mono/scalable/apps/ooo_impress.svgz
new file mode 100644
index 0000000..db0c7a5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_impress.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_impress_tpl.svgz b/IconThemes/mono/scalable/apps/ooo_impress_tpl.svgz
new file mode 100644
index 0000000..71ae51a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_impress_tpl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_math.svgz b/IconThemes/mono/scalable/apps/ooo_math.svgz
new file mode 100644
index 0000000..dc58466
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_math.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_printeradmin.svgz b/IconThemes/mono/scalable/apps/ooo_printeradmin.svgz
new file mode 100644
index 0000000..395cf86
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_printeradmin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_setup.svgz b/IconThemes/mono/scalable/apps/ooo_setup.svgz
new file mode 100644
index 0000000..f4d488a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_setup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_template.svgz b/IconThemes/mono/scalable/apps/ooo_template.svgz
new file mode 100644
index 0000000..27d1e41
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_template.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_web.svgz b/IconThemes/mono/scalable/apps/ooo_web.svgz
new file mode 100644
index 0000000..28ca25a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_web.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/ooo_writer.svgz b/IconThemes/mono/scalable/apps/ooo_writer.svgz
new file mode 100644
index 0000000..ebc91cf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/ooo_writer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/openft.svgz b/IconThemes/mono/scalable/apps/openft.svgz
new file mode 100644
index 0000000..e7d9e99
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/openft.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/openoffice.svgz b/IconThemes/mono/scalable/apps/openoffice.svgz
new file mode 100644
index 0000000..b58840b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/openoffice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/openoffice1.svgz b/IconThemes/mono/scalable/apps/openoffice1.svgz
new file mode 100644
index 0000000..a81dceb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/openoffice1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/opera.svgz b/IconThemes/mono/scalable/apps/opera.svgz
new file mode 100644
index 0000000..31e4c3d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/opera.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package.svgz b/IconThemes/mono/scalable/apps/package.svgz
new file mode 100644
index 0000000..4deb321
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_application.svgz b/IconThemes/mono/scalable/apps/package_application.svgz
new file mode 100644
index 0000000..e8fb5d4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_application.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_applications.svgz b/IconThemes/mono/scalable/apps/package_applications.svgz
new file mode 100644
index 0000000..e172a3b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_applications.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_development.svgz b/IconThemes/mono/scalable/apps/package_development.svgz
new file mode 100644
index 0000000..567e2fa
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_development.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_editors.svgz b/IconThemes/mono/scalable/apps/package_editors.svgz
new file mode 100644
index 0000000..450f388
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_editors.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_edutainment.svgz b/IconThemes/mono/scalable/apps/package_edutainment.svgz
new file mode 100644
index 0000000..54debd0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_edutainment.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_favourite.svgz b/IconThemes/mono/scalable/apps/package_favourite.svgz
new file mode 100644
index 0000000..d28529d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_favourite.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_games.svgz b/IconThemes/mono/scalable/apps/package_games.svgz
new file mode 100644
index 0000000..e2330af
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_games.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_games_arcade.svgz b/IconThemes/mono/scalable/apps/package_games_arcade.svgz
new file mode 100644
index 0000000..90ba297
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_games_arcade.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_games_board.svgz b/IconThemes/mono/scalable/apps/package_games_board.svgz
new file mode 100644
index 0000000..0f14959
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_games_board.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_games_card.svgz b/IconThemes/mono/scalable/apps/package_games_card.svgz
new file mode 100644
index 0000000..d92968c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_games_card.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_games_cards.svgz b/IconThemes/mono/scalable/apps/package_games_cards.svgz
new file mode 100644
index 0000000..cb0f902
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_games_cards.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_games_kids.svgz b/IconThemes/mono/scalable/apps/package_games_kids.svgz
new file mode 100644
index 0000000..cce69c2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_games_kids.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_games_strategy.svgz b/IconThemes/mono/scalable/apps/package_games_strategy.svgz
new file mode 100644
index 0000000..89b65d6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_games_strategy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_graphics.svgz b/IconThemes/mono/scalable/apps/package_graphics.svgz
new file mode 100644
index 0000000..ba6b286
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_graphics.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_multimedia.svgz b/IconThemes/mono/scalable/apps/package_multimedia.svgz
new file mode 100644
index 0000000..584d2c0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_multimedia.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_network.svgz b/IconThemes/mono/scalable/apps/package_network.svgz
new file mode 100644
index 0000000..e5e2ba4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_network.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_settings.svgz b/IconThemes/mono/scalable/apps/package_settings.svgz
new file mode 100644
index 0000000..1679b25
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_settings.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_system.svgz b/IconThemes/mono/scalable/apps/package_system.svgz
new file mode 100644
index 0000000..c3ae313
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_system.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_toys.svgz b/IconThemes/mono/scalable/apps/package_toys.svgz
new file mode 100644
index 0000000..cce69c2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_toys.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_utilities.svgz b/IconThemes/mono/scalable/apps/package_utilities.svgz
new file mode 100644
index 0000000..df8ede0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_utilities.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/package_wordprocessing.svgz b/IconThemes/mono/scalable/apps/package_wordprocessing.svgz
new file mode 100644
index 0000000..bc82bc3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/package_wordprocessing.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/palm-pilot.svgz b/IconThemes/mono/scalable/apps/palm-pilot.svgz
new file mode 100644
index 0000000..f475dc1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/palm-pilot.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/pan.svgz b/IconThemes/mono/scalable/apps/pan.svgz
new file mode 100644
index 0000000..826e5be
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/pan.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/panel.svgz b/IconThemes/mono/scalable/apps/panel.svgz
new file mode 100644
index 0000000..3b08167
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/panel.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/panel_settings.svgz b/IconThemes/mono/scalable/apps/panel_settings.svgz
new file mode 100644
index 0000000..53e62aa
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/panel_settings.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/partitioner.svgz b/IconThemes/mono/scalable/apps/partitioner.svgz
new file mode 100644
index 0000000..fdecbfd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/partitioner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/password.svgz b/IconThemes/mono/scalable/apps/password.svgz
new file mode 100644
index 0000000..28b87c7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/password.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/payee.svgz b/IconThemes/mono/scalable/apps/payee.svgz
new file mode 100644
index 0000000..d2f5abb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/payee.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/pcmcia.svgz b/IconThemes/mono/scalable/apps/pcmcia.svgz
new file mode 100644
index 0000000..73c9f27
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/pcmcia.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/penguin.svgz b/IconThemes/mono/scalable/apps/penguin.svgz
new file mode 100644
index 0000000..0a757f3
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/penguin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/personal.svgz b/IconThemes/mono/scalable/apps/personal.svgz
new file mode 100644
index 0000000..0f23d94
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/personal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/photobook.svgz b/IconThemes/mono/scalable/apps/photobook.svgz
new file mode 100644
index 0000000..d9f75ff
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/photobook.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/phppg.svgz b/IconThemes/mono/scalable/apps/phppg.svgz
new file mode 100644
index 0000000..05a963c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/phppg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/plan.svgz b/IconThemes/mono/scalable/apps/plan.svgz
new file mode 100644
index 0000000..a184580
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/plan.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/planner.svgz b/IconThemes/mono/scalable/apps/planner.svgz
new file mode 100644
index 0000000..f2a92f0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/planner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/playing.svgz b/IconThemes/mono/scalable/apps/playing.svgz
new file mode 100644
index 0000000..debe0ad
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/playing.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/potracegui.svgz b/IconThemes/mono/scalable/apps/potracegui.svgz
new file mode 100644
index 0000000..84d62d5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/potracegui.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/power-management.svgz b/IconThemes/mono/scalable/apps/power-management.svgz
new file mode 100644
index 0000000..f15b7a7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/power-management.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/power-manager.svgz b/IconThemes/mono/scalable/apps/power-manager.svgz
new file mode 100644
index 0000000..b843478
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/power-manager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/powertweak.svgz b/IconThemes/mono/scalable/apps/powertweak.svgz
new file mode 100644
index 0000000..59ffcd7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/powertweak.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/printer.svgz b/IconThemes/mono/scalable/apps/printer.svgz
new file mode 100644
index 0000000..85a69c8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/printer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/printer2.svgz b/IconThemes/mono/scalable/apps/printer2.svgz
new file mode 100644
index 0000000..d6c87f8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/printer2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/printing_section.svgz b/IconThemes/mono/scalable/apps/printing_section.svgz
new file mode 100644
index 0000000..7a92227
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/printing_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/printmgr.svgz b/IconThemes/mono/scalable/apps/printmgr.svgz
new file mode 100644
index 0000000..da4cbdb
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/printmgr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/proxy.svgz b/IconThemes/mono/scalable/apps/proxy.svgz
new file mode 100644
index 0000000..0db4a28
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/proxy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/psi.svgz b/IconThemes/mono/scalable/apps/psi.svgz
new file mode 100644
index 0000000..f5fe312
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/psi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/pwmanager.svgz b/IconThemes/mono/scalable/apps/pwmanager.svgz
new file mode 100644
index 0000000..2423ee4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/pwmanager.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/pybliographic.svgz b/IconThemes/mono/scalable/apps/pybliographic.svgz
new file mode 100644
index 0000000..60dd9ff
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/pybliographic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/pysol.svgz b/IconThemes/mono/scalable/apps/pysol.svgz
new file mode 100644
index 0000000..f6b1797
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/pysol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/qt.svgz b/IconThemes/mono/scalable/apps/qt.svgz
new file mode 100644
index 0000000..10eb214
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/qt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/qtella.svgz b/IconThemes/mono/scalable/apps/qtella.svgz
new file mode 100644
index 0000000..9eabdf9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/qtella.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/quanta.svgz b/IconThemes/mono/scalable/apps/quanta.svgz
new file mode 100644
index 0000000..50a37c5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/quanta.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/quanta_be.svgz b/IconThemes/mono/scalable/apps/quanta_be.svgz
new file mode 100644
index 0000000..82ffb9f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/quanta_be.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/quicktime.svgz b/IconThemes/mono/scalable/apps/quicktime.svgz
new file mode 100644
index 0000000..ab0c015
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/quicktime.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/randr.svgz b/IconThemes/mono/scalable/apps/randr.svgz
new file mode 100644
index 0000000..e948f24
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/randr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/realplay.svgz b/IconThemes/mono/scalable/apps/realplay.svgz
new file mode 100644
index 0000000..977cd52
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/realplay.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/realplayer.svgz b/IconThemes/mono/scalable/apps/realplayer.svgz
new file mode 100644
index 0000000..977cd52
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/realplayer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/relokate.svgz b/IconThemes/mono/scalable/apps/relokate.svgz
new file mode 100644
index 0000000..73e332c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/relokate.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/remote.svgz b/IconThemes/mono/scalable/apps/remote.svgz
new file mode 100644
index 0000000..668a2e0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/remote.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/rsibreak.svgz b/IconThemes/mono/scalable/apps/rsibreak.svgz
new file mode 100644
index 0000000..f25299a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/rsibreak.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/running.svgz b/IconThemes/mono/scalable/apps/running.svgz
new file mode 100644
index 0000000..f7afd0d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/running.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/runprocesscatcher.svgz b/IconThemes/mono/scalable/apps/runprocesscatcher.svgz
new file mode 100644
index 0000000..aaeb1ce
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/runprocesscatcher.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/samba-client.svgz b/IconThemes/mono/scalable/apps/samba-client.svgz
new file mode 100644
index 0000000..7ae8fbd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/samba-client.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/samba-server.svgz b/IconThemes/mono/scalable/apps/samba-server.svgz
new file mode 100644
index 0000000..80e502f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/samba-server.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/samba.svgz b/IconThemes/mono/scalable/apps/samba.svgz
new file mode 100644
index 0000000..07ca309
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/samba.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/samba_client.svgz b/IconThemes/mono/scalable/apps/samba_client.svgz
new file mode 100644
index 0000000..db13bb9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/samba_client.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/samba_server.svgz b/IconThemes/mono/scalable/apps/samba_server.svgz
new file mode 100644
index 0000000..4e5c7c9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/samba_server.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/samba_setup.svgz b/IconThemes/mono/scalable/apps/samba_setup.svgz
new file mode 100644
index 0000000..ebc3986
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/samba_setup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/scanner.svgz b/IconThemes/mono/scalable/apps/scanner.svgz
new file mode 100644
index 0000000..f779bd6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/scanner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/schedule.svgz b/IconThemes/mono/scalable/apps/schedule.svgz
new file mode 100644
index 0000000..d789545
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/schedule.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/screensaver.svgz b/IconThemes/mono/scalable/apps/screensaver.svgz
new file mode 100644
index 0000000..9104c85
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/screensaver.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/scribus.svgz b/IconThemes/mono/scalable/apps/scribus.svgz
new file mode 100644
index 0000000..0935acd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/scribus.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/searchtool.svgz b/IconThemes/mono/scalable/apps/searchtool.svgz
new file mode 100644
index 0000000..6a60842
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/searchtool.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/settings-sound.svgz b/IconThemes/mono/scalable/apps/settings-sound.svgz
new file mode 100644
index 0000000..693036a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/settings-sound.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/shell.svgz b/IconThemes/mono/scalable/apps/shell.svgz
new file mode 100644
index 0000000..de8a624
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/shell.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/shells_section.svgz b/IconThemes/mono/scalable/apps/shells_section.svgz
new file mode 100644
index 0000000..1e43791
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/shells_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/showfoto.svgz b/IconThemes/mono/scalable/apps/showfoto.svgz
new file mode 100644
index 0000000..d9f75ff
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/showfoto.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/showimg.svgz b/IconThemes/mono/scalable/apps/showimg.svgz
new file mode 100644
index 0000000..69010d8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/showimg.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/shredder.svgz b/IconThemes/mono/scalable/apps/shredder.svgz
new file mode 100644
index 0000000..acf4b61
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/shredder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/sim.svgz b/IconThemes/mono/scalable/apps/sim.svgz
new file mode 100644
index 0000000..02a8cf9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/sim.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/slp.svgz b/IconThemes/mono/scalable/apps/slp.svgz
new file mode 100644
index 0000000..86789e9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/slp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/smb4k.svgz b/IconThemes/mono/scalable/apps/smb4k.svgz
new file mode 100644
index 0000000..61f8d5b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/smb4k.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/sms_protocol.svgz b/IconThemes/mono/scalable/apps/sms_protocol.svgz
new file mode 100644
index 0000000..a067173
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/sms_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/sodipodi.svgz b/IconThemes/mono/scalable/apps/sodipodi.svgz
new file mode 100644
index 0000000..73e8127
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/sodipodi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/soffice.svgz b/IconThemes/mono/scalable/apps/soffice.svgz
new file mode 100644
index 0000000..41d53b8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/soffice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/software.svgz b/IconThemes/mono/scalable/apps/software.svgz
new file mode 100644
index 0000000..4a1b35d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/software.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/software2.svgz b/IconThemes/mono/scalable/apps/software2.svgz
new file mode 100644
index 0000000..c5fcad0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/software2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/soulseek.svgz b/IconThemes/mono/scalable/apps/soulseek.svgz
new file mode 100644
index 0000000..468849a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/soulseek.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/soundcard.svgz b/IconThemes/mono/scalable/apps/soundcard.svgz
new file mode 100644
index 0000000..0f73fbf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/soundcard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/source.svgz b/IconThemes/mono/scalable/apps/source.svgz
new file mode 100644
index 0000000..572fab8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/source.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/staroffice.svgz b/IconThemes/mono/scalable/apps/staroffice.svgz
new file mode 100644
index 0000000..8ff0ccd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/staroffice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/style.svgz b/IconThemes/mono/scalable/apps/style.svgz
new file mode 100644
index 0000000..15d23f6
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/style.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/stylesheet.svgz b/IconThemes/mono/scalable/apps/stylesheet.svgz
new file mode 100644
index 0000000..9067cc7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/stylesheet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/superkaramba.svgz b/IconThemes/mono/scalable/apps/superkaramba.svgz
new file mode 100644
index 0000000..10483de
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/superkaramba.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/support.svgz b/IconThemes/mono/scalable/apps/support.svgz
new file mode 100644
index 0000000..04a2b89
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/support.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/suse.svgz b/IconThemes/mono/scalable/apps/suse.svgz
new file mode 100644
index 0000000..2c4a8b2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/suse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/synaescope.svgz b/IconThemes/mono/scalable/apps/synaescope.svgz
new file mode 100644
index 0000000..7767536
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/synaescope.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/synaptic.svgz b/IconThemes/mono/scalable/apps/synaptic.svgz
new file mode 100644
index 0000000..d89607f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/synaptic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/sysadmin.svgz b/IconThemes/mono/scalable/apps/sysadmin.svgz
new file mode 100644
index 0000000..d6aaf32
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/sysadmin.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/system-floppy.svgz b/IconThemes/mono/scalable/apps/system-floppy.svgz
new file mode 100644
index 0000000..f1d597b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/system-floppy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/system.svgz b/IconThemes/mono/scalable/apps/system.svgz
new file mode 100644
index 0000000..2853585
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/system.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/systemprotocol.svgz b/IconThemes/mono/scalable/apps/systemprotocol.svgz
new file mode 100644
index 0000000..c3be6ee
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/systemprotocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/systemsettings.svgz b/IconThemes/mono/scalable/apps/systemsettings.svgz
new file mode 100644
index 0000000..4e63e95
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/systemsettings.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/systemtray.svgz b/IconThemes/mono/scalable/apps/systemtray.svgz
new file mode 100644
index 0000000..829b8d1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/systemtray.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/taskbar.svgz b/IconThemes/mono/scalable/apps/taskbar.svgz
new file mode 100644
index 0000000..147bcaa
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/taskbar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/tdsl.svgz b/IconThemes/mono/scalable/apps/tdsl.svgz
new file mode 100644
index 0000000..7681727
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/tdsl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/tellico.svgz b/IconThemes/mono/scalable/apps/tellico.svgz
new file mode 100644
index 0000000..1f87d12
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/tellico.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/telnet.svgz b/IconThemes/mono/scalable/apps/telnet.svgz
new file mode 100644
index 0000000..f634ce4
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/telnet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/terminal.svgz b/IconThemes/mono/scalable/apps/terminal.svgz
new file mode 100644
index 0000000..86da98f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/terminal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/terminals_section.svgz b/IconThemes/mono/scalable/apps/terminals_section.svgz
new file mode 100644
index 0000000..356002d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/terminals_section.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/thunderbird.svgz b/IconThemes/mono/scalable/apps/thunderbird.svgz
new file mode 100644
index 0000000..e1a5f9a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/thunderbird.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/timezone.svgz b/IconThemes/mono/scalable/apps/timezone.svgz
new file mode 100644
index 0000000..7f222fa
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/timezone.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/timezone2.svgz b/IconThemes/mono/scalable/apps/timezone2.svgz
new file mode 100644
index 0000000..acb602f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/timezone2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/tux.svgz b/IconThemes/mono/scalable/apps/tux.svgz
new file mode 100644
index 0000000..961bb0e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/tux.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/tv.svgz b/IconThemes/mono/scalable/apps/tv.svgz
new file mode 100644
index 0000000..bafd923
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/tv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/tvtime.svgz b/IconThemes/mono/scalable/apps/tvtime.svgz
new file mode 100644
index 0000000..bafd923
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/tvtime.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/umbrello.svgz b/IconThemes/mono/scalable/apps/umbrello.svgz
new file mode 100644
index 0000000..c4a5216
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/umbrello.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/unknownapp.svgz b/IconThemes/mono/scalable/apps/unknownapp.svgz
new file mode 100644
index 0000000..cf6bae8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/unknownapp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/usb.svgz b/IconThemes/mono/scalable/apps/usb.svgz
new file mode 100644
index 0000000..6ec28a1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/usb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/user-info.svgz b/IconThemes/mono/scalable/apps/user-info.svgz
new file mode 100644
index 0000000..a4e4d0c
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/user-info.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/userconfig.svgz b/IconThemes/mono/scalable/apps/userconfig.svgz
new file mode 100644
index 0000000..c9cd38b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/userconfig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/visor.svgz b/IconThemes/mono/scalable/apps/visor.svgz
new file mode 100644
index 0000000..f475dc1
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/visor.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/vnc.svgz b/IconThemes/mono/scalable/apps/vnc.svgz
new file mode 100644
index 0000000..6c018f0
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/vnc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/wabi.svgz b/IconThemes/mono/scalable/apps/wabi.svgz
new file mode 100644
index 0000000..24143b9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/wabi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/waiting.svgz b/IconThemes/mono/scalable/apps/waiting.svgz
new file mode 100644
index 0000000..d705064
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/waiting.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/wallpaper.svgz b/IconThemes/mono/scalable/apps/wallpaper.svgz
new file mode 100644
index 0000000..4f49380
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/wallpaper.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/warning.svgz b/IconThemes/mono/scalable/apps/warning.svgz
new file mode 100644
index 0000000..c1f9cc8
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/warning.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/web-browser.svgz b/IconThemes/mono/scalable/apps/web-browser.svgz
new file mode 100644
index 0000000..5d6442a
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/web-browser.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/wilber.svgz b/IconThemes/mono/scalable/apps/wilber.svgz
new file mode 100644
index 0000000..721f6bf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/wilber.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/win_apps.svgz b/IconThemes/mono/scalable/apps/win_apps.svgz
new file mode 100644
index 0000000..1ead60d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/win_apps.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/window-capplet.svgz b/IconThemes/mono/scalable/apps/window-capplet.svgz
new file mode 100644
index 0000000..0ee7cee
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/window-capplet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/window_list.svgz b/IconThemes/mono/scalable/apps/window_list.svgz
new file mode 100644
index 0000000..d51f7e9
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/window_list.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/wine.svgz b/IconThemes/mono/scalable/apps/wine.svgz
new file mode 100644
index 0000000..5bcb81d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/wine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/wineconfig.svgz b/IconThemes/mono/scalable/apps/wineconfig.svgz
new file mode 100644
index 0000000..5bcb81d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/wineconfig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/winprops.svgz b/IconThemes/mono/scalable/apps/winprops.svgz
new file mode 100644
index 0000000..05098b7
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/winprops.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/wmaker_apps.svgz b/IconThemes/mono/scalable/apps/wmaker_apps.svgz
new file mode 100644
index 0000000..36e64a2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/wmaker_apps.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/wp.svgz b/IconThemes/mono/scalable/apps/wp.svgz
new file mode 100644
index 0000000..525b981
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/wp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/www.svgz b/IconThemes/mono/scalable/apps/www.svgz
new file mode 100644
index 0000000..c35d303
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/www.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/x.svgz b/IconThemes/mono/scalable/apps/x.svgz
new file mode 100644
index 0000000..13a9e72
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/x.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/x11.svgz b/IconThemes/mono/scalable/apps/x11.svgz
new file mode 100644
index 0000000..47d38cf
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/x11.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xapp.svgz b/IconThemes/mono/scalable/apps/xapp.svgz
new file mode 100644
index 0000000..86bf953
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xapp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xawtv.svgz b/IconThemes/mono/scalable/apps/xawtv.svgz
new file mode 100644
index 0000000..bafd923
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xawtv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xcalc.svgz b/IconThemes/mono/scalable/apps/xcalc.svgz
new file mode 100644
index 0000000..349bd20
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xcalc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xcdroast.svgz b/IconThemes/mono/scalable/apps/xcdroast.svgz
new file mode 100644
index 0000000..f2e270e
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xcdroast.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xchat.svgz b/IconThemes/mono/scalable/apps/xchat.svgz
new file mode 100644
index 0000000..a900d96
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xchat.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xclipboard.svgz b/IconThemes/mono/scalable/apps/xclipboard.svgz
new file mode 100644
index 0000000..09b3ffd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xclipboard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xclock.svgz b/IconThemes/mono/scalable/apps/xclock.svgz
new file mode 100644
index 0000000..1a57f23
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xclock.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xconsole.svgz b/IconThemes/mono/scalable/apps/xconsole.svgz
new file mode 100644
index 0000000..e000e90
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xconsole.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xedit.svgz b/IconThemes/mono/scalable/apps/xedit.svgz
new file mode 100644
index 0000000..3329436
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xedit.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xemacs.svgz b/IconThemes/mono/scalable/apps/xemacs.svgz
new file mode 100644
index 0000000..bcba462
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xemacs.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xeyes.svgz b/IconThemes/mono/scalable/apps/xeyes.svgz
new file mode 100644
index 0000000..8a6a065
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xeyes.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xfig.svgz b/IconThemes/mono/scalable/apps/xfig.svgz
new file mode 100644
index 0000000..c500638
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xfig.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xfmail.svgz b/IconThemes/mono/scalable/apps/xfmail.svgz
new file mode 100644
index 0000000..6eee046
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xfmail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xine.svgz b/IconThemes/mono/scalable/apps/xine.svgz
new file mode 100644
index 0000000..970082f
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xload.svgz b/IconThemes/mono/scalable/apps/xload.svgz
new file mode 100644
index 0000000..1147212
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xload.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xmag.svgz b/IconThemes/mono/scalable/apps/xmag.svgz
new file mode 100644
index 0000000..f68ec6b
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xmag.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xmms.svgz b/IconThemes/mono/scalable/apps/xmms.svgz
new file mode 100644
index 0000000..9641478
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xmms.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xosview.svgz b/IconThemes/mono/scalable/apps/xosview.svgz
new file mode 100644
index 0000000..a5d91fd
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xosview.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xpaint.svgz b/IconThemes/mono/scalable/apps/xpaint.svgz
new file mode 100644
index 0000000..2bfc4c2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xpaint.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xsane.svgz b/IconThemes/mono/scalable/apps/xsane.svgz
new file mode 100644
index 0000000..0200e3d
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xsane.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xterm-terminal.svgz b/IconThemes/mono/scalable/apps/xterm-terminal.svgz
new file mode 100644
index 0000000..271e262
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xterm-terminal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/xv.svgz b/IconThemes/mono/scalable/apps/xv.svgz
new file mode 100644
index 0000000..f14c7f5
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/xv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/yahoo_protocol.svgz b/IconThemes/mono/scalable/apps/yahoo_protocol.svgz
new file mode 100644
index 0000000..e277a08
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/yahoo_protocol.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/yakuake.svgz b/IconThemes/mono/scalable/apps/yakuake.svgz
new file mode 100644
index 0000000..2f505f2
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/yakuake.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/apps/zip.svgz b/IconThemes/mono/scalable/apps/zip.svgz
new file mode 100644
index 0000000..51efa19
--- /dev/null
+++ b/IconThemes/mono/scalable/apps/zip.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/3floppy_mount.svgz b/IconThemes/mono/scalable/devices/3floppy_mount.svgz
new file mode 100644
index 0000000..d443554
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/3floppy_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/3floppy_unmount.svgz b/IconThemes/mono/scalable/devices/3floppy_unmount.svgz
new file mode 100644
index 0000000..c634a26
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/3floppy_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/5floppy_mount.svgz b/IconThemes/mono/scalable/devices/5floppy_mount.svgz
new file mode 100644
index 0000000..ac3fad8
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/5floppy_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/5floppy_unmount.svgz b/IconThemes/mono/scalable/devices/5floppy_unmount.svgz
new file mode 100644
index 0000000..f1cee5a
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/5floppy_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/blockdevice.svgz b/IconThemes/mono/scalable/devices/blockdevice.svgz
new file mode 100644
index 0000000..1409608
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/blockdevice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/cam.svgz b/IconThemes/mono/scalable/devices/cam.svgz
new file mode 100644
index 0000000..e0f0be3
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/cam.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/camera.svgz b/IconThemes/mono/scalable/devices/camera.svgz
new file mode 100644
index 0000000..638b9e5
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/camera.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/camera_mount.svgz b/IconThemes/mono/scalable/devices/camera_mount.svgz
new file mode 100644
index 0000000..5e978d3
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/camera_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/camera_unmount.svgz b/IconThemes/mono/scalable/devices/camera_unmount.svgz
new file mode 100644
index 0000000..2d96759
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/camera_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/cdaudio_mount.svgz b/IconThemes/mono/scalable/devices/cdaudio_mount.svgz
new file mode 100644
index 0000000..fbf1f3e
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/cdaudio_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/cdaudio_unmount.svgz b/IconThemes/mono/scalable/devices/cdaudio_unmount.svgz
new file mode 100644
index 0000000..18805d5
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/cdaudio_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/cdrom_audio.svgz b/IconThemes/mono/scalable/devices/cdrom_audio.svgz
new file mode 100644
index 0000000..63e616c
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/cdrom_audio.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/cdrom_mount.svgz b/IconThemes/mono/scalable/devices/cdrom_mount.svgz
new file mode 100644
index 0000000..87f0831
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/cdrom_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/cdrom_unmount.svgz b/IconThemes/mono/scalable/devices/cdrom_unmount.svgz
new file mode 100644
index 0000000..0debe88
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/cdrom_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/cdwriter_mount.svgz b/IconThemes/mono/scalable/devices/cdwriter_mount.svgz
new file mode 100644
index 0000000..b579595
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/cdwriter_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/cdwriter_unmount.svgz b/IconThemes/mono/scalable/devices/cdwriter_unmount.svgz
new file mode 100644
index 0000000..5bbbd23
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/cdwriter_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/chardevice.svgz b/IconThemes/mono/scalable/devices/chardevice.svgz
new file mode 100644
index 0000000..39fadfb
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/chardevice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/compact_flash_mount.svgz b/IconThemes/mono/scalable/devices/compact_flash_mount.svgz
new file mode 100644
index 0000000..0e23cd2
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/compact_flash_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/compact_flash_unmount.svgz b/IconThemes/mono/scalable/devices/compact_flash_unmount.svgz
new file mode 100644
index 0000000..71c7ce1
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/compact_flash_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/dvd_mount.svgz b/IconThemes/mono/scalable/devices/dvd_mount.svgz
new file mode 100644
index 0000000..2c67979
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/dvd_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/dvd_unmount.svgz b/IconThemes/mono/scalable/devices/dvd_unmount.svgz
new file mode 100644
index 0000000..8ca747f
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/dvd_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/firewire_mount.svgz b/IconThemes/mono/scalable/devices/firewire_mount.svgz
new file mode 100644
index 0000000..29bfa9d
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/firewire_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/firewire_unmount.svgz b/IconThemes/mono/scalable/devices/firewire_unmount.svgz
new file mode 100644
index 0000000..657f4b8
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/firewire_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/handheld.svgz b/IconThemes/mono/scalable/devices/handheld.svgz
new file mode 100644
index 0000000..f475dc1
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/handheld.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/hdd_mount.svgz b/IconThemes/mono/scalable/devices/hdd_mount.svgz
new file mode 100644
index 0000000..8f28ef9
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/hdd_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/hdd_unmount.svgz b/IconThemes/mono/scalable/devices/hdd_unmount.svgz
new file mode 100644
index 0000000..65a66b2
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/hdd_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/hdd_usb.svgz b/IconThemes/mono/scalable/devices/hdd_usb.svgz
new file mode 100644
index 0000000..7aa6fb2
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/hdd_usb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/hdd_win_mount.svgz b/IconThemes/mono/scalable/devices/hdd_win_mount.svgz
new file mode 100644
index 0000000..446e05c
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/hdd_win_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/hdd_win_unmount.svgz b/IconThemes/mono/scalable/devices/hdd_win_unmount.svgz
new file mode 100644
index 0000000..0336dc2
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/hdd_win_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/ipod_mount.svgz b/IconThemes/mono/scalable/devices/ipod_mount.svgz
new file mode 100644
index 0000000..1a8161e
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/ipod_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/ipod_unmount.svgz b/IconThemes/mono/scalable/devices/ipod_unmount.svgz
new file mode 100644
index 0000000..a7267ad
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/ipod_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/joystick.svgz b/IconThemes/mono/scalable/devices/joystick.svgz
new file mode 100644
index 0000000..32e051c
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/joystick.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/ksim_cpu.svgz b/IconThemes/mono/scalable/devices/ksim_cpu.svgz
new file mode 100644
index 0000000..293401d
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/ksim_cpu.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/kxkb.svgz b/IconThemes/mono/scalable/devices/kxkb.svgz
new file mode 100644
index 0000000..df37f42
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/kxkb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/laptop.svgz b/IconThemes/mono/scalable/devices/laptop.svgz
new file mode 100644
index 0000000..5a8c3e7
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/laptop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/linux_hdd_mount.svgz b/IconThemes/mono/scalable/devices/linux_hdd_mount.svgz
new file mode 100644
index 0000000..1eb5a5f
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/linux_hdd_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/linux_hdd_unmount.svgz b/IconThemes/mono/scalable/devices/linux_hdd_unmount.svgz
new file mode 100644
index 0000000..05cb203
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/linux_hdd_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/memory.svgz b/IconThemes/mono/scalable/devices/memory.svgz
new file mode 100644
index 0000000..840d1b2
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/memory.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/memory_stick_mount.svgz b/IconThemes/mono/scalable/devices/memory_stick_mount.svgz
new file mode 100644
index 0000000..9825783
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/memory_stick_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/memory_stick_unmount.svgz b/IconThemes/mono/scalable/devices/memory_stick_unmount.svgz
new file mode 100644
index 0000000..33d316b
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/memory_stick_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/mo_mount.svgz b/IconThemes/mono/scalable/devices/mo_mount.svgz
new file mode 100644
index 0000000..b73976c
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/mo_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/mo_unmount.svgz b/IconThemes/mono/scalable/devices/mo_unmount.svgz
new file mode 100644
index 0000000..8ee46a5
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/mo_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/modem.svgz b/IconThemes/mono/scalable/devices/modem.svgz
new file mode 100644
index 0000000..6017a39
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/modem.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/mouse.svgz b/IconThemes/mono/scalable/devices/mouse.svgz
new file mode 100644
index 0000000..6f899e3
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/mouse.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/nfs_mount.svgz b/IconThemes/mono/scalable/devices/nfs_mount.svgz
new file mode 100644
index 0000000..0e0820b
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/nfs_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/nfs_unmount.svgz b/IconThemes/mono/scalable/devices/nfs_unmount.svgz
new file mode 100644
index 0000000..acf70e5
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/nfs_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/pda.svgz b/IconThemes/mono/scalable/devices/pda.svgz
new file mode 100644
index 0000000..f475dc1
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/pda.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/pda_black.svgz b/IconThemes/mono/scalable/devices/pda_black.svgz
new file mode 100644
index 0000000..f475dc1
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/pda_black.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/pda_blue.svgz b/IconThemes/mono/scalable/devices/pda_blue.svgz
new file mode 100644
index 0000000..f475dc1
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/pda_blue.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/print_class.svgz b/IconThemes/mono/scalable/devices/print_class.svgz
new file mode 100644
index 0000000..50af2f5
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/print_class.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/print_printer.svgz b/IconThemes/mono/scalable/devices/print_printer.svgz
new file mode 100644
index 0000000..366de36
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/print_printer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/printer1.svgz b/IconThemes/mono/scalable/devices/printer1.svgz
new file mode 100644
index 0000000..d4032e7
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/printer1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/printer2.svgz b/IconThemes/mono/scalable/devices/printer2.svgz
new file mode 100644
index 0000000..d6c87f8
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/printer2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/scanner.svgz b/IconThemes/mono/scalable/devices/scanner.svgz
new file mode 100644
index 0000000..f779bd6
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/scanner.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/sd_mmc_mount.svgz b/IconThemes/mono/scalable/devices/sd_mmc_mount.svgz
new file mode 100644
index 0000000..603812a
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/sd_mmc_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/sd_mmc_unmount.svgz b/IconThemes/mono/scalable/devices/sd_mmc_unmount.svgz
new file mode 100644
index 0000000..c031e50
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/sd_mmc_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/smart_media_mount.svgz b/IconThemes/mono/scalable/devices/smart_media_mount.svgz
new file mode 100644
index 0000000..14aece0
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/smart_media_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/smart_media_unmount.svgz b/IconThemes/mono/scalable/devices/smart_media_unmount.svgz
new file mode 100644
index 0000000..7a79c7c
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/smart_media_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/system.svgz b/IconThemes/mono/scalable/devices/system.svgz
new file mode 100644
index 0000000..d4d76de
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/system.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/tablet.svgz b/IconThemes/mono/scalable/devices/tablet.svgz
new file mode 100644
index 0000000..9dedfd7
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/tablet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/tv.svgz b/IconThemes/mono/scalable/devices/tv.svgz
new file mode 100644
index 0000000..bafd923
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/tv.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/usb_mount.svgz b/IconThemes/mono/scalable/devices/usb_mount.svgz
new file mode 100644
index 0000000..09bf9ba
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/usb_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/usb_unmount.svgz b/IconThemes/mono/scalable/devices/usb_unmount.svgz
new file mode 100644
index 0000000..ae5ebf9
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/usb_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/usbdisk_mount.svgz b/IconThemes/mono/scalable/devices/usbdisk_mount.svgz
new file mode 100644
index 0000000..e181bae
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/usbdisk_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/usbdisk_unmount.svgz b/IconThemes/mono/scalable/devices/usbdisk_unmount.svgz
new file mode 100644
index 0000000..fcb062a
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/usbdisk_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/usbpendrive_mount.svgz b/IconThemes/mono/scalable/devices/usbpendrive_mount.svgz
new file mode 100644
index 0000000..111665e
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/usbpendrive_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/usbpendrive_unmount.svgz b/IconThemes/mono/scalable/devices/usbpendrive_unmount.svgz
new file mode 100644
index 0000000..abd9866
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/usbpendrive_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/zip_external_mount.svgz b/IconThemes/mono/scalable/devices/zip_external_mount.svgz
new file mode 100644
index 0000000..c897342
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/zip_external_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/zip_external_unmount.svgz b/IconThemes/mono/scalable/devices/zip_external_unmount.svgz
new file mode 100644
index 0000000..898fa69
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/zip_external_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/zip_mount.svgz b/IconThemes/mono/scalable/devices/zip_mount.svgz
new file mode 100644
index 0000000..d325ef8
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/zip_mount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/devices/zip_unmount.svgz b/IconThemes/mono/scalable/devices/zip_unmount.svgz
new file mode 100644
index 0000000..1c2ce97
--- /dev/null
+++ b/IconThemes/mono/scalable/devices/zip_unmount.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/blockdevice.svgz b/IconThemes/mono/scalable/filesystems/blockdevice.svgz
new file mode 100644
index 0000000..1409608
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/blockdevice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/camera.svgz b/IconThemes/mono/scalable/filesystems/camera.svgz
new file mode 100644
index 0000000..638b9e5
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/camera.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/chardevice.svgz b/IconThemes/mono/scalable/filesystems/chardevice.svgz
new file mode 100644
index 0000000..6ddd3d0
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/chardevice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/connect_to_network.svgz b/IconThemes/mono/scalable/filesystems/connect_to_network.svgz
new file mode 100644
index 0000000..2599a1b
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/connect_to_network.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/desktop.svgz b/IconThemes/mono/scalable/filesystems/desktop.svgz
new file mode 100644
index 0000000..68d9b6c
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/desktop.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/exec.svgz b/IconThemes/mono/scalable/filesystems/exec.svgz
new file mode 100644
index 0000000..954c5f4
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/exec.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/exec_wine.svgz b/IconThemes/mono/scalable/filesystems/exec_wine.svgz
new file mode 100644
index 0000000..d3575de
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/exec_wine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/file_broken.svgz b/IconThemes/mono/scalable/filesystems/file_broken.svgz
new file mode 100644
index 0000000..bad86ec
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/file_broken.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/file_important.svgz b/IconThemes/mono/scalable/filesystems/file_important.svgz
new file mode 100644
index 0000000..b2d92f1
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/file_important.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/file_locked.svgz b/IconThemes/mono/scalable/filesystems/file_locked.svgz
new file mode 100644
index 0000000..910096c
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/file_locked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/file_temporary.svgz b/IconThemes/mono/scalable/filesystems/file_temporary.svgz
new file mode 100644
index 0000000..9fb7ab6
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/file_temporary.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder.svgz b/IconThemes/mono/scalable/filesystems/folder.svgz
new file mode 100644
index 0000000..f3171e9
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_apollon.svgz b/IconThemes/mono/scalable/filesystems/folder_apollon.svgz
new file mode 100644
index 0000000..fb667f8
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_apollon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_binary.svgz b/IconThemes/mono/scalable/filesystems/folder_binary.svgz
new file mode 100644
index 0000000..776d4c2
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_binary.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_bomb.svgz b/IconThemes/mono/scalable/filesystems/folder_bomb.svgz
new file mode 100644
index 0000000..5fa5f82
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_bomb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_cd.svgz b/IconThemes/mono/scalable/filesystems/folder_cd.svgz
new file mode 100644
index 0000000..e4b44f4
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_cd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_crystal.svgz b/IconThemes/mono/scalable/filesystems/folder_crystal.svgz
new file mode 100644
index 0000000..71d38ab
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_crystal.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_cyan.svgz b/IconThemes/mono/scalable/filesystems/folder_cyan.svgz
new file mode 100644
index 0000000..8cc8c01
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_cyan.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_cyan_open.svgz b/IconThemes/mono/scalable/filesystems/folder_cyan_open.svgz
new file mode 100644
index 0000000..f26e451
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_cyan_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_deb.svgz b/IconThemes/mono/scalable/filesystems/folder_deb.svgz
new file mode 100644
index 0000000..eb0d9fc
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_deb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_documents.svgz b/IconThemes/mono/scalable/filesystems/folder_documents.svgz
new file mode 100644
index 0000000..03b117b
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_documents.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_download.svgz b/IconThemes/mono/scalable/filesystems/folder_download.svgz
new file mode 100644
index 0000000..c2ad170
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_download.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_favorite.svgz b/IconThemes/mono/scalable/filesystems/folder_favorite.svgz
new file mode 100644
index 0000000..53b2c72
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_favorite.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_fonts.svgz b/IconThemes/mono/scalable/filesystems/folder_fonts.svgz
new file mode 100644
index 0000000..1593f62
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_fonts.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_games.svgz b/IconThemes/mono/scalable/filesystems/folder_games.svgz
new file mode 100644
index 0000000..5328dfe
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_games.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_green.svgz b/IconThemes/mono/scalable/filesystems/folder_green.svgz
new file mode 100644
index 0000000..6115ea5
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_green.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_green_open.svgz b/IconThemes/mono/scalable/filesystems/folder_green_open.svgz
new file mode 100644
index 0000000..a217e44
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_green_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_grey.svgz b/IconThemes/mono/scalable/filesystems/folder_grey.svgz
new file mode 100644
index 0000000..ae76ecc
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_grey.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_grey_open.svgz b/IconThemes/mono/scalable/filesystems/folder_grey_open.svgz
new file mode 100644
index 0000000..e83b06f
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_grey_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_home.svgz b/IconThemes/mono/scalable/filesystems/folder_home.svgz
new file mode 100644
index 0000000..fedfdac
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_home.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_home2.svgz b/IconThemes/mono/scalable/filesystems/folder_home2.svgz
new file mode 100644
index 0000000..8ea7ff6
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_home2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_html.svgz b/IconThemes/mono/scalable/filesystems/folder_html.svgz
new file mode 100644
index 0000000..b35b411
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_html.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_image.svgz b/IconThemes/mono/scalable/filesystems/folder_image.svgz
new file mode 100644
index 0000000..3c9cca8
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_image.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_important.svgz b/IconThemes/mono/scalable/filesystems/folder_important.svgz
new file mode 100644
index 0000000..592faec
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_important.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_inbox.svgz b/IconThemes/mono/scalable/filesystems/folder_inbox.svgz
new file mode 100644
index 0000000..acadecb
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_inbox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_locked.svgz b/IconThemes/mono/scalable/filesystems/folder_locked.svgz
new file mode 100644
index 0000000..be8271e
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_locked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_mail.svgz b/IconThemes/mono/scalable/filesystems/folder_mail.svgz
new file mode 100644
index 0000000..ec2e0ac
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_mail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_man.svgz b/IconThemes/mono/scalable/filesystems/folder_man.svgz
new file mode 100644
index 0000000..5fa5ebb
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_man.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_midi.svgz b/IconThemes/mono/scalable/filesystems/folder_midi.svgz
new file mode 100644
index 0000000..a8cbec8
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_midi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_music.svgz b/IconThemes/mono/scalable/filesystems/folder_music.svgz
new file mode 100644
index 0000000..8006eba
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_music.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_open.svgz b/IconThemes/mono/scalable/filesystems/folder_open.svgz
new file mode 100644
index 0000000..6ef2526
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_orange.svgz b/IconThemes/mono/scalable/filesystems/folder_orange.svgz
new file mode 100644
index 0000000..9ee73c0
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_orange.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_orange_open.svgz b/IconThemes/mono/scalable/filesystems/folder_orange_open.svgz
new file mode 100644
index 0000000..1632a34
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_orange_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_outbox.svgz b/IconThemes/mono/scalable/filesystems/folder_outbox.svgz
new file mode 100644
index 0000000..18ba4aa
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_outbox.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_print.svgz b/IconThemes/mono/scalable/filesystems/folder_print.svgz
new file mode 100644
index 0000000..c5aff11
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_print.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_print2.svgz b/IconThemes/mono/scalable/filesystems/folder_print2.svgz
new file mode 100644
index 0000000..18e5387
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_print2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_red.svgz b/IconThemes/mono/scalable/filesystems/folder_red.svgz
new file mode 100644
index 0000000..24c73f2
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_red.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_red_open.svgz b/IconThemes/mono/scalable/filesystems/folder_red_open.svgz
new file mode 100644
index 0000000..d9bf680
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_red_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_rpm.svgz b/IconThemes/mono/scalable/filesystems/folder_rpm.svgz
new file mode 100644
index 0000000..d21e648
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_rpm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_sent_mail.svgz b/IconThemes/mono/scalable/filesystems/folder_sent_mail.svgz
new file mode 100644
index 0000000..f5259f9
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_sent_mail.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_sound.svgz b/IconThemes/mono/scalable/filesystems/folder_sound.svgz
new file mode 100644
index 0000000..3917ac2
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_sound.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_synch.svgz b/IconThemes/mono/scalable/filesystems/folder_synch.svgz
new file mode 100644
index 0000000..bde9542
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_synch.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_tar.svgz b/IconThemes/mono/scalable/filesystems/folder_tar.svgz
new file mode 100644
index 0000000..9fb991d
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_tar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_txt.svgz b/IconThemes/mono/scalable/filesystems/folder_txt.svgz
new file mode 100644
index 0000000..0481530
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_txt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_video.svgz b/IconThemes/mono/scalable/filesystems/folder_video.svgz
new file mode 100644
index 0000000..91c5309
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_video.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_violet.svgz b/IconThemes/mono/scalable/filesystems/folder_violet.svgz
new file mode 100644
index 0000000..494fcd0
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_violet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_violet_open.svgz b/IconThemes/mono/scalable/filesystems/folder_violet_open.svgz
new file mode 100644
index 0000000..307dff9
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_violet_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_wine.svgz b/IconThemes/mono/scalable/filesystems/folder_wine.svgz
new file mode 100644
index 0000000..dee1c25
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_wine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_yellow.svgz b/IconThemes/mono/scalable/filesystems/folder_yellow.svgz
new file mode 100644
index 0000000..c2e4790
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_yellow.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/folder_yellow_open.svgz b/IconThemes/mono/scalable/filesystems/folder_yellow_open.svgz
new file mode 100644
index 0000000..59fa6ee
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/folder_yellow_open.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/ftp.svgz b/IconThemes/mono/scalable/filesystems/ftp.svgz
new file mode 100644
index 0000000..216ff11
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/ftp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/link_overlay.svgz b/IconThemes/mono/scalable/filesystems/link_overlay.svgz
new file mode 100644
index 0000000..35e117b
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/link_overlay.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/lock_overlay.svgz b/IconThemes/mono/scalable/filesystems/lock_overlay.svgz
new file mode 100644
index 0000000..ee129cd
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/lock_overlay.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/mycomp.svgz b/IconThemes/mono/scalable/filesystems/mycomp.svgz
new file mode 100644
index 0000000..db85f50
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/mycomp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/mycomputer.svgz b/IconThemes/mono/scalable/filesystems/mycomputer.svgz
new file mode 100644
index 0000000..6e2b020
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/mycomputer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/network.svgz b/IconThemes/mono/scalable/filesystems/network.svgz
new file mode 100644
index 0000000..e5e2ba4
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/network.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/network_local.svgz b/IconThemes/mono/scalable/filesystems/network_local.svgz
new file mode 100644
index 0000000..dff08f9
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/network_local.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/pipe.svgz b/IconThemes/mono/scalable/filesystems/pipe.svgz
new file mode 100644
index 0000000..8ba3783
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/pipe.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/server.svgz b/IconThemes/mono/scalable/filesystems/server.svgz
new file mode 100644
index 0000000..905530f
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/server.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/services.svgz b/IconThemes/mono/scalable/filesystems/services.svgz
new file mode 100644
index 0000000..fd5dce0
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/services.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/socket.svgz b/IconThemes/mono/scalable/filesystems/socket.svgz
new file mode 100644
index 0000000..410f74d
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/socket.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/trashcan_empty.svgz b/IconThemes/mono/scalable/filesystems/trashcan_empty.svgz
new file mode 100644
index 0000000..8f10d9f
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/trashcan_empty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/trashcan_full.svgz b/IconThemes/mono/scalable/filesystems/trashcan_full.svgz
new file mode 100644
index 0000000..878e905
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/trashcan_full.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/www.svgz b/IconThemes/mono/scalable/filesystems/www.svgz
new file mode 100644
index 0000000..774f25e
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/www.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/filesystems/zip_overlay.svgz b/IconThemes/mono/scalable/filesystems/zip_overlay.svgz
new file mode 100644
index 0000000..ceed8ca
--- /dev/null
+++ b/IconThemes/mono/scalable/filesystems/zip_overlay.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/applix.svgz b/IconThemes/mono/scalable/mimetypes/applix.svgz
new file mode 100644
index 0000000..7750e4a
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/applix.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/ascii.svgz b/IconThemes/mono/scalable/mimetypes/ascii.svgz
new file mode 100644
index 0000000..ce77aab
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/ascii.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/backup.svgz b/IconThemes/mono/scalable/mimetypes/backup.svgz
new file mode 100644
index 0000000..dae063f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/backup.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/binary.svgz b/IconThemes/mono/scalable/mimetypes/binary.svgz
new file mode 100644
index 0000000..927b792
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/binary.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/blender3d.svgz b/IconThemes/mono/scalable/mimetypes/blender3d.svgz
new file mode 100644
index 0000000..212575f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/blender3d.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/bt.svgz b/IconThemes/mono/scalable/mimetypes/bt.svgz
new file mode 100644
index 0000000..3ca0401
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/bt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/cdbo_list.svgz b/IconThemes/mono/scalable/mimetypes/cdbo_list.svgz
new file mode 100644
index 0000000..4ec0db8
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/cdbo_list.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/cdimage.svgz b/IconThemes/mono/scalable/mimetypes/cdimage.svgz
new file mode 100644
index 0000000..42d7829
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/cdimage.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/cdr.svgz b/IconThemes/mono/scalable/mimetypes/cdr.svgz
new file mode 100644
index 0000000..3174135
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/cdr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/cdtrack.svgz b/IconThemes/mono/scalable/mimetypes/cdtrack.svgz
new file mode 100644
index 0000000..97c0f33
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/cdtrack.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/chart.svgz b/IconThemes/mono/scalable/mimetypes/chart.svgz
new file mode 100644
index 0000000..29a8bf0
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/chart.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/colorscm.svgz b/IconThemes/mono/scalable/mimetypes/colorscm.svgz
new file mode 100644
index 0000000..5ef967b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/colorscm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/colorset.svgz b/IconThemes/mono/scalable/mimetypes/colorset.svgz
new file mode 100644
index 0000000..26d0110
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/colorset.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/configure.svgz b/IconThemes/mono/scalable/mimetypes/configure.svgz
new file mode 100644
index 0000000..21e55cd
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/configure.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/core.svgz b/IconThemes/mono/scalable/mimetypes/core.svgz
new file mode 100644
index 0000000..562479b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/core.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/database.svgz b/IconThemes/mono/scalable/mimetypes/database.svgz
new file mode 100644
index 0000000..16fd523
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/database.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/deb.svgz b/IconThemes/mono/scalable/mimetypes/deb.svgz
new file mode 100644
index 0000000..03d83a3
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/deb.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/djvu.svgz b/IconThemes/mono/scalable/mimetypes/djvu.svgz
new file mode 100644
index 0000000..9715b62
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/djvu.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/document.svgz b/IconThemes/mono/scalable/mimetypes/document.svgz
new file mode 100644
index 0000000..b440178
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/document.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/document2.svgz b/IconThemes/mono/scalable/mimetypes/document2.svgz
new file mode 100644
index 0000000..5e3c540
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/document2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/drawing.svgz b/IconThemes/mono/scalable/mimetypes/drawing.svgz
new file mode 100644
index 0000000..b0f7b2b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/drawing.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/dvi.svgz b/IconThemes/mono/scalable/mimetypes/dvi.svgz
new file mode 100644
index 0000000..85c8200
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/dvi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/empty.svgz b/IconThemes/mono/scalable/mimetypes/empty.svgz
new file mode 100644
index 0000000..380c3e0
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/empty.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/encrypted.svgz b/IconThemes/mono/scalable/mimetypes/encrypted.svgz
new file mode 100644
index 0000000..877b27c
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/encrypted.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/exec_wine.svgz b/IconThemes/mono/scalable/mimetypes/exec_wine.svgz
new file mode 100644
index 0000000..9dc4499
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/exec_wine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/executable.svgz b/IconThemes/mono/scalable/mimetypes/executable.svgz
new file mode 100644
index 0000000..2561128
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/executable.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/file_locked.svgz b/IconThemes/mono/scalable/mimetypes/file_locked.svgz
new file mode 100644
index 0000000..910096c
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/file_locked.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/file_temporary.svgz b/IconThemes/mono/scalable/mimetypes/file_temporary.svgz
new file mode 100644
index 0000000..ed38ef8
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/file_temporary.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/font.svgz b/IconThemes/mono/scalable/mimetypes/font.svgz
new file mode 100644
index 0000000..dd9148c
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/font.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/font_bitmap.svgz b/IconThemes/mono/scalable/mimetypes/font_bitmap.svgz
new file mode 100644
index 0000000..4181f21
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/font_bitmap.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/font_truetype.svgz b/IconThemes/mono/scalable/mimetypes/font_truetype.svgz
new file mode 100644
index 0000000..9467637
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/font_truetype.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/font_type1.svgz b/IconThemes/mono/scalable/mimetypes/font_type1.svgz
new file mode 100644
index 0000000..594edc3
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/font_type1.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/formula.svgz b/IconThemes/mono/scalable/mimetypes/formula.svgz
new file mode 100644
index 0000000..9a0ef9f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/formula.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/gettext.svgz b/IconThemes/mono/scalable/mimetypes/gettext.svgz
new file mode 100644
index 0000000..1ee9835
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/gettext.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/gf.svgz b/IconThemes/mono/scalable/mimetypes/gf.svgz
new file mode 100644
index 0000000..f572ce2
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/gf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/gnome-library.svgz b/IconThemes/mono/scalable/mimetypes/gnome-library.svgz
new file mode 100644
index 0000000..839c4f6
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/gnome-library.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/gnome_app_info.svgz b/IconThemes/mono/scalable/mimetypes/gnome_app_info.svgz
new file mode 100644
index 0000000..37c84be
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/gnome_app_info.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/graphic.svgz b/IconThemes/mono/scalable/mimetypes/graphic.svgz
new file mode 100644
index 0000000..66b4e40
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/graphic.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/html.svgz b/IconThemes/mono/scalable/mimetypes/html.svgz
new file mode 100644
index 0000000..2d401a2
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/html.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/igc.svgz b/IconThemes/mono/scalable/mimetypes/igc.svgz
new file mode 100644
index 0000000..a3aacba
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/igc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/image.svgz b/IconThemes/mono/scalable/mimetypes/image.svgz
new file mode 100644
index 0000000..bd00208
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/image.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/images.svgz b/IconThemes/mono/scalable/mimetypes/images.svgz
new file mode 100644
index 0000000..4c97b08
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/images.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/info.svgz b/IconThemes/mono/scalable/mimetypes/info.svgz
new file mode 100644
index 0000000..d28731d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/info.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/ipod.svgz b/IconThemes/mono/scalable/mimetypes/ipod.svgz
new file mode 100644
index 0000000..66caebf
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/ipod.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/java_jar.svgz b/IconThemes/mono/scalable/mimetypes/java_jar.svgz
new file mode 100644
index 0000000..eb99a52
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/java_jar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/javascript.svgz b/IconThemes/mono/scalable/mimetypes/javascript.svgz
new file mode 100644
index 0000000..51f955a
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/javascript.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/karbon_karbon.svgz b/IconThemes/mono/scalable/mimetypes/karbon_karbon.svgz
new file mode 100644
index 0000000..825be83
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/karbon_karbon.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kchart_chrt.svgz b/IconThemes/mono/scalable/mimetypes/kchart_chrt.svgz
new file mode 100644
index 0000000..c52599f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kchart_chrt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kdevelop_project.svgz b/IconThemes/mono/scalable/mimetypes/kdevelop_project.svgz
new file mode 100644
index 0000000..56a654e
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kdevelop_project.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kexi.svgz b/IconThemes/mono/scalable/mimetypes/kexi.svgz
new file mode 100644
index 0000000..f20a32a
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kexi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kexi_kexi.svgz b/IconThemes/mono/scalable/mimetypes/kexi_kexi.svgz
new file mode 100644
index 0000000..20a2081
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kexi_kexi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kexiproject_shortcut.svgz b/IconThemes/mono/scalable/mimetypes/kexiproject_shortcut.svgz
new file mode 100644
index 0000000..a11b1ae
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kexiproject_shortcut.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kexiproject_sqlite.svgz b/IconThemes/mono/scalable/mimetypes/kexiproject_sqlite.svgz
new file mode 100644
index 0000000..c6cfa3f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kexiproject_sqlite.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kexiproject_sqlite2.svgz b/IconThemes/mono/scalable/mimetypes/kexiproject_sqlite2.svgz
new file mode 100644
index 0000000..36990eb
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kexiproject_sqlite2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kformula_kfo.svgz b/IconThemes/mono/scalable/mimetypes/kformula_kfo.svgz
new file mode 100644
index 0000000..9833cb8
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kformula_kfo.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kget_list.svgz b/IconThemes/mono/scalable/mimetypes/kget_list.svgz
new file mode 100644
index 0000000..f151817
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kget_list.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kig_doc.svgz b/IconThemes/mono/scalable/mimetypes/kig_doc.svgz
new file mode 100644
index 0000000..fcff020
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kig_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kivio_flw.svgz b/IconThemes/mono/scalable/mimetypes/kivio_flw.svgz
new file mode 100644
index 0000000..6de7091
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kivio_flw.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kmultiple.svgz b/IconThemes/mono/scalable/mimetypes/kmultiple.svgz
new file mode 100644
index 0000000..cfed5b8
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kmultiple.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kmy.svgz b/IconThemes/mono/scalable/mimetypes/kmy.svgz
new file mode 100644
index 0000000..f00e300
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kmy.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/koffice.svgz b/IconThemes/mono/scalable/mimetypes/koffice.svgz
new file mode 100644
index 0000000..68ebb6f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/koffice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kopete_emoticons.svgz b/IconThemes/mono/scalable/mimetypes/kopete_emoticons.svgz
new file mode 100644
index 0000000..57bfa1d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kopete_emoticons.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kpovmodeler_doc.svgz b/IconThemes/mono/scalable/mimetypes/kpovmodeler_doc.svgz
new file mode 100644
index 0000000..d3c76e1
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kpovmodeler_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kpresenter_kpr.svgz b/IconThemes/mono/scalable/mimetypes/kpresenter_kpr.svgz
new file mode 100644
index 0000000..78250a6
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kpresenter_kpr.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/krita_kra.svgz b/IconThemes/mono/scalable/mimetypes/krita_kra.svgz
new file mode 100644
index 0000000..66b4e40
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/krita_kra.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kspread_ksp.svgz b/IconThemes/mono/scalable/mimetypes/kspread_ksp.svgz
new file mode 100644
index 0000000..b49042b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kspread_ksp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kugar_kud.svgz b/IconThemes/mono/scalable/mimetypes/kugar_kud.svgz
new file mode 100644
index 0000000..06bad8c
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kugar_kud.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kugardata.svgz b/IconThemes/mono/scalable/mimetypes/kugardata.svgz
new file mode 100644
index 0000000..cca6c97
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kugardata.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kword_kwd.svgz b/IconThemes/mono/scalable/mimetypes/kword_kwd.svgz
new file mode 100644
index 0000000..997809e
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kword_kwd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/kwordquiz_doc.svgz b/IconThemes/mono/scalable/mimetypes/kwordquiz_doc.svgz
new file mode 100644
index 0000000..2909fc4
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/kwordquiz_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/log.svgz b/IconThemes/mono/scalable/mimetypes/log.svgz
new file mode 100644
index 0000000..a591e4d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/log.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/lpl.svgz b/IconThemes/mono/scalable/mimetypes/lpl.svgz
new file mode 100644
index 0000000..118e857
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/lpl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/make.svgz b/IconThemes/mono/scalable/mimetypes/make.svgz
new file mode 100644
index 0000000..2561128
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/make.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/man.svgz b/IconThemes/mono/scalable/mimetypes/man.svgz
new file mode 100644
index 0000000..aa399ae
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/man.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/message.svgz b/IconThemes/mono/scalable/mimetypes/message.svgz
new file mode 100644
index 0000000..b1fa88b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/message.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/metafont.svgz b/IconThemes/mono/scalable/mimetypes/metafont.svgz
new file mode 100644
index 0000000..7783d39
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/metafont.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/midi.svgz b/IconThemes/mono/scalable/mimetypes/midi.svgz
new file mode 100644
index 0000000..5394990
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/midi.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/mime.svgz b/IconThemes/mono/scalable/mimetypes/mime.svgz
new file mode 100644
index 0000000..46c9bf2
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/mime.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/mime_kaffeine.svgz b/IconThemes/mono/scalable/mimetypes/mime_kaffeine.svgz
new file mode 100644
index 0000000..97fd24b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/mime_kaffeine.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/mime_lyx.svgz b/IconThemes/mono/scalable/mimetypes/mime_lyx.svgz
new file mode 100644
index 0000000..dd28305
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/mime_lyx.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/mime_video.svgz b/IconThemes/mono/scalable/mimetypes/mime_video.svgz
new file mode 100644
index 0000000..bb15539
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/mime_video.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/misc.svgz b/IconThemes/mono/scalable/mimetypes/misc.svgz
new file mode 100644
index 0000000..c350489
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/misc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/misc_doc.svgz b/IconThemes/mono/scalable/mimetypes/misc_doc.svgz
new file mode 100644
index 0000000..646d3ee
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/misc_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/moc_src.svgz b/IconThemes/mono/scalable/mimetypes/moc_src.svgz
new file mode 100644
index 0000000..073a23d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/moc_src.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/money.svgz b/IconThemes/mono/scalable/mimetypes/money.svgz
new file mode 100644
index 0000000..ecd1cf4
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/money.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/mozilla_doc.svgz b/IconThemes/mono/scalable/mimetypes/mozilla_doc.svgz
new file mode 100644
index 0000000..deb9281
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/mozilla_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/netscape.svgz b/IconThemes/mono/scalable/mimetypes/netscape.svgz
new file mode 100644
index 0000000..365071e
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/netscape.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/netscape_doc.svgz b/IconThemes/mono/scalable/mimetypes/netscape_doc.svgz
new file mode 100644
index 0000000..b2c3b0f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/netscape_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/news.svgz b/IconThemes/mono/scalable/mimetypes/news.svgz
new file mode 100644
index 0000000..fdaf76a
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/news.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/pdf.svgz b/IconThemes/mono/scalable/mimetypes/pdf.svgz
new file mode 100644
index 0000000..f2d4ab9
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/pdf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/php.svgz b/IconThemes/mono/scalable/mimetypes/php.svgz
new file mode 100644
index 0000000..5e2393a
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/php.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/pk.svgz b/IconThemes/mono/scalable/mimetypes/pk.svgz
new file mode 100644
index 0000000..7e31640
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/pk.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/postscript.svgz b/IconThemes/mono/scalable/mimetypes/postscript.svgz
new file mode 100644
index 0000000..0a467b5
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/postscript.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/presentation.svgz b/IconThemes/mono/scalable/mimetypes/presentation.svgz
new file mode 100644
index 0000000..807bf5f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/presentation.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/printer.svgz b/IconThemes/mono/scalable/mimetypes/printer.svgz
new file mode 100644
index 0000000..86c655e
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/printer.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/psd.svgz b/IconThemes/mono/scalable/mimetypes/psd.svgz
new file mode 100644
index 0000000..c1749fa
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/psd.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/quicktime.svgz b/IconThemes/mono/scalable/mimetypes/quicktime.svgz
new file mode 100644
index 0000000..18fbb13
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/quicktime.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/readme.svgz b/IconThemes/mono/scalable/mimetypes/readme.svgz
new file mode 100644
index 0000000..ed9fa6f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/readme.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/real.svgz b/IconThemes/mono/scalable/mimetypes/real.svgz
new file mode 100644
index 0000000..1866556
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/real.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/real_doc.svgz b/IconThemes/mono/scalable/mimetypes/real_doc.svgz
new file mode 100644
index 0000000..e667a4d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/real_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/recycled.svgz b/IconThemes/mono/scalable/mimetypes/recycled.svgz
new file mode 100644
index 0000000..0324bd2
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/recycled.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/reject.svgz b/IconThemes/mono/scalable/mimetypes/reject.svgz
new file mode 100644
index 0000000..1fab59c
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/reject.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/resource.svgz b/IconThemes/mono/scalable/mimetypes/resource.svgz
new file mode 100644
index 0000000..8afdd5b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/resource.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/rpm.svgz b/IconThemes/mono/scalable/mimetypes/rpm.svgz
new file mode 100644
index 0000000..5d4a32d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/rpm.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/shellscript.svgz b/IconThemes/mono/scalable/mimetypes/shellscript.svgz
new file mode 100644
index 0000000..c0cf649
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/shellscript.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/soffice.svgz b/IconThemes/mono/scalable/mimetypes/soffice.svgz
new file mode 100644
index 0000000..8428598
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/soffice.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/sound.svgz b/IconThemes/mono/scalable/mimetypes/sound.svgz
new file mode 100644
index 0000000..8b666b7
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/sound.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source.svgz b/IconThemes/mono/scalable/mimetypes/source.svgz
new file mode 100644
index 0000000..572fab8
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_c.svgz b/IconThemes/mono/scalable/mimetypes/source_c.svgz
new file mode 100644
index 0000000..f914d5a
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_c.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_cpp.svgz b/IconThemes/mono/scalable/mimetypes/source_cpp.svgz
new file mode 100644
index 0000000..0c74e2f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_cpp.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_f.svgz b/IconThemes/mono/scalable/mimetypes/source_f.svgz
new file mode 100644
index 0000000..633e2c6
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_f.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_h.svgz b/IconThemes/mono/scalable/mimetypes/source_h.svgz
new file mode 100644
index 0000000..7895b09
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_h.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_j.svgz b/IconThemes/mono/scalable/mimetypes/source_j.svgz
new file mode 100644
index 0000000..384ecce
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_j.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_java.svgz b/IconThemes/mono/scalable/mimetypes/source_java.svgz
new file mode 100644
index 0000000..eb99a52
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_java.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_l.svgz b/IconThemes/mono/scalable/mimetypes/source_l.svgz
new file mode 100644
index 0000000..b36b5e1
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_l.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_moc.svgz b/IconThemes/mono/scalable/mimetypes/source_moc.svgz
new file mode 100644
index 0000000..073a23d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_moc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_mono.svgz b/IconThemes/mono/scalable/mimetypes/source_mono.svgz
new file mode 100644
index 0000000..1e4a3b6
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_mono.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_o.svgz b/IconThemes/mono/scalable/mimetypes/source_o.svgz
new file mode 100644
index 0000000..35b0c85
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_o.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_p.svgz b/IconThemes/mono/scalable/mimetypes/source_p.svgz
new file mode 100644
index 0000000..61e76b8
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_p.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_php.svgz b/IconThemes/mono/scalable/mimetypes/source_php.svgz
new file mode 100644
index 0000000..5e2393a
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_php.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_pl.svgz b/IconThemes/mono/scalable/mimetypes/source_pl.svgz
new file mode 100644
index 0000000..8e51ec4
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_pl.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_py.svgz b/IconThemes/mono/scalable/mimetypes/source_py.svgz
new file mode 100644
index 0000000..598db95
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_py.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_s.svgz b/IconThemes/mono/scalable/mimetypes/source_s.svgz
new file mode 100644
index 0000000..c229d72
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_s.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_xml.svgz b/IconThemes/mono/scalable/mimetypes/source_xml.svgz
new file mode 100644
index 0000000..126b714
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_xml.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/source_y.svgz b/IconThemes/mono/scalable/mimetypes/source_y.svgz
new file mode 100644
index 0000000..5eb2d57
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/source_y.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/spreadsheet.svgz b/IconThemes/mono/scalable/mimetypes/spreadsheet.svgz
new file mode 100644
index 0000000..5bf5763
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/spreadsheet.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/sql.svgz b/IconThemes/mono/scalable/mimetypes/sql.svgz
new file mode 100644
index 0000000..f4b2d5b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/sql.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/superkaramba_theme.svgz b/IconThemes/mono/scalable/mimetypes/superkaramba_theme.svgz
new file mode 100644
index 0000000..562479b
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/superkaramba_theme.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/swf.svgz b/IconThemes/mono/scalable/mimetypes/swf.svgz
new file mode 100644
index 0000000..5f85f19
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/swf.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/tar.svgz b/IconThemes/mono/scalable/mimetypes/tar.svgz
new file mode 100644
index 0000000..396d2e9
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/tar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/tellico.svgz b/IconThemes/mono/scalable/mimetypes/tellico.svgz
new file mode 100644
index 0000000..eb885cb
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/tellico.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/template.svgz b/IconThemes/mono/scalable/mimetypes/template.svgz
new file mode 100644
index 0000000..85fe758
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/template.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/template_source.svgz b/IconThemes/mono/scalable/mimetypes/template_source.svgz
new file mode 100644
index 0000000..85fe758
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/template_source.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/tex.svgz b/IconThemes/mono/scalable/mimetypes/tex.svgz
new file mode 100644
index 0000000..0e12b32
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/tex.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/text.svgz b/IconThemes/mono/scalable/mimetypes/text.svgz
new file mode 100644
index 0000000..152112e
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/text.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/tgz.svgz b/IconThemes/mono/scalable/mimetypes/tgz.svgz
new file mode 100644
index 0000000..95c5b43
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/tgz.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/torrent.svgz b/IconThemes/mono/scalable/mimetypes/torrent.svgz
new file mode 100644
index 0000000..3ca0401
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/torrent.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/trash.svgz b/IconThemes/mono/scalable/mimetypes/trash.svgz
new file mode 100644
index 0000000..406325d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/trash.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/txt.svgz b/IconThemes/mono/scalable/mimetypes/txt.svgz
new file mode 100644
index 0000000..4d275d8
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/txt.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/txt2.svgz b/IconThemes/mono/scalable/mimetypes/txt2.svgz
new file mode 100644
index 0000000..61adfc9
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/txt2.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/umbrellofile.svgz b/IconThemes/mono/scalable/mimetypes/umbrellofile.svgz
new file mode 100644
index 0000000..bb4873f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/umbrellofile.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/unknown.svgz b/IconThemes/mono/scalable/mimetypes/unknown.svgz
new file mode 100644
index 0000000..36343f3
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/unknown.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/vcalendar.svgz b/IconThemes/mono/scalable/mimetypes/vcalendar.svgz
new file mode 100644
index 0000000..0d46d69
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/vcalendar.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/vcard.svgz b/IconThemes/mono/scalable/mimetypes/vcard.svgz
new file mode 100644
index 0000000..24b0521
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/vcard.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/vectorgfx.svgz b/IconThemes/mono/scalable/mimetypes/vectorgfx.svgz
new file mode 100644
index 0000000..2970143
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/vectorgfx.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/video.svgz b/IconThemes/mono/scalable/mimetypes/video.svgz
new file mode 100644
index 0000000..bb15539
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/video.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/widget_doc.svgz b/IconThemes/mono/scalable/mimetypes/widget_doc.svgz
new file mode 100644
index 0000000..45f843f
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/widget_doc.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/wordprocessing.svgz b/IconThemes/mono/scalable/mimetypes/wordprocessing.svgz
new file mode 100644
index 0000000..c610971
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/wordprocessing.svgz
Binary files differ
diff --git a/IconThemes/mono/scalable/mimetypes/zip.svgz b/IconThemes/mono/scalable/mimetypes/zip.svgz
new file mode 100644
index 0000000..72e8e4d
--- /dev/null
+++ b/IconThemes/mono/scalable/mimetypes/zip.svgz
Binary files differ
diff --git a/Makefile.am.in b/Makefile.am.in
new file mode 100644
index 0000000..bde0eca
--- /dev/null
+++ b/Makefile.am.in
@@ -0,0 +1,9 @@
+## kdebase/Makefile.am
+## (C) 1997 Stephan Kulow
+
+AUTOMAKE_OPTIONS = foreign 1.6.1
+
+include admin/deps.am
+
+MAINTAINERCLEANFILES = subdirs configure.in acinclude.m4 SUBDIRS
+EXTRA_DIST = admin
diff --git a/Makefile.cvs b/Makefile.cvs
new file mode 100644
index 0000000..d5c4a7b
--- /dev/null
+++ b/Makefile.cvs
@@ -0,0 +1,15 @@
+
+all:
+ @echo "This Makefile is only for the CVS repository"
+ @echo "This will be deleted before making the distribution"
+ @echo ""
+ @if test ! -d admin; then \
+ echo "Please recheckout this module!" ;\
+ echo "for cvs: use checkout once and after that update again" ;\
+ echo "for cvsup: checkout kde-common from cvsup and" ;\
+ echo " link kde-common/admin to ./admin" ;\
+ exit 1 ;\
+ fi
+ $(MAKE) -f admin/Makefile.common cvs
+
+.SILENT:
diff --git a/configure.in.in b/configure.in.in
new file mode 100644
index 0000000..5f790d5
--- /dev/null
+++ b/configure.in.in
@@ -0,0 +1,51 @@
+#MIN_CONFIG(3.2)
+
+AM_INIT_AUTOMAKE(kdeaccessibility,1.0.0)
+KDE_ENABLE_HIDDEN_VISIBILITY
+AC_CHECK_SETENV
+AC_CHECK_UNSETENV
+
+CXXFLAGS="$CXXFLAGS $KDE_DEFAULT_CXXFLAGS"
+
+#AC_CHECK_HEADERS(sys/stropts.h stropts.h)
+
+dnl ================================================================================
+
+dnl See if the latest kspeech.h is installed and if not, compile against
+dnl kttsd/compat directory.
+
+if test "$KTTS_KSPEECH_DIR" = ""; then
+ KDE_CHECK_HEADER(kspeech.h, ktts_have_kspeech_h=yes, ktts_have_kspeech_h=no)
+ have_latest_kspeech=no
+ if test "x$ktts_have_kspeech_h" = xyes; then
+ AC_MSG_CHECKING([whether installed kspeech.h is latest version])
+ ktts_save_cppflags=$CPPFLAGS
+ AC_LANG_SAVE
+ CPPFLAGS="$all_includes $CPPFLAGS"
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE(
+ [#include <kspeech.h>],
+ [
+ if (4 == KSpeech::mtHtml);
+ ],
+ have_latest_kspeech=yes,
+ have_latest_kspeech=no)
+ AC_MSG_RESULT($have_latest_kspeech)
+ CPPFLAGS=$ktts_save_cppflags
+ AC_LANG_RESTORE
+ fi
+ if test "x$have_latest_kspeech" = xyes; then
+ KTTS_KSPEECH_DIR='$(kde_includes)'
+ KTTS_KSPEECH_INCLUDE=""
+ KTTS_INTERFACES_DIR=""
+ else
+ KTTS_KSPEECH_DIR='$(top_srcdir)/kttsd/compat/interfaces/kspeech'
+ KTTS_KSPEECH_INCLUDE='-I$(top_srcdir)/kttsd/compat/interfaces/kspeech'
+ KTTS_INTERFACES_DIR="interfaces"
+ AC_MSG_WARN([Latest kspeech.h not installed. Compiling using kttsd/compat directory.])
+ fi
+
+ AC_SUBST(KTTS_KSPEECH_DIR)
+ AC_SUBST(KTTS_KSPEECH_INCLUDE)
+ AC_SUBST(KTTS_INTERFACES_DIR)
+fi
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..6812bd2
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,5 @@
+
+KDE_LANG = en
+KDE_DOCS = AUTO
+SUBDIRS = $(AUTODIRS)
+
diff --git a/doc/kmag/Makefile.am b/doc/kmag/Makefile.am
new file mode 100644
index 0000000..cc0e7e4
--- /dev/null
+++ b/doc/kmag/Makefile.am
@@ -0,0 +1,4 @@
+KDE_LANG = en
+KDE_DOCS = AUTO
+KDE_MANS = AUTO
+
diff --git a/doc/kmag/index.docbook b/doc/kmag/index.docbook
new file mode 100644
index 0000000..0faf531
--- /dev/null
+++ b/doc/kmag/index.docbook
@@ -0,0 +1,647 @@
+<?xml version="1.0" ?>
+<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
+ <!ENTITY kmag "<application>KMagnifier</application>">
+ <!ENTITY kappname "&kmag;">
+ <!ENTITY package "kdeaccessibility">
+ <!ENTITY % addindex "IGNORE">
+ <!ENTITY % English "INCLUDE"><!-- change language only here -->
+]>
+
+<!-- The language must NOT be changed here. -->
+
+<book lang="&language;">
+
+
+<bookinfo>
+<title>The &kmag; Handbook</title>
+
+<authorgroup>
+<author>
+<firstname>Sarang</firstname>
+<surname>Lakare</surname>
+<affiliation>
+<address><email>sarang@users.sf.net</email></address>
+</affiliation>
+</author>
+<author>
+<firstname>Olaf</firstname>
+<surname>Schmidt</surname>
+<affiliation>
+<address><email>ojschmidt@kde.org</email></address>
+</affiliation>
+</author>
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+</authorgroup>
+
+
+<copyright>
+<year>2000</year>
+<year>2002</year>
+<holder>Sarang Lakare</holder>
+</copyright>
+
+<copyright>
+<year>2004</year>
+<year>2005</year>
+<holder>Olaf Schmidt</holder>
+</copyright>
+
+<legalnotice>&FDLNotice;</legalnotice>
+
+
+
+<date>2006-05-25</date>
+<releaseinfo>1.0</releaseinfo>
+
+<!-- Abstract about this handbook -->
+
+<abstract>
+<para>
+&kmag; is a screen magnifier. You can use
+&kmag; to magnify a part of the screen just as you would use a lens to magnify
+a newspaper fine-print or a photograph. This application is useful for a
+variety of people: from researchers to artists to web-designers to people with
+low vision. This document will try to be a complete reference manual for using
+&kmag;.
+</para>
+
+</abstract>
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>kmag</keyword>
+<keyword>K Magnifier</keyword>
+</keywordset>
+
+</bookinfo>
+
+<chapter id="introduction">
+<title>Introduction</title>
+
+<para>
+&kmag; is a screen magnifier for the K Desktop Environment (&kde;). It can be used
+to magnify a part of the screen. This application can be useful to various people:
+People with low vision can use this application to magnify a part of the screen which they
+are unable to view clearly,
+artists can use this application to zoom into the graphics they produce and verify it
+at the pixel level,
+image-processing researchers can use this application to zoom into images and study them closely.
+Other than these, &kmag; can be used for various other purposes &eg; is possible to use the
+application for grabbing a portion of the screen and saving it to the disk (with an option of
+zooming the screen captured).
+</para>
+<para>
+&kmag; is a very powerful application with new features being added all the time. It is optimized
+for use on low processing power machines.
+</para>
+</chapter>
+
+<chapter id="using-kmag">
+<title>Using &kmag;</title>
+
+<screenshot>
+<screeninfo>Here's a screen shot of &kmag;</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="screenshot.png" format="PNG"/>
+ </imageobject>
+ <textobject>
+ <phrase>Screen shot of &kmag;</phrase>
+ </textobject>
+ </mediaobject>
+</screenshot>
+
+<para>
+After running &kmag; you will get a window similar to the one show above. The main window of
+&kmag; shows the magnified (or zoomed) contents.
+We refer to this window as the <quote>zoom window</quote>. The zoomed image shown inside the zoom window is
+captured from a part of the screen. The part of the screen which is magnified is referred to
+as the <quote>selection window</quote>.
+</para>
+<para>
+By default, &kmag; magnifies the region around the mouse cursor into the zoom window (think of it as a moving lens).
+Alternatively, you can ask &kmag; to magnify an chosen area of the screen into the zoom window
+(<guilabel>Selection Window Mode</guilabel>), or the area around the mouse cursur to one of the screen edges
+(e.g. <guilabel>Left Screen Edge Mode</guilabel>).
+</para>
+<para>
+If you would prefer not to see the mouse cursor in the zoomed image, select
+<guilabel>Hide Mouse Cursor</guilabel>. Please note that &kmag; cannot yet find out the current cursor shape.
+Thus, it shows the default &kde;/&Qt; cursor.
+</para>
+
+<sect1 id="changing-selection-window">
+<title>Changing the part of the screen to be magnified</title>
+<para>
+When in <guilabel>Selection Window Mode</guilabel>, the selection window can be moved and resized.
+You can also change the position and size of the selection window using the arrow keys on the keyboard,
+or by clicking into the zoom window:
+</para>
+
+<variablelist>
+<varlistentry>
+<term><keycap>Arrow keys</keycap> or &LMB;</term>
+<listitem>
+<para>By keeping the left mouse button pressed and moving the
+mouse, you can grab and drag the contents of the zoom window.
+You can also use the arrow keys.</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><keycombo>&Shift;<keycap>Arrow Keys</keycap></keycombo> or
+&Shift;&LMB; or &MMB;.</term>
+<listitem>
+<para>By additionally pressing &Shift; or using the &MMB;,
+you can move the selection window.
+</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><keycombo>&Ctrl;<keycap>Arrow Keys</keycap></keycombo> or
+&Ctrl;&LMB;</term>
+<listitem>
+<para>By using this combination, you can resize the selection
+window. Keep in mind that the top-left corner of the selection window
+is kept constant and the bottom-right corner is movable.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+
+</sect1>
+
+<sect1 id="kmag-features">
+<title>More &kmag; features</title>
+
+<para>&kmag; comes with lots of features. Its possible to print the zoomed
+image directly to a printer, save the image to a file, copy the zoomed
+image to the clipboard (which can be later used to paste in other applications),
+rotate the magnification image and more.
+</para>
+
+</sect1>
+</chapter>
+
+
+<chapter id="menus">
+<title>Menu Reference</title>
+
+<sect1 id="the-file-menu">
+<title>The <guimenu>File</guimenu> Menu</title>
+
+<variablelist>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;
+<keycap>N</keycap></keycombo>
+</shortcut>
+<guimenu>File</guimenu>
+<guimenuitem>New Window</guimenuitem>
+</menuchoice></term>
+<listitem><para>Opens a new &kmag; window.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;
+<keycap>S</keycap></keycombo>
+</shortcut>
+<guimenu>File</guimenu>
+<guimenuitem>Save Snapshot As...</guimenuitem>
+</menuchoice></term>
+<listitem><para>Saves the zoomed view to an image file.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;
+<keycap>P</keycap></keycombo>
+</shortcut>
+<guimenu>File</guimenu>
+<guimenuitem>Print...</guimenuitem>
+</menuchoice></term>
+<listitem><para>Prints the current zoomed view.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;
+<keycap>Q</keycap></keycombo>
+</shortcut>
+<guimenu>File</guimenu>
+<guimenuitem>Quit</guimenuitem>
+</menuchoice></term>
+<listitem><para>Quits the application</para></listitem>
+</varlistentry>
+</variablelist>
+</sect1>
+
+<sect1 id="the-edit-menu">
+<title>The <guimenu>Edit</guimenu> Menu</title>
+
+<variablelist>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;
+<keycap>C</keycap></keycombo>
+</shortcut>
+<guimenu>Edit</guimenu>
+<guimenuitem>Copy</guimenuitem>
+</menuchoice></term>
+<listitem><para>Copy the current zoomed view to the clipboard which
+you can paste in other applications.</para></listitem>
+</varlistentry>
+</variablelist>
+</sect1>
+
+<sect1 id="the-view-menu">
+<title>The <guimenu>View</guimenu> Menu</title>
+
+<variablelist>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">
+<keycap>F5</keycap></keycombo>
+</shortcut>
+<guimenu>View</guimenu>
+<guimenuitem>Start/Stop</guimenuitem>
+</menuchoice></term>
+<listitem><para>Start/Stop updating of the display.
+Stopping the update will zero the processing power required (CPU
+usage)</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>View</guimenu>
+<guimenuitem>Zoom</guimenuitem>
+</menuchoice></term>
+<listitem><para>Select the zoom factor.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;
+<keycap>-</keycap></keycombo>
+</shortcut>
+<guimenu>View</guimenu>
+<guimenuitem>Zoom Out</guimenuitem>
+</menuchoice></term>
+<listitem><para>Click on this button to zoom-out on the selected region.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;
+<keycap>+</keycap></keycombo>
+</shortcut>
+<guimenu>View</guimenu>
+<guimenuitem>Zoom In</guimenuitem>
+</menuchoice></term>
+<listitem><para>Click on this button to zoom-in on the selected region.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">
+<keycap>F6</keycap></keycombo>
+</shortcut>
+<guimenu>View</guimenu>
+<guimenuitem>Invert Colors</guimenuitem>
+</menuchoice></term>
+<listitem><para><action>Inverts</action> colors on the view, &ie; black things will be shown white.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>View</guimenu>
+<guimenuitem>Rotation</guimenuitem>
+</menuchoice></term>
+<listitem><para>Select the rotation degree (<guimenuitem>No Rotation (0 Degrees)</guimenuitem>,
+<guimenuitem>Left (90 Degrees)</guimenuitem>, <guimenuitem>Upside Down (180 Degrees)</guimenuitem>,
+<guimenuitem>Right (270 Degrees)</guimenuitem>.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>View</guimenu>
+<guimenuitem>Refresh</guimenuitem>
+</menuchoice></term>
+<listitem><para>Select the refresh rate (<guimenuitem>Very Low</guimenuitem>,
+<guimenuitem>Low</guimenuitem>, <guimenuitem>Medium</guimenuitem>,
+<guimenuitem>High</guimenuitem>, <guimenuitem>Very High</guimenuitem>).
+The higher the rate, the more computing power (CPU)
+will be needed.</para></listitem>
+</varlistentry>
+</variablelist>
+</sect1>
+
+<sect1 id="the-settings-menu">
+<title>The <guimenu>Settings</guimenu> Menu</title>
+
+<variablelist>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;
+<keycap>M</keycap></keycombo>
+</shortcut>
+<guimenu>Settings</guimenu>
+<guimenuitem>Show/Hide Menu</guimenuitem>
+</menuchoice></term>
+<listitem><para>Toggles the menubar on/off.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Show/Hide Main Toolbar</guimenuitem>
+</menuchoice></term>
+<listitem><para>Toggles the main toolbar on/off.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Show/Hide View Toolbar</guimenuitem>
+</menuchoice></term>
+<listitem><para>Toggles the view toolbar on/off.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Show/Hide Settings Toolbar</guimenuitem>
+</menuchoice></term>
+<listitem><para>Toggles the settings toolbar on/off.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">
+<keycap>F1</keycap></keycombo>
+</shortcut>
+<guimenu>Settings</guimenu>
+<guimenuitem>Follow Mouse Mode</guimenuitem>
+</menuchoice></term>
+<listitem><para>In this mode the area around the mouse cursor is shown in a normal window.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">
+<keycap>F2</keycap></keycombo>
+</shortcut>
+<guimenu>Settings</guimenu>
+<guimenuitem>Selection Window Mode</guimenuitem>
+</menuchoice></term>
+<listitem><para>In this mode a selection window is opened. The selected area is shown in a normal window.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Top Screen Edge Mode</guimenuitem>
+</menuchoice></term>
+<listitem><para>In this mode the area around the mouse is magnified to the top screen edge.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Left Screen Edge Mode</guimenuitem>
+</menuchoice></term>
+<listitem><para>In this mode the area around the mouse is magnified to the left screen edge.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Right Screen Edge Mode</guimenuitem>
+</menuchoice></term>
+<listitem><para>In this mode the area around the mouse is magnified to the right screen edge.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Bottom Screen Edge Mode</guimenuitem>
+</menuchoice></term>
+<listitem><para>In this mode the area around the mouse is magnified to the bottom screen edge.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">
+<keycap>F4</keycap></keycombo>
+</shortcut>
+<guimenu>Settings</guimenu>
+<guimenuitem>Show/Hide Mouse Cursor</guimenuitem>
+</menuchoice></term>
+<listitem><para>Show or hide the mouse cursor in the magnified image.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Configure Shortcuts...</guimenuitem>
+</menuchoice></term>
+<listitem><para>Opens a window that lets you configure the keyboard
+shortcuts for many menu commands.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<guimenu>Settings</guimenu>
+<guimenuitem>Configure Toolbars...</guimenuitem>
+</menuchoice></term>
+<listitem><para>Opens a window that lets you choose which icons are visible
+in the toolbar.</para></listitem>
+</varlistentry>
+</variablelist>
+</sect1>
+
+<sect1 id="the-help-menu">
+<title>The <guimenu>Help</guimenu> Menu</title>
+
+&help.menu.documentation;
+
+</sect1>
+</chapter>
+
+<chapter id="commands">
+<title>Command Reference</title>
+
+<para>&kmag; automatically uses all your default shortcuts for saving
+file, opening new window, printing, starting/stopping refresh (reload
+button in &konqueror;), zoom-in, zoom-out &etc;</para>
+
+<table>
+<title>Default Keyboard Shortcuts</title>
+<tgroup cols="2">
+<tbody>
+<row>
+<entry><keycombo>&Ctrl;<keycap>S</keycap></keycombo></entry>
+<entry><para>This will save the contents of the zoom window to a
+file.</para>
+</entry>
+</row>
+<row>
+<entry><keycap>F1</keycap></entry>
+<entry><para>Switch to "Follow Mouse Mode".</para>
+</entry>
+</row>
+<row>
+<entry><keycap>F2</keycap></entry>
+<entry><para>Switch to "Selection Window Mode".</para>
+</entry>
+</row>
+<row>
+<entry><keycap>F4</keycap></entry>
+<entry><para>Show or hide the mouse cursor in the magnified image.</para>
+</entry>
+</row>
+<row>
+<entry><keycap>F5</keycap></entry>
+<entry><para>This will start the refresh of the zoom window if it is
+stopped, or stops the refresh of the zoom window if the refresh is
+currently on.</para>
+</entry>
+</row>
+<row>
+<entry><keycap>F6</keycap></entry>
+<entry><para>Invert Colors</para>
+</entry>
+</row>
+<row>
+<entry><keycombo>&Ctrl;<keycap>N</keycap></keycombo></entry>
+<entry><para>This will open a new &kmag; window.</para></entry>
+</row>
+<row>
+<entry><keycombo>&Ctrl;<keycap>P</keycap></keycombo></entry>
+<entry><para>This will open the print dialog for printing the contents
+of the zoom window.</para></entry>
+</row>
+<row>
+<entry><keycombo>&Ctrl;<keycap>C</keycap></keycombo></entry>
+<entry><para>This will copy the zoom window contents to the
+clipboard.</para>
+</entry>
+</row>
+<row>
+<entry><keycombo>&Ctrl;<keycap>M</keycap></keycombo></entry>
+<entry><para>Show/Hide the menubar.</para>
+</entry>
+</row>
+<row>
+<entry><keycombo>&Ctrl;<keycap>-</keycap></keycombo></entry>
+<entry><para>Zoom out</para></entry>
+</row>
+<row>
+<entry><keycombo>&Ctrl;<keycap>+</keycap></keycombo></entry>
+<entry><para>Zoom in</para></entry>
+</row>
+<row>
+<entry><keycombo>&Ctrl;<keycap>Q</keycap></keycombo></entry>
+<entry><para>Quits the application.</para></entry>
+</row>
+</tbody>
+</tgroup>
+
+</table>
+
+</chapter>
+
+<!--
+<chapter id="faq">
+<title>Questions and Answers</title>
+
+&reporting.bugs;
+&updating.documentation;
+
+<para>
+This section is currently empty as I have not received any questions from any users! I
+will add some FAQ if I hear from any of the users.
+</para>
+
+</chapter>
+-->
+<chapter id="credits">
+
+<!-- Include credits for the programmers, documentation writers, and
+contributors here. The license for your software should then be included below
+the credits with a reference to the appropriate license file included in the KDE
+distribution. -->
+
+<title>Credits and License</title>
+
+<para>
+&kmag;
+</para>
+<para>
+Program copyright 2001-2003 Sarang Lakare <email>sarang@users.sf.net</email> and 2003-2005 Olaf Schmidt <email>ojschmidt@kde.org</email>.
+</para>
+<para>
+Contributors:
+<itemizedlist>
+<listitem><para>Michael Forster <email>forster@fmi.uni-passau.de</email> (original author)</para></listitem>
+</itemizedlist>
+</para>
+
+
+<para>
+Documentation copyright 2002 Sarang Lakare <email>sarang@users.sf.net</email> and
+2004-2005 Olaf Schmidt <email>ojschmidt@kde.org</email>
+</para>
+
+<!-- TRANS:CREDIT_FOR_TRANSLATORS -->
+&underFDL; <!-- FDL: do not remove. Commercial development should -->
+&underGPL; <!-- GPL License -->
+
+</chapter>
+
+<appendix id="installation">
+<title>Installation</title>
+
+<sect1 id="getting-kmag">
+<title>How to obtain &kmag;</title>
+
+&install.intro.documentation;
+
+</sect1>
+
+<sect1 id="compilation">
+<title>Compilation and Installation</title>
+
+&install.compile.documentation;
+
+</sect1>
+
+</appendix>
+
+&documentation.index;
+</book>
+<!--
+Local Variables:
+mode: sgml
+sgml-minimize-attributes:nil
+sgml-general-insert-case:lower
+sgml-indent-step:0
+sgml-indent-data:nil
+End:
+-->
diff --git a/doc/kmag/man-kmag.1.docbook b/doc/kmag/man-kmag.1.docbook
new file mode 100644
index 0000000..540b139
--- /dev/null
+++ b/doc/kmag/man-kmag.1.docbook
@@ -0,0 +1,64 @@
+<?xml version="1.0" ?>
+<!DOCTYPE refentry PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
+<!ENTITY % English "INCLUDE">
+]>
+
+<refentry lang="&language;">
+<refentryinfo>
+<title>&kde; User's Manual</title>
+<author>&Lauri.Watts; &Lauri.Watts.mail;</author>
+<date>June 12, 2005</date>
+<productname>K Desktop Environment</productname>
+</refentryinfo>
+
+<refmeta>
+<refentrytitle><command>kmag</command></refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+
+<refnamediv>
+<refname><command>kmag</command></refname>
+<refpurpose>Screen magnifier</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+<cmdsynopsis>
+<command>kmag</command>
+<arg choice="opt">&kde; Generic Options</arg>
+<arg choice="opt">&Qt; Generic Options</arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+<title>Description</title>
+<para><command>kmag</command>, also known as &kmagnifier; is a screen
+magnifier. You can use &kmagnifier; to magnify a part of the screen just as
+you would use a lens to magnify a newspaper fine-print or a photograph. This
+application is useful for a variety of people: from researchers to artists
+to web-designers to people with low vision.</para>
+</refsect1>
+
+<refsect1>
+<title>See Also</title>
+
+<para>More detailed user documentation is available from <ulink
+url="help:/kmag">help:/kmag</ulink>
+(either enter this &URL; into &konqueror;, or run
+<userinput><command>khelpcenter</command>
+<parameter>help:/kmag</parameter></userinput>).</para>
+
+<para>There is also further information available at the <ulink url="http://accessibility.kde.org/">&kde; accessibility project home page.</ulink></para>
+</refsect1>
+
+<refsect1>
+<title>Authors</title>
+<para>&kmagnifier; was written by
+<personname><firstname>Olaf</firstname><surname>Schmidt</surname></personname>
+<email>ojschmidt@kde.org</email> and
+<personname><firstname>Sarang</firstname><surname>Lakare</surname></personname>
+<email>sarang@users.sf.net</email> and
+<personname><firstname>Michael</firstname><surname>Forster</surname></personname>
+<email>forster@fmi.uni-passau.de</email></para>
+</refsect1>
+
+</refentry>
diff --git a/doc/kmag/screenshot.png b/doc/kmag/screenshot.png
new file mode 100644
index 0000000..7d90441
--- /dev/null
+++ b/doc/kmag/screenshot.png
Binary files differ
diff --git a/doc/kmousetool/Makefile.am b/doc/kmousetool/Makefile.am
new file mode 100644
index 0000000..cc0e7e4
--- /dev/null
+++ b/doc/kmousetool/Makefile.am
@@ -0,0 +1,4 @@
+KDE_LANG = en
+KDE_DOCS = AUTO
+KDE_MANS = AUTO
+
diff --git a/doc/kmousetool/index.docbook b/doc/kmousetool/index.docbook
new file mode 100644
index 0000000..dce288f
--- /dev/null
+++ b/doc/kmousetool/index.docbook
@@ -0,0 +1,449 @@
+<?xml version="1.0" ?>
+<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
+ <!ENTITY kmousetool '<application>KMouseTool</application>'>
+ <!ENTITY kappname "&kmousetool;">
+ <!ENTITY package "kdeaccessibility">
+ <!ENTITY % addindex "IGNORE">
+ <!ENTITY % English "INCLUDE"><!-- change language only here -->
+]>
+
+<book lang="&language;">
+
+<bookinfo>
+<title>The &kmousetool; Handbook</title>
+
+<authorgroup>
+<author>
+<firstname>Jeff</firstname>
+
+<surname>Roush</surname>
+<affiliation>
+<address><email>jeff@kmousetool.com</email></address>
+</affiliation>
+</author>
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+</authorgroup>
+
+
+<copyright>
+<year>2002</year>
+<holder>Jeff Roush</holder>
+</copyright>
+
+<legalnotice>&FDLNotice;</legalnotice>
+
+<date>2006-05-20</date>
+<releaseinfo>1.12</releaseinfo>
+
+<abstract>
+<para>
+&kmousetool; clicks the mouse whenever the mouse cursor pauses briefly. It
+was designed to help those with repetitive strain injuries, for whom
+pressing buttons hurts.
+</para>
+</abstract>
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>kdeutils</keyword>
+<keyword>KMouseTool</keyword>
+<keyword>ergonomic</keyword>
+<keyword>tendonitis</keyword>
+<keyword>carpal tunnel syndrome</keyword>
+</keywordset>
+
+</bookinfo>
+
+<chapter id="introduction">
+<title>Introduction</title>
+
+<para>
+&kmousetool; clicks the mouse whenever the mouse cursor pauses briefly. It was designed to help those
+with repetitive strain injuries, for whom pressing buttons hurts.
+It can also drag the mouse, although this takes a bit more practice.
+</para>
+
+<para>
+&kmousetool; can eliminate the pain caused by clicking the mouse, and helps many
+people to use the computer without pain. Unfortunately, some pain can also
+be caused by simply moving the mouse around the table. If you are experiencing
+computer-related pain and haven't yet seen a doctor, please do so.
+</para>
+<para>
+Just to make it absolutely clear: while &kmousetool; can help reduce the pain
+caused by <emphasis>clicking</emphasis> the mouse, it cannot help any pain
+caused by <emphasis>moving</emphasis> the mouse. And, like all ergonomic tools,
+your mileage may vary.
+</para>
+
+</chapter>
+
+
+<chapter id="using-kmousetool">
+<title>Using &kmousetool;</title>
+<para>
+Using &kmousetool; is simple: &kmousetool; watches as you move the mouse, and
+when you pause briefly, it clicks.
+</para>
+
+<para>
+&kmousetool;'s Smart Drag mode allows you to drag the mouse.
+</para>
+
+<para>
+When Smart Drag is enabled, &kmousetool; pauses after it clicks down; if you
+move the mouse, it waits until you stop moving before it clicks up. This
+way, you can both click and drag the mouse. Smart Drag takes a bit more
+practice, but becomes natural once you get used to it.
+</para>
+
+</chapter>
+
+
+<chapter id="commands">
+<title>Command Reference</title>
+
+<sect1 id="kmousetool-mainwindow">
+<title>The Main &kmousetool; window</title>
+
+ <para>&kmousetool;'s
+ options are accessed mostly via the mouse.</para>
+
+
+ <variablelist>
+ <varlistentry>
+ <term><guibutton>Start</guibutton>
+ </term>
+ <listitem>
+ <para>Starts (or stops) &kmousetool;.</para>
+ </listitem>
+ </varlistentry>
+<varlistentry>
+<term><guilabel>Minimum movement:</guilabel></term>
+<listitem>
+<para>The minimum movement in pixels before &kmousetool; will attempt
+to click the mouse.</para>
+</listitem>
+</varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Dwell time (1/10 sec):</guilabel>
+ </term>
+ <listitem>
+ <para>The time the mouse has to pause before &kmousetool; clicks.
+ Try increasing this time if
+ it is hard getting used to &kmousetool; </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><guilabel>Smart drag</guilabel>
+ </term>
+ <listitem>
+ <para>Enables or disables Smart Drag. Disabled use is
+ easier, so this is the default.</para><para>If you enable
+ <guilabel>Smart drag</guilabel> the <guilabel>Drag time
+ (1/10 sec):</guilabel> field becomes available. This is the
+ time &kmousetool; waits, after it clicks down, before it
+ clicks back up if you don't move the mouse. </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><guilabel>Enable strokes</guilabel>
+ </term>
+ <listitem>
+ <para>&kmousetool; now supports strokes. When you enable
+strokes, a slow move to the right and back, followed by a pause, will
+generate a <mousebutton>right</mousebutton> click. A slow move left
+and back will generate a double click. (Strokes are specified in
+<filename>$<envar>KDEHOME</envar>/share/config/kmousetool_strokes.txt</filename>.
+This file is generated by &kmousetool; the first time it is run, but
+can be modified afterwards.)
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><guilabel>Audible click</guilabel>
+ </term>
+ <listitem>
+ <para>
+ Plays a sound when &kmousetool; clicks down. This helps, especially
+ with Smart Drag.
+ </para>
+ <para>
+ If the sound seems delayed, you can have &kde; speed it up.
+ To do this open the &kcontrolcenter;, click on
+ <guimenuitem>Sound &amp; Multimedia</guimenuitem>, then on <guimenuitem>Sound
+ System</guimenuitem>, and then select the <guilabel>Sound
+ I/O</guilabel> tab. At the bottom
+ of the tab, there is an <guilabel>Audio buffer size (response
+ time)</guilabel> adjustment;
+ slide this towards the lower number to speed up the audio
+ response time.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><guilabel>Start with KDE</guilabel>
+ </term>
+ <listitem>
+ <para>When this is enabled, &kmousetool; will start each
+ time &kde; starts. At the moment, this only works under
+ &kde;. Under GNOME or other Window Managers, see the
+ documentation for the Window Manager itself to see how to
+ start a program automatically when you start the windowing
+ system.</para>
+ </listitem>
+ </varlistentry>
+<varlistentry>
+<term><guibutton>Defaults</guibutton></term>
+<listitem>
+<para>Reset all settings to their defaults.</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><guibutton>Reset</guibutton></term>
+<listitem>
+<para>Reset all settings to their state when you opened the dialog,
+or, if you have already saved a setting with the
+<guibutton>Apply</guibutton> button, reset all settings to the state
+when you last pressed <guibutton>Apply</guibutton></para>
+</listitem>
+</varlistentry>
+ <varlistentry>
+ <term><guibutton>Apply</guibutton>
+ </term>
+ <listitem>
+ <para>After changing any settings, you must click this button.</para>
+ </listitem>
+ </varlistentry>
+<varlistentry>
+<term><guibutton>Help</guibutton></term>
+<listitem>
+<para>Opens the User manual (this document).</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><guibutton>Close</guibutton></term>
+<listitem>
+<para>Close the dialog without saving any settings.</para>
+</listitem>
+</varlistentry>
+<varlistentry>
+<term><guibutton>Quit</guibutton></term>
+<listitem>
+<para>Quit &kmousetool;</para>
+</listitem>
+</varlistentry>
+</variablelist>
+
+</sect1>
+</chapter>
+
+<chapter id="Tips">
+<title>Tips</title>
+
+<para>
+These tips can help shorten &kmousetool;'s learning curve a bit.
+
+<itemizedlist>
+<listitem><para>You can modify the time delays &kmousetool; waits, for both clicking and for dragging.</para>
+</listitem>
+<listitem><para>It's best to practice clicking with &kmousetool; using its defaults first.
+You may especially want to leave Smart Drag disabled at first.
+Then, once you are comfortable clicking, move on to practicing Smart Drag.</para>
+</listitem>
+<listitem><para>When using Smart Drag, it may help to enable the Audible Click</para>
+</listitem>
+<listitem><para>When using the Audible Click, you may need to speed up &kde;'s audio response.</para>
+</listitem>
+</itemizedlist>
+</para>
+
+</chapter>
+
+<chapter id="faq">
+<title>Questions and Answers</title>
+
+&reporting.bugs;
+&updating.documentation;
+
+<qandaset id="faqlist">
+<qandaentry>
+<question>
+<para>Help! &kmousetool; keeps dropping spurious clicks all over the screen!</para>
+</question>
+<answer>
+<para>
+When you are using &kmousetool;, you do have to learn new mousing habits.
+</para>
+<para>
+First,
+keep in mind where it's safe to click &mdash; clicking on gray parts of windows or non-link
+areas of web browsers won't hurt anything, so you can safely rest the mouse over those areas
+until you need it.
+</para>
+<para>
+Second, you need to know where you're going to click before you move
+the mouse. Most of the time, when we know we're going to use the mouse, most of
+us grab the mouse and start moving it around randomly until we figure out where
+we want to click. With &kmousetool;, you need to know where you're going to click
+before you move the mouse in the first place. It is also a good idea to keep
+your hands off the mouse when you're not using it.
+</para>
+</answer>
+</qandaentry>
+
+<qandaentry>
+<question>
+<para>My mouse sticks when I move it. Can I still use &kmousetool;?</para>
+</question>
+<answer>
+<para>Yes. If your mouse sticks, it means you need to clean your mouse.
+This is usually easy to do; the trick is that you have to clean not just the
+mouse's ball, but the rollers that the ball rolls against inside the mouse.</para>
+<para>First, you have to remove the ball. The method for doing this varies from
+mouse to mouse, but it's usually pretty clear how to do this if you look at
+the bottom of the mouse.</para>
+<para>Once you've removed the ball, you should be able to see the rollers on the
+sides of the hole that contained the ball. The dirt and grime on them can be
+easily scraped off with a flat blade or with a fingernail. </para>
+</answer>
+</qandaentry>
+
+<qandaentry>
+<question>
+<para>&kmousetool; clicks down and never clicks up. What's happening?</para>
+</question>
+<answer>
+<para>In some rare situations, the system suspends &kmousetool; when a drag
+starts; if you are using Smart Drag, this means thar &kmousetool; can never finish the drag by
+clicking up.</para>
+<para>
+This happens when you use &kmousetool; under a non &kde; window manager and then
+use it to move a window.
+</para>
+<para>The solution is to simply click manually; this resets &kmousetool;, and you can then
+continue to work normally again.</para>
+</answer>
+</qandaentry>
+
+<qandaentry>
+<question>
+<para>
+&kmousetool; moves the cursor when I am trying to type.</para>
+</question>
+<answer>
+<para>Problem: When you're typing text, &kmousetool; keeps
+dropping clicks and moving the cursor away from where you want to type.</para>
+<para>Solution: Use the mouse to place the cursor where you want it, but when you're ready
+to type, park the mouse on a neutral area on the screen. Then, if you
+bump the mouse, or if it moves a few pixels, any random clicks that it sends
+won't matter. Safe places to park the mouse include the gray areas
+around toolbars and menus, and on the title bars of windows.</para>
+</answer>
+</qandaentry>
+
+<qandaentry>
+<question>
+<para>I'm trying to use Smart Drag, but I cannot get the hang of using it to edit text.</para>
+</question>
+<answer>
+<para>
+Smart Drag is an advanced feature of &kmousetool;, and takes some getting used to. It is very
+possible to use it to select text, to cut and paste, and use it in almost any situation
+where you would normally want to drag the mouse. But you probably won't be able to do this
+at first. Here are some suggestions:
+</para>
+<itemizedlist>
+<listitem><para>Don't use Smart Drag while you are first learning to use &kmousetool;. Instead,
+to select text, click at one end of the text, and hold down
+the shift key while you click at the other end of the text.
+</para></listitem>
+<listitem><para>Use the Audible Click. This will play a <quote>click</quote> sound when &kmousetool; clicks
+down, and this will tell you when the Smart Drag delay is beginning. With practice, you
+can use Smart Drag without the Audible Click, but it does take a fair amount of practice.
+</para></listitem>
+<listitem><para>Know where you're going to click the mouse before you begin moving it.
+</para></listitem>
+</itemizedlist>
+
+</answer>
+</qandaentry>
+
+</qandaset>
+</chapter>
+
+<chapter id="credits">
+
+<title>Credits and License</title>
+
+<para>
+&kmousetool;
+</para>
+<para>
+Program copyright 2002 Jeff Roush <email>jeff@mousetool.com</email>
+and 2003 Gunnar Schmi Dt <email>gunnar@schmi-dt.de</email>
+</para>
+<para>
+Contributors:
+<itemizedlist>
+<listitem><para>Jeff Roush <email>jeff@mousetool.com</email></para></listitem>
+<listitem><para>Gunnar Schmi Dt<email>gunnar@schmi-dt.de</email></para></listitem>
+<listitem><para>Olaf Schmidt <email>ojschmidt@kde.org</email></para></listitem>
+</itemizedlist>
+</para>
+
+<para>
+Documentation copyright 2002 Jeff Roush<email>jeff@mousetool.com</email>
+</para>
+
+<!-- TRANS:CREDIT_FOR_TRANSLATORS -->
+&underFDL;
+&underGPL; <!-- GPL License -->
+
+</chapter>
+
+<appendix id="installation">
+<title>Installation</title>
+
+<sect1 id="getting-kmousetool">
+<title>How to obtain &kmousetool;</title>
+
+&install.intro.documentation;
+
+</sect1>
+
+<sect1 id="requirements">
+<title>Requirements</title>
+
+<para>
+In order to successfully use &kappname;, you need the XTest extension
+compiled as part of your &X-Window;. This should already be installed
+on your system; very few systems won't have it.
+</para>
+<para>
+In order to use the Audible Click feature, you will have to have a
+sound card and speakers, and you will have to have configured the
+sound card correctly.
+</para>
+</sect1>
+
+<sect1 id="compilation">
+<title>Compilation and Installation</title>
+
+&install.compile.documentation;
+
+</sect1>
+
+</appendix>
+
+&documentation.index;
+</book>
+<!--
+Local Variables:
+mode: sgml
+sgml-minimize-attributes:nil
+sgml-general-insert-case:lower
+sgml-indent-step:0
+sgml-indent-data:nil
+End:
+-->
diff --git a/doc/kmousetool/man-kmousetool.1.docbook b/doc/kmousetool/man-kmousetool.1.docbook
new file mode 100644
index 0000000..31f68cc
--- /dev/null
+++ b/doc/kmousetool/man-kmousetool.1.docbook
@@ -0,0 +1,63 @@
+<?xml version="1.0" ?>
+<!DOCTYPE refentry PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
+<!ENTITY kmousetool '<application>KMouseTool</application>'>
+<!ENTITY % English "INCLUDE">
+]>
+
+<refentry lang="&language;">
+<refentryinfo>
+<title>&kde; User's Manual</title>
+<author>&Lauri.Watts; &Lauri.Watts.mail;</author>
+<date>June 12, 2005</date>
+<productname>K Desktop Environment</productname>
+</refentryinfo>
+
+<refmeta>
+<refentrytitle><command>kmousetool</command></refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+
+<refnamediv>
+<refname><command>kmousetool</command></refname>
+<refpurpose>Accessibility tool to help click the mouse</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+<cmdsynopsis>
+<command>kmousetool</command>
+<arg choice="opt">&kde; Generic Options</arg>
+<arg choice="opt">&Qt; Generic Options</arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+<title>Description</title>
+
+<para>&kmousetool; clicks the mouse whenever the mouse cursor pauses
+briefly. It was designed to help those with repetitive strain injuries, for
+whom pressing buttons hurts. </para>
+
+<para>&kmousetool; can also be configured to wait for a specified time for a
+drag to begin, before unclicking the mouse. This way, you can use it for
+drag and drop operations as well.</para>
+
+</refsect1>
+
+<refsect1>
+<title>See Also</title>
+
+<para>More detailed user documentation is available from <ulink
+url="help:/kmousetool">help:/kmousetool</ulink>
+(either enter this &URL; into &konqueror;, or run
+<userinput><command>khelpcenter</command>
+<parameter>help:/kmousetool</parameter></userinput>).</para>
+
+<para>There is also further information available at <ulink url="http://accessibility.kde.org">the &kde; accessibility site.</ulink></para>
+</refsect1>
+
+<refsect1>
+<title>Authors</title>
+<para>&kmousetool; was written by <personname><firstname>Gunnar</firstname><surname>Schmi Dt</surname></personname> <email>gunnar@schmi-dt.de</email>, <personname><firstname>Olaf</firstname><surname>Schmidt</surname></personname> <email>ojschmidt@kde.org</email> and <personname><firstname>Jeff</firstname><surname>Roush</surname></personname> <email>jeff@mousetool.com</email>.</para>
+</refsect1>
+
+</refentry>
diff --git a/doc/kmouth/Makefile.am b/doc/kmouth/Makefile.am
new file mode 100644
index 0000000..cc0e7e4
--- /dev/null
+++ b/doc/kmouth/Makefile.am
@@ -0,0 +1,4 @@
+KDE_LANG = en
+KDE_DOCS = AUTO
+KDE_MANS = AUTO
+
diff --git a/doc/kmouth/index.docbook b/doc/kmouth/index.docbook
new file mode 100644
index 0000000..3cfcf10
--- /dev/null
+++ b/doc/kmouth/index.docbook
@@ -0,0 +1,1122 @@
+<?xml version="1.0" ?>
+<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
+ <!ENTITY kmouth '<application>KMouth</application>'>
+ <!ENTITY kappname "&kmouth;">
+ <!ENTITY package "kdeaccessibility">
+ <!ENTITY % addindex "IGNORE">
+ <!ENTITY % English "INCLUDE"><!-- change language only here -->
+]>
+
+<book lang="&language;">
+<bookinfo>
+ <title>The &kmouth; Handbook</title>
+
+ <authorgroup>
+ <author>
+ <firstname>Gunnar</firstname>
+ <surname>Schmi Dt</surname>
+ <affiliation>
+ <address><email>gunnar@schmi-dt.de</email></address>
+ </affiliation>
+ </author>
+ <!-- TRANS:ROLES_OF_TRANSLATORS -->
+ </authorgroup>
+
+
+ <copyright>
+ <year>2002</year><year>2003</year>
+ <holder>Gunnar Schmi Dt</holder>
+ </copyright>
+ <!-- Translators: put here the copyright notice of the translation -->
+ <legalnotice>&FDLNotice;</legalnotice>
+
+
+ <date>2006-05-20</date>
+ <releaseinfo>1.1.1</releaseinfo>
+
+ <abstract>
+ <para>
+ &kmouth; is an application that enables persons that cannot speak to let their
+ computers speak.
+ </para>
+ </abstract>
+
+ <keywordset>
+ <keyword>KDE</keyword>
+ <keyword>kdeutils</keyword>
+ <keyword>KMouth</keyword>
+ <keyword>text-to-speech conversion</keyword>
+ <keyword>mutual persons</keyword>
+ </keywordset>
+</bookinfo>
+
+<chapter id="introduction">
+ <title>Introduction</title>
+
+ <para>
+ &kmouth; is a program that enables persons that cannot speak to let their
+ computers speak. It includes a history of spoken sentences from which the
+ user can select sentences to be re-spoken.
+ </para>
+ <para>
+ Note that &kmouth; does not include speech synthesizer. Instead it requires
+ a speech synthesizer installed in the system.
+ </para>
+ <para>
+ Please report any problems and feature requests to the author of &kmouth;.
+ </para>
+</chapter>
+
+<chapter id="using-kmouth">
+ <title>Using &kmouth;</title>
+ <sect1 id="Wizard">
+ <title>The first start</title>
+ <para>
+ During the first start of &kmouth;, a wizard is displayed into which you
+ can enter some basic configuration.
+ </para>
+ <para>
+ <screenshot>
+ <screeninfo>The wizard</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="kmouthwizard.png" format="PNG"/>
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="kmouthwizard.eps" format="EPS"/>
+ </imageobject>
+ <textobject>
+ <phrase>The wizard</phrase>
+ </textobject>
+ </mediaobject>
+ </screenshot>
+ </para>
+ <para>
+ With the first page of the wizard (the left screen shot) you specify
+ the command that shall later be used for the text-to-speech conversion.
+ For more details look into the <link linkend="tts-config">description
+ of the configuration dialog.</link>
+ </para>
+ <para>
+ With the second page you select which standard phrase books you need.
+ From the phrase books you later can select often used phrases so that
+ you do not need to type them in. Of course &kmouth; also has an edit
+ dialog for the case that you later want to edit your phrase books.
+ </para>
+ <para>
+ With the third page (the right screen shot) you define the dictionary
+ for a word completion. &kmouth; will parse the &kde; documentation of
+ the chosen language in order to detect the frequentness of individual
+ words. Optionally you can compare the word list to an OpenOffice.org
+ dictionary in order to only add correctly spelled words to the word
+ completion.
+ </para>
+ </sect1>
+ <sect1 id="main-window">
+ <title>The Main Window</title>
+ <para>
+ The main window of &kmouth; is fairly simple. It consists basically of an
+ edit field into which you type your sentences (the lower white field in
+ the screen shot) and a history of spoken sentences (the upper white field
+ in the screen shot).
+ </para>
+ <para>
+ <screenshot>
+ <screeninfo>The main window of &kmouth;</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="kmouthmain.png" format="PNG"/>
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="kmouthmain.eps" format="EPS"/>
+ </imageobject>
+ <textobject>
+ <phrase>Screen shot</phrase>
+ </textobject>
+ </mediaobject>
+ </screenshot>
+ </para>
+ <para>
+ Assuming that you have correctly <link linkend="config-dialog">configured
+ &kmouth;</link> you can use the edit field for entering sentences you
+ want to hear. Once a sentence got spoken it will be appended to the
+ history. From the history you can select sentences to be re-spoken.
+ </para>
+ <para>
+ From the phrase books (located in the line below the tool bar) you can
+ select often used phrases.
+ </para>
+ </sect1>
+ <sect1 id="config-dialog">
+ <title>The Configuration Dialog</title>
+ <para>
+ By using the menu entry
+ <menuchoice>
+ <guimenu>Settings</guimenu><guimenuitem>Configure &kmouth;...</guimenuitem>
+ </menuchoice>
+ you open the configuration dialog of &kmouth;. This dialog consists of
+ the pages <guilabel>General Options</guilabel> with the two tabs <guilabel>Text-to-Speech</guilabel>
+ and <guilabel>Preferences</guilabel>, the page <guilabel>Word Completion</guilabel> and
+ the page <guilabel>KTTSD Speech Service</guilabel>
+ </para>
+ <sect2 id="tts-config">
+ <title>The <guilabel>Text-to-Speech</guilabel> tab</title>
+ <para>
+ <screenshot>
+ <screeninfo>The <guilabel>Text-to-Speech</guilabel> tab</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="kmouthctts.png" format="PNG"/>
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="kmouthctts.eps" format="EPS"/>
+ </imageobject>
+ <textobject>
+ <phrase>Screen shot</phrase>
+ </textobject>
+ </mediaobject>
+ </screenshot>
+ </para>
+ <para>
+ Into the edit field of the <guilabel>Text-to-Speech</guilabel> tab you enter the command
+ for calling the speech synthesizer. With the combo box below the edit
+ field you specify the character encoding that is used for passing the
+ text to the speech synthesizer.
+ </para>
+ <para>
+ &kmouth; knows two ways of passing the text: If the command expects the
+ text as standard input you select the check box.
+ </para>
+ <para>
+ The other way is to pass the text as a parameter:
+ Before calling the command &kmouth; replaces certain placeholders with
+ actual content:
+ <informaltable frame="topbot">
+ <tgroup cols="2">
+ <thead>
+ <row><entry>Placeholder</entry><entry>Replaced with</entry></row>
+ </thead>
+ <tbody>
+ <row><entry><token>%t</token></entry>
+ <entry>The actual text that should be spoken</entry>
+ </row>
+ <row><entry><token>%f</token></entry>
+ <entry>The name of a temporary file that contains the text
+ that should be spoken</entry>
+ </row>
+ <row><entry><token>%l</token></entry>
+ <entry>The language code associated with the current word completion
+ dictionary</entry>
+ </row>
+ <row><entry><token>%%</token></entry><entry>A percent sign</entry></row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ <para>
+ Off course the command for speaking texts is dependent on which speech
+ synthesizer you use. Please look into the documentation of your speech
+ synthesizer for the command for speaking texts. You can find examples
+ for the command in the <link linkend="tts">appendix</link>.
+ </para>
+ <para>
+ By selecting <guilabel>Use KTTSD speech service if possible</guilabel> you tell &kmouth;
+ first to try to send the text to the KTTSD speech service. If this succeeds the
+ other configuration entries on this tab are ignored. The KTTSD speech
+ service is a &kde; daemon which gives &kde; applications a standardized
+ interface for speech synthesis and is currently developed in <acronym>SVN</acronym>. It
+ is safe to select this option even if KTTSD is not installed.
+ </para>
+ </sect2>
+ <sect2 id="preferences">
+ <title>The <guilabel>Preferences</guilabel> tab</title>
+ <para>
+ <screenshot>
+ <screeninfo>The <guilabel>Preferences</guilabel> tab</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="kmouthcpref.png" format="PNG"/>
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="kmouthcpref.eps" format="EPS"/>
+ </imageobject>
+ <textobject>
+ <phrase>Screen shot</phrase>
+ </textobject>
+ </mediaobject>
+ </screenshot>
+ </para>
+ <para>
+ The <guilabel>Preferences</guilabel> tab contains options that alter the behavior of
+ &kmouth; in certain situations.
+ </para>
+ <para>
+ With the first combo box, <guilabel>Selection of phrases in the phrase book:</guilabel>,
+ you specify which action is triggered by typing the shortcut of a
+ phrase or by selecting a phrase in the <guimenu>Phrase Book</guimenu>
+ menu or in the phrase book bar.
+ </para>
+ <para>
+ By selecting <guilabel>Speak Immediately</guilabel> the
+ selected phrase gets immediately spoken and is entered into
+ the history. If you select <guilabel>Insert Into Edit
+ Field</guilabel> the selected phrase is just inserted into the
+ edit field.
+ </para>
+ <para>
+ With the second combo box, <guilabel>Closing the phrase book
+ edit window:</guilabel>, you specify whether the phrase book
+ gets saved if you just close the phrase book edit window.
+ </para>
+ <para>
+ By selecting <guilabel>Save Phrase Book</guilabel> the phrase
+ book gets saved. If you select <guilabel>Discard
+ changes</guilabel> the changes are discarded and the phrase
+ book is not saved. If you select <guilabel>Ask Whether to
+ Save</guilabel> &kmouth; will ask you whether it shall save
+ the phrase book.
+ </para>
+ </sect2>
+ <sect2 id="completion-config">
+ <title>The <guilabel>Word Completion</guilabel> page</title>
+ <para>
+ <screenshot>
+ <screeninfo>The <guilabel>Word Completion</guilabel> page</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="kmouthcwcp.png" format="PNG"/>
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="kmouthcwcp.eps" format="EPS"/>
+ </imageobject>
+ <textobject>
+ <phrase>Screen shot</phrase>
+ </textobject>
+ </mediaobject>
+ </screenshot>
+ </para>
+ <para>
+ The <guilabel>Word Completion</guilabel> page contains a list
+ of dictionaries used for the word completion. (&kmouth; will
+ display a combo box next to the edit field in the main window
+ if this list contains more than one dictionary. You can use this
+ combo box in order to select the dictionary that actually gets
+ used for the word completion.)
+ </para>
+ <para>
+ With the buttons on the right side of the page you can add and
+ delete dictionaries, change the order of the dictionaries or export
+ dictionaries to a file. With the edit field and the combo box below
+ the list you can change the name and the language associated with
+ the dictionary.
+ </para>
+ <para>
+ When you add a new dictionary you may choose between several sources:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>Create a new dictionary from the &kde; documentation</para>
+ <para>
+ If you use this source &kmouth; will ask you for the intended
+ language and afterwards parse the &kde; documentation. The
+ frequentness of the individual words is detect by simply counting
+ the occurrences of each word. Optionally you can compare the word
+ list to an OpenOffice.org dictionary in order to only add correctly
+ spelled words to the new dictionary.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Create a new dictionary from a file</para>
+ <para>
+ If you use this source &kmouth; will ask you for the intended
+ file. You may either select an &XML; file, a standard text file or
+ a file containing a word completion dictionary created by either
+ &kmouth; or GOK (the GNOME On-screen Keyboard). If you select a
+ standard text file or an &XML; file the frequentness of the individual
+ words is detected by simply counting the occurrences of each word.
+ Optionally you can compare the word list to an OpenOffice.org
+ dictionary in order to only add correctly spelled words to the new
+ dictionary.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Create a new dictionary from a folder</para>
+ <para>
+ If you use this source &kmouth; will ask you for the intended folder.
+ &kmouth; will open all files in that folder and its subdirectories.
+ Each file is either loaded as a completion dictionary, as an &XML; file
+ or as a standard text file. In the latter two cases the occurrences of
+ each individual word in the file is counted. Optionally you can compare
+ the word list to an OpenOffice.org dictionary in order to only add
+ correctly spelled words to the new dictionary.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Merge dictionaries</para>
+ <para>
+ You can use this option in order to merge the available dictionaries.
+ &kmouth; will ask you which dictionaries should be merged and how the
+ individual dictionaries should be weighted.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Create an empty word list</para>
+ <para>
+ You can use this option in order to create a blank dictionary without
+ any entries. As &kmouth; automatically adds newly typed words to the
+ dictionaries it will learn your vocabulary with the time.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ <sect2 id="kttsd-speech-service-config">
+ <title>The <guilabel>KTTSD Speech Service</guilabel> page</title>
+ <para>The configuration of the &kde; Speech Service is described in detail in the
+ <ulink url="help:kttsd">KTTS Handbook</ulink>.</para>
+ </sect2>
+ </sect1>
+ <sect1 id="phrasebook-editor">
+ <title>The Phrase Book Edit Window</title>
+ <para>
+ By using the menu entry
+ <menuchoice>
+ <guimenu>Phrase Books</guimenu><guimenuitem>Edit...</guimenuitem>
+ </menuchoice>
+ you open the phrase book edit window.
+ </para>
+ <para>
+ <screenshot>
+ <screeninfo>The phrase book edit window</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="kmouthedit.png" format="PNG"/>
+ </imageobject>
+ <imageobject>
+ <imagedata fileref="kmouthedit.eps" format="EPS"/>
+ </imageobject>
+ <textobject>
+ <phrase>Screens hot</phrase>
+ </textobject>
+ </mediaobject>
+ </screenshot>
+ </para>
+ <para>
+ The main area of the phrase book edit window is divided into two parts.
+ Within the upper part the phrase books are displayed in some tree
+ structure.
+ </para>
+ <para>
+ Within the lower part you may modify a selected item. If you have
+ selected a phrase you can modify the contents of the phrase as well
+ as its shortcut. If you have selected a phrase book you can only
+ change its name.
+ </para>
+ <para>
+ Actions like adding new phrases and phrase books and deleting selected
+ phrases and phrase books can be done by selecting them in either the
+ menu bar, the toolbar or a pop up menu.
+ </para>
+ <para>
+ You can change the order of the phrase books and phrases by dragging
+ them to their new places or by using the arrow keys while the
+ &Alt; key is pressed.
+ </para>
+ </sect1>
+
+</chapter>
+
+<chapter id="commands">
+ <title>Command Reference</title>
+
+ <sect1 id="main-commands">
+ <title>Commands Within The Main Window</title>
+ <sect2 id="file-menu">
+ <title>The <guimenu>File</guimenu> Menu</title>
+ <variablelist>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>O</keycap></keycombo>
+ </shortcut>
+ <guimenu>File</guimenu>
+ <guimenuitem>Open as History...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Opens a text file into as history of spoken sentences.</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>S</keycap></keycombo>
+ </shortcut>
+ <guimenu>File</guimenu>
+ <guimenuitem>Save History As...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Saves the history into a text file.</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>P</keycap></keycombo>
+ </shortcut>
+ <guimenu>File</guimenu>
+ <guimenuitem>Print History...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Prints the history.</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>Q</keycap></keycombo>
+ </shortcut>
+ <guimenu>File</guimenu>
+ <guimenuitem>Quit</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Quits &kmouth;</action></para></listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+
+ <sect2 id="edit-menu">
+ <title>The <guimenu>Edit</guimenu> Menu</title>
+ <variablelist>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>X</keycap></keycombo>
+ </shortcut>
+ <guimenu>Edit</guimenu>
+ <guimenuitem>Cut</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Cuts the selected section and puts it to the clipboard. If there
+ is some text selected in the edit field it is placed it on the
+ clipboard. Otherwise the selected sentences in the history (if
+ any) are placed on the clipboard.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>C</keycap></keycombo>
+ </shortcut>
+ <guimenu>Edit</guimenu>
+ <guimenuitem>Copy</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Copies the selected section to the clipboard. If there is some
+ text selected in the edit field it is copied to the clipboard.
+ Otherwise the selected sentences in the history (if any) are
+ copied to the clipboard.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>V</keycap></keycombo>
+ </shortcut>
+ <guimenu>Edit</guimenu>
+ <guimenuitem>Paste</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Pastes the clipboard contents at the current cursor position into
+ the edit field.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>Edit</guimenu>
+ <guimenuitem>Speak</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Speaks the currently active sentence(s). If there is some text in
+ the edit field it is spoken. Otherwise the selected sentences in
+ the history (if any) are spoken.
+ </action></para></listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+
+ <sect2 id="phrasebooks-menu">
+ <title>The <guimenu>Phrase Books</guimenu> Menu</title>
+ <variablelist>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>Phrase Books</guimenu>
+ <guimenuitem>Edit...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para>
+ Opens the <link linkend="phrasebook-editor">phrase book edit window</link>.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+
+ <sect2 id="settings-menu">
+ <title>The <guimenu>Settings</guimenu> Menu</title>
+ <variablelist>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>M</keycap></keycombo>
+ </shortcut>
+ <guimenu>Settings</guimenu>
+ <guimenuitem>Show Menubar</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ When checked, this displays the menubar. When unchecked the
+ menubar is hidden.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>Settings</guimenu>
+ <guimenuitem>Show Toolbar</guimenuitem>
+ </menuchoice></term>
+ <listitem><para>
+ <action>
+ When checked, this displays a movable toolbar containing
+ buttons used to initiate frequently used commands. The toolbar
+ is most commonly located at the top of the editor just under
+ the menu. When unchecked the toolbar is hidden.
+ </action>
+ Clicking on the striated grip and dragging allows the user to move
+ the bar.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>Settings</guimenu>
+ <guimenuitem>Show Statusbar</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ When checked, this displays a small bar at the bottom of the
+ main window containing information about the status of
+ &kmouth;. When unchecked the status bar is hidden.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>Settings</guimenu>
+ <guimenuitem>Show Phrasebook Bar</guimenuitem>
+ </menuchoice></term>
+ <listitem><para>
+ <action>
+ When checked, this displays a movable phrasebook bar containing
+ buttons for the phrasebook entries. The phrasebook bar
+ is most commonly located at the top of the editor just under
+ the toolbar. When unchecked the phrasebook bar is hidden.
+ </action>
+ Clicking on the striated grip and dragging allows the user to move
+ the bar.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>Settings</guimenu>
+ <guimenuitem>Configure KMouth...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para>
+ Opens the <link linkend="config-dialog">configuration dialog for
+ the speech synthesizer</link> and other &kmouth; settings.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+
+ <sect2 id="help-menu">
+ <title>The <guimenu>Help</guimenu> Menu</title>
+ &help.menu.documentation;
+ </sect2>
+
+ <sect2 id="popup-menu">
+ <title>The pop up menu of history entries</title>
+ <variablelist>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Speak</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ The selected sentences are spoken.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Delete</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ The selected sentences are removed from the history.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Cut</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ The selected sentences are deleted and placed on the clipboard.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Copy</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ The selected sentences are copied to the clipboard.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Select All Entries</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ All history entries are selected.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Deselect All Entries</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ All history entries are deselected.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut><keycombo>&Ctrl;<keycap>O</keycap></keycombo></shortcut>
+ <guimenuitem>Open as History...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Opens a text file into as history of spoken sentences.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+<shortcut><keycombo>&Ctrl;<keycap>S</keycap></keycombo></shortcut>
+ <guimenuitem>Save History As...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Saves the history into a text file.
+ </action></para></listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+ </sect1>
+
+ <sect1 id="pb-editor-commands">
+ <title>Commands within the phrase book edit window</title>
+ <sect2 id="pbe-file-menu">
+ <title>The <guimenu>File</guimenu> Menu</title>
+ <variablelist>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>File</guimenu>
+ <guimenuitem>New Phrase</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Adds a new phrase.</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>File</guimenu>
+ <guimenuitem>New Phrase Book</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Adds a new phrase book.</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>S</keycap></keycombo>
+ </shortcut>
+ <guimenu>File</guimenu>
+ <guimenuitem>Save</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Saves the phrase book.</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>File</guimenu>
+ <guimenuitem>Import...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Imports a file and adds its contents to the phrase book</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>File</guimenu>
+ <guimenuitem>Import Standard Phrase Book</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Imports a standard phrase book and adds its contents to the phrase book</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>File</guimenu>
+ <guimenuitem>Export...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Exports the currently selected phrase(s) or phrase book(s) to a file</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>P</keycap></keycombo>
+ </shortcut>
+ <guimenu>File</guimenu>
+ <guimenuitem>Print...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Prints the currently selected phrase(s) or phrase book(s)</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>W</keycap></keycombo>
+ </shortcut>
+ <guimenu>File</guimenu>
+ <guimenuitem>Close</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Closes the window</action></para></listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+
+ <sect2 id="pbe-edit-menu">
+ <title>The <guimenu>Edit</guimenu> Menu</title>
+ <variablelist>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>X</keycap></keycombo>
+ </shortcut>
+ <guimenu>Edit</guimenu>
+ <guimenuitem>Cut</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Cuts the selected items and puts it to the clipboard.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>C</keycap></keycombo>
+ </shortcut>
+ <guimenu>Edit</guimenu>
+ <guimenuitem>Copy</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Copies the selected items to the clipboard.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>V</keycap></keycombo>
+ </shortcut>
+ <guimenu>Edit</guimenu>
+ <guimenuitem>Paste</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Pastes the clipboard contents into the phrase book.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenu>Edit</guimenu>
+ <guimenuitem>Delete</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Deletes the selected items.
+ </action></para></listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+
+ <sect2 id="pbe-help-menu">
+ <title>The <guimenu>Help</guimenu> Menu</title>
+ &help.menu.documentation;
+ </sect2>
+
+ <sect2 id="pbe-popup-menu">
+ <title>The Pop up Menu</title>
+ <variablelist>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>New Phrase</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Adds a new phrase.</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>New Phrase Book</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Adds a new phrase book.</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Import...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Imports a file and adds its contents to the phrase book</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Import Standard Phrase Book</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Imports a standard phrase book and adds its contents to the phrase book</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Export...</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>Exports the currently selected phrase(s) or phrase book(s) to a file</action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>X</keycap></keycombo>
+ </shortcut>
+ <guimenuitem>Cut</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Cuts the selected items and puts it to the clipboard.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>C</keycap></keycombo>
+ </shortcut>
+ <guimenuitem>Copy</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Copies the selected items to the clipboard.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <shortcut>
+ <keycombo>&Ctrl;<keycap>V</keycap></keycombo>
+ </shortcut>
+ <guimenuitem>Paste</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Pastes the clipboard contents at this position into the phrase book.
+ </action></para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><menuchoice>
+ <guimenuitem>Delete</guimenuitem>
+ </menuchoice></term>
+ <listitem><para><action>
+ Deletes the selected items.
+ </action></para></listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+ </sect1>
+
+</chapter>
+
+<chapter id="faq">
+ <title>Questions and Answers</title>
+
+ &reporting.bugs;
+ &updating.documentation;
+
+ <qandaset id="faqlist">
+ <qandaentry>
+ <question>
+ <para>I do not hear anything.</para>
+ </question>
+ <answer>
+ <para>
+ Most likely you did not configure correctly (or not at all?) the
+ text-to-speech command. Use
+ <menuchoice>
+ <guimenu>Settings</guimenu><guimenuitem>Configure &kmouth;...</guimenuitem>
+ </menuchoice>, open the page <guilabel>General Options</guilabel>
+ and enter the command for speaking texts on the tab <guilabel>Text-to-Speech</guilabel>.
+ (See section about the <link linkend="tts-config">configuration
+ dialog for the speech synthesizer</link> for more details.)
+ </para>
+ </answer>
+ </qandaentry>
+ </qandaset>
+</chapter>
+
+<chapter id="credits">
+ <title>Credits and License</title>
+
+ <para>
+ &kappname;
+ </para>
+ <para>
+ Program copyright 2002-2004 Gunnar Schmi Dt<email>gunnar@schmi-dt.de</email>
+ </para>
+ <para>
+ Documentation copyright 2002-2004 Gunnar Schmi Dt <email>gunnar@schmi-dt.de</email>
+ </para>
+
+ <!-- TRANS:CREDIT_FOR_TRANSLATORS -->
+
+ &underFDL;
+ &underGPL;
+</chapter>
+
+<appendix id="tts">
+ <title>Examples for the text-to-speech configuration</title>
+ <qandaset id="ttslist">
+ <qandaentry>
+ <question>
+ <para>Festival</para>
+ </question>
+ <answer>
+ <para>
+ Festival is a text-to-speech system written from the University of
+ Edinburgh. It currently supports English, Spanish and Welsh speech.
+ Its license allows to use and distribute Festival free of charge
+ without restrictions.
+ </para>
+ <para>
+ In order to create the command line example for the text-to-speech
+ configuration we assume that Festival is installed in the directory
+ <filename class="directory">/usr/local/festival/</filename>. The
+ command for speaking texts then is as follows:
+ </para>
+ <para>
+ <screen><userinput><command>/usr/local/festival/bin/festival</command> <option>--tts</option></userinput></screen>
+ </para>
+ <para>
+ The option <guilabel>Send the data as standard input</guilabel> must
+ be enabled.
+ </para>
+ </answer>
+ </qandaentry>
+ <qandaentry>
+ <question>
+ <para>FreeTTS</para>
+ </question>
+ <answer>
+ <para>
+ FreeTTS is a speech synthesizer written entirely in the &Java;™
+ programming language. It currently only has support for English
+ pronounciation. Its license allows to use and distribute FreeTTS
+ free of charge without restrictions.
+ </para>
+ <para>
+ In order to create the command line example for the text-to-speech
+ configuration we assume that FreeTTS is installed in the directory
+ <filename class="directory">/usr/local/freetts/</filename>. The
+ command for speaking texts then one of the following three examples:
+ </para>
+ <para>
+ <screen><userinput><command>java</command> <option>-jar /usr/local/freetts/lib/freetts.jar</option> <option>-text %t</option></userinput></screen>
+ </para>
+ <para>
+ <screen><userinput><command>java</command> <option>-jar /usr/local/freetts/lib/freetts.jar</option> <option>-file %f</option></userinput></screen>
+ </para>
+ <para>
+ <screen><userinput><command>java</command> <option>-jar /usr/local/freetts/lib/freetts.jar</option></userinput></screen>
+ </para>
+ <para>
+ For the third example the option <guilabel>Send the data as standard
+ input</guilabel> must be enabled. (This one is the preferred example
+ for the use with FreeTTS.)
+ </para>
+ </answer>
+ </qandaentry>
+ <qandaentry>
+ <question>
+ <para>MBROLA</para>
+ </question>
+ <answer>
+ <para>
+ MBROLA is a speech synthesizer for a large number of languages. It
+ converts a list of phonemes to a wave file, so you need some other
+ tool to convert the text into a list of phonemes. The license of
+ MBROLA allows to use and MBROLA free of charge for non-commercial,
+ non-military applications.
+ </para>
+ <para>
+ For our example we will use Hadifax in order to convert German texts
+ into a list of phonemes suitable for MBROLA. We will assume that
+ Hadifax and MBROLA are installed to
+ <filename class="directory">/usr/local/hadifax/</filename> and
+ <filename class="directory">/usr/local/mbrola/</filename>.
+ </para>
+ <para>
+ Unfortunately Hadifax tends to swallow the last character of the text,
+ so we may want to add an additional character to the text. The complete
+ command is therefore more complex than the previous examples:
+ </para>
+ <para>
+ <screen><userinput>(<command>cat</command> <option>-</option>; <command>echo</command> <option>&quot; &quot;</option>) | <command>/usr/local/hadifax/txt2pho</command> <option>-f</option>
+ | <command>/usr/local/mbrola/mbrola</command> <option>-e</option>
+ <option>/usr/local/mbrola/de1/de1 - /tmp/tmp.wav</option>;
+ <command>artsplay</command> <option>/tmp/tmp.wav</option>; <command>rm</command> <option>/tmp/tmp.wav</option></userinput></screen>
+ </para>
+ <para>
+ All parts of this command need to be written into one line. The option
+ <guilabel>Send the data as standard input</guilabel> must be enabled.
+ </para>
+ </answer>
+ </qandaentry>
+ <qandaentry>
+ <question>
+ <para>The &kde; Text-to-Speech Daemon</para>
+ </question>
+ <answer>
+ <para>
+ The &kde; Text-to-Speech Daemon (KTTSD) is a &kde; wide text-to-speech service
+ which gives &kde; applications a standardized interface for speech synthesis
+ and is currently developed in <acronym>SVN</acronym>. It uses plug-ins in
+ order to support various text-to-speech systems.
+ </para>
+ <para>
+ As the configuration of the speech synthesizer is done in KTTSD the only
+ &kmouth;-specific option you need to activate is <guilabel>Use KTTSD speech
+ service if possible</guilabel>.
+ </para>
+ <para>
+ Of course you need to configure KTTSD. You may do this with the configuration
+ page <guilabel>KTTSD Speech Service</guilabel> that is added to the configuration
+ dialog of &kmouth; if KTTSD is installed.
+ </para>
+ </answer>
+ </qandaentry>
+ </qandaset>
+</appendix>
+
+<appendix id="installation">
+ <title>Installation</title>
+
+ <sect1 id="getting-kmouth">
+ <title>How to obtain &kmouth;</title>
+
+ &install.intro.documentation;
+
+ </sect1>
+
+ <sect1 id="requirements">
+ <title>Requirements</title>
+
+ <para>
+ In order to successfully use &kmouth;, you need a speech synthesizer
+ (and of course &kde; 3.x). &kmouth; uses about 15 MB of memory to
+ run (plus the amount of memory needed by your speech synthesizer),
+ but this may vary depending on your platform and configuration.
+ </para>
+ </sect1>
+
+
+ <sect1 id="compilation">
+ <title>Compilation and Installation</title>
+
+ &install.compile.documentation;
+
+ </sect1>
+</appendix>
+
+</book>
+<!--
+Local Variables:
+mode: sgml
+sgml-minimize-attributes:nil
+sgml-general-insert-case:lower
+sgml-indent-step:0
+sgml-indent-data:nil
+End:
+-->
diff --git a/doc/kmouth/kmouthcpref.eps b/doc/kmouth/kmouthcpref.eps
new file mode 100644
index 0000000..69d8d47
--- /dev/null
+++ b/doc/kmouth/kmouthcpref.eps
@@ -0,0 +1,3026 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: GIMP PostScript file plugin V 1.15 by Peter Kirchgessner
+%%Title: /local/src/kde32/kdeaccessibility/doc/kmouth/kmouthcpref.eps
+%%CreationDate: Sun May 30 14:52:34 2004
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%Pages: 1
+%%BoundingBox: 14 14 596 357
+%%EndComments
+%%BeginProlog
+% Use own dictionary to avoid conflicts
+10 dict begin
+%%EndProlog
+%%Page: 1 1
+% Translate for offset
+14.173228 14.173228 translate
+% Translate to begin of first scanline
+0.000000 342.077918 translate
+581.132369 -342.077918 scale
+% Image geometry
+581 342 8
+% Transformation matrix
+[ 581 0 0 342 0 0 ]
+% Strings to hold RGB-samples per scanline
+/rstr 581 string def
+/gstr 581 string def
+/bstr 581 string def
+{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
+true 3
+%%BeginData: 190519 ASCII Bytes
+colorimage
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+g]%?3[%r82QAYj0XMsmas+14"s*t~>
+g]%NDd`T;<]"Yn.]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"YbiBtD$i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%qcJJDKs+14"s*t~>
+f`)*Js7ZKmJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds(;!)pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+p4<6ps3^js~>
+h>[fLUk=SXMh?q?K7Af3Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh>c&K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?Mp6hQJcF:#J,~>
+h>[NHb(7-c\cKP)JcC<$ec1.~>
+g])iuO7n/)JcF7"J,~>
+hZ!r-Mh?q?Mh?q?Mi3(;Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q(K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YAXmXbChs4@:$~>
+hZ!W5^4EkT\cKtEJcC<$fDg@~>
+h#@EKs8M]os7Z0drq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6En
+pAb-c!WVkEs+14#s*t~>
+q>UNQ[&!)I"-iNZ]n(fnK*.&"s3:P$!/#i\JW&iP".Z13pA"Z<~>
+q>Vc+d`T;<]"Yni^:M%i^:M%i^:M%i^:M2Ts44ci]!f2Y]!f2Y[XYls]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!cUi[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^ro]pAa-`\pqH*^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:Jg.]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Y`p^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i`ld<7q#>j~>
+pAYj#s7ZKmpAajdpAajdpAajdpAaj[rr7QCM>$rKrUta@pAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAai9s7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd(]X4/pAajd
+pAajdpAajdpAajdpAajdp@eN:~>
+qu7W'Uk=SXMh?q?K8YA?K8YA?K8YA?K8YA?ec4KWK8>-]SH&V=P`(0PK8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?ItNZ3Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?M]RM/
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?`W#l;^&@t]~>
+qu6]fb3QVL^?5I\]!f2Y]!f2Y]!f2]J$uqs]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y\oY<k[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roes8TgE]"Wa,J\('V!P[FirrCdOs*t~>
+q>]aRrr<#l!<<&l!<<&l"98)gs8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8;Qjs8M]ms7ZHlrq6?lJbFZgkP"]NJ,~>
+r;Rb]Mh?q?Mh?q?Mi34GK8YA?K8YA?K8YA?MuWg8JU<0!"jR(lH\6s#Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?IuAr;K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K--#(Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mkp(Hs-3N_J,~>
+r;QfS^?W9?^An5IZF7'IZF7'IZF7'EJ$uYkZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZ?*I[[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?Iir@l@]!d1$J\(!T"NpH<s2+d8J,~>
+qYpTis8M]os7Z0drq6?lrq6?lrq6?lrq?BlJbFilrr3)gp@eOcp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lpAY'lpAY)B~>
+rVlr4K7!QL"+,[%hZ!3Lc(t>k!.4Wr"FIi^eT:_:!-A-d!-A$a!-A-d!-A-d!-A-d&9E2NXJBT?
+HZOO\@VVF7K6.$=!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-ds8W+G!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-ds8W+G!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A'b!-A-d"`o$Ks5n\,K)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK*-IQXPWsM!R7G>K)g8tK+rZbK?a,ipAajdpAajdpAaj2
+K7eOMK+?0"s7ZKds7ZKds7ZKdc2N>"Mt[2N9)npA~>
+rVm5U]!f2Y[^roYcKbE&%c5LB[^roY[^roY[atK@jK\nJ!#/+`rNZQ_9G@Id]s@\<]<_J:^Tr@'
+s73>$]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f1c[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^scLrq8A/
+cFUHq[^roY[^rp(pA4LZpA4LZpA4LZp>3Bh[^roYhY-g>qY'dZqY'dZqY&dW[^s'Ds8SAas*t~>
+r;ZTdqZ$<`rr;'Q"B#4:C;p/F"N>*m!)gN(s8T_)s8Th,s8N)eJbGT,qZ$<`o)JU\o)J[^rr3&f
+s8RT~>
+rr3GXK6r5tK7eNHc0kW*mf)>W`M@j5H\6ZtH\9TCUucY.;ZG#As5p+\>,:Tds3:R9q/cN7mW8C-
+!d"DAj)b8#!s!EBs5S2#s8I*>s8R0>s8I*=s6k%/rrW7Bs8TrW!Ug!eH[gZpK6r5tK6r5tK6r5t
+K6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5t
+K6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6q6`H\6Zt
+H\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6Zt
+H\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH_epSs7Ym[jq#G,H\6ZtH\6Ztk5Y/Tp@eIQ
+r8nB6K7eN'HfkA%s7Z0bmel2RH\6ZtPlLcs3WFU~>
+rr2u\qR-RIhX:72mf)JPg;`rs+6*=CZECL9ZECL9ZECL9Y-P49Y-P49Y-P49Y-P49Fo24A&7Ju]
+qu@"FY-P49Y-P49rVmM5ZECL9ZECL9ZECL9ZECL9ZEF3,9s4NrZECL9ZECL9ZECL9ZECL9ZECL9
+ZECL9ZECL9ZEF6-!3ZA%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZEF6-ZECM5s/r[,rrTL/
+ZMsl-ZECL9ZECL9ZECL9ZECL9ZEF6-!3ZA%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9
+ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECM(s0Aq][[so2`np.[o'ZMB!SYQh[LVTrpAb!_
+o()5:lK[NslMJ""lLsrOqY'LNmdBB*k3D71[KXPJs43&,J,~>
+rVuWc!<<#k!:KUTs8W&k!:Kj[!:Kj["7GmVmf)n[mf)n[mf)n]me3a[!!='rM\u?l"/PYamf)n\
+me6VZs7QH\rq6?[rq6?[rq6?[rq6?[rr3,hs8Vf\rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6Wc
+s8N)es8Vf\rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6Zds8Vf\pAb0\pAY*kpAY'mp?qqR!:Kj[
+!:Kj[!:Kj[#k%`m!:Kmep?qqR!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:KdY!:Kj[!:Kj[s8N,nmXb)$p&P-kp&OOSpAFpkpAb*b!q,dMqY'je!VZQlp&a[UmeleX
+rrM9^J,~>
+rr2tVqg/aAhWFP3s7YmCk2+XQqKiD>s+>B6CAr8SCAr8VC3+H2rc8'Src8'Src8?[F)ssT]qhaS
+rVm,AXIQu*8onbHErg#sqZ$P9!,DLS!,DLS!,DLS!,DK4!s&B$!<.$>CAr8SCAr8SCAr8SCAr8S
+CAr8SCAr8SCAn/7F8u7?rc8'Src8'Src8'Src8'Src8'Src8'Src8E]F8u7?F8u7?!-A/>!W[:V
+rr2rurc8'Src8'Src8'Src8'SrVlt@s8N)uEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSErp)tCAr8SCAr8WC=W?KF+J\1HOQG$k4\iTp?q)*hURkeHNVg\me6SY
+s7ZHS!S)8hHNVg\me6SYs7ZHS!S)8iHN_Uns#L+0~>
+rr4"QZF7'IZEh@(lLt8Xo'Yf.inhPX[^*?I[^,W,]&g'tFTB!a*;]^=*+?DYFo&9;s7*8jrrW9$
+rrD/`rVlu&s8N)[Y5eM+!3ZA%!!'2$rrN2'Y5\G$!:d5jrr]G(rrBs>J*-dJWj]4AZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZ@96f[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I_VXSOs8VZXlK[Bc_QpVU[^*?IhWjP&
+s8Dctp@@M6k2-*C#I^qHhWjP&s8Dd)p@@M6k2*DL[^*@$s8RrUJ,~>
+rr;ff!Uf[[s8M`lmeQSUs5iqWU]A);)#F:9+C`"aV#'f]s7,g]rrW9$rrD0SrVluns8N)[pAb-s
+!;?Hm!!)`lrrN2opAY'l!:fd]rr_uprrBt1rr2u\JbG]/!Uf[[s8M`lmeQPWme6GUs7ZH[r:U0Z
+pA"[fpAXLYpAY'mk5Tr~>
+s8N,MF8gLjF*i88hX9h2rsA,UhWE@iHZOOTrd4\FjD#3'k$$Wu]p,U_Pf;M9;XRH[CB+>4!<<'"
+!,DK4rbDB2s(_N4"T\T&!,?9Hs8Qj6s8Qj6s8Qj6rrQs8CAe)3CAn/9!<<'!C23_IrbDB2nnS4)
+"p"]'!!$bKrr3$"C23bJ!WZtMrVuk3s8W+6s8N(6rVlitr;X`N"MOi*F*%>-!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d"`o$lhX9h0!!V6AeZ=+=rd+ijHbJS(me6SY!:KjK
+$b^"rHZOO\^#nJFpAFpjmf)>U]jc>0H[C\Ns/\52~>
+s8N)]qQ^4ChX9t6q??<Pk3Cg?qQg/$1od^YY,\Y)Y,\Y)Y,\M)WiiA)WiiA)WiiA)Wih$U=k;<<
+OfFP']%5S8!/7GUWiiA)s8W#ts8N*"Y5SA%WiiB"rrK.&rVm$$s8N)!Y5J;0Y,_O%Y,_O%Y,_O%
+Y5b[&rrB5#rriE&rrB(%rVlr!Y,_F"(TOX<Y,\Y)Y,\Y)Y,\Y)s8N*!rr<&!Y5\G&!334$rrN2#
+Y5SA,WiiB%s/rC%s/u>#!!)rs5cUueY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y1EWmV65BTTX"[>hX9t4!!DBKhST,p&'F2&meZt[s8)T_lK76O
+U&;2,b3J9[qZ$ElqYKdJk2sg[rNZR?s8UAqJ,~>
+rr;ig"6T%FpAY*lp&jaVk2uO6s8W,m1@Fl(p?qYBp?qYBme6)Bme6)Bme6)Bme6)B]`;6mhS#/T
+Pa'/DhGO?mme6)Bme6\\r;clt!<DilrrVW^mem(cme6VZ"T\T&!:KRYrsnbjs8Vf\s8Vf\s8Vfm
+pAFpjpAP!p!<<'!me6VZ!q,dMr;RT$p?qYBp?qYBp?qYBp?qt\!<<'!!:KR[rrN2gpAY'n!:KRZ
+rsA,emf3=\mf3=\rVlitr;T%Mp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYSs7YUCJbGc1"6T%FpA=mmme5f*qXsp>rq?6hs7QQ_p>4[(p&NYB
+pA=mip&jaVhVS5)rVllJJ,~>
+s8N(pqf;mm^#nJNrVm&hhVRD.KDT`irrHkDrb;FBrb;FBqe?+?rb;FBrb;FBrb<!RC5]0XMj2cl
+e_Z4KMl_hGrb;gMC23eK!,?7XC&e82s8Qj2s8Qj6s8N*!rrE+7qu6s&CB+;6CB+;6CARr1!<3!(
+CB+;6!<<'!CA\&2CA\&2C&h`BC&h`BC&h`BCAn24!<6d6@f?<,CAn/5!,DE2s(_T6#ln`?rr?g6
+rr<&rs8Qg6@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@f0s@@fC*H
+@VTYBs35;0F.dRVK>$F0q>^WSk.QEEEr`<@jpUn_rr<'!p>4roXCD*K!3H1^rrE#trrE)]!N]c.
+Es(k1p*kL~>
+s8N)AqlUC6`ocRWqZ$Ecmc*6k`qlk<s5U*g,WLpGOk0Q`er>fO3$e@#s8N'!rMoktqu?\rqu?\r
+s8W*!s8N*"Wr)f&!36)!!36)!!35nq!!*#u#cdq)!!*'!!35qrs/Ptro;_chrrE%urVlktrVllu
+Wr)hrWrN)*!36)!!36)!!!)or`i9-Xs5KT#Y+Vp"ZGu%lq>^TVlGi\'!4r0l$hjGs!!)ldio]C7
+Q2Icb])Ljl!"&]%s7u]qk2s7?r2p.qs7U/W~>
+s8W&k#4D3Ymb[[2r;QromdBf*k5=oSmf3=Ip'i`:P`(dVs4,taP`%OVqY'sh!!)ukrrDrrs7Z?i
+s7ZKmrrE*!!<Dijrs8]!s8N)ms8N)mqYpNqrr38ts8N'!s8N)mqu?]iqu?9]rVultrq?<j!;?Bk
+!<Dijs8Vfmrs8]!s8N)ms8N'!qu=\0rr2uTrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6N`p?pf2pA+akme5N"rq6Qap@d&1p?qq[rrE*!#4D3Qc.2OUrq6NGp@dnS!<)rt
+!!Dr_c.2dd!:Kjd!3C\~>
+s8NX_C3+-2C3,$PhWF8+pAaj[rn[t#HYRV:F)#drs5RPt9(&5+hNY++Phsrdk">JZs8N'!r*o^+
+r;clt&Rte?!!*'!!+Q!.!+Q!.!<<)u!<<',!+Q!.!+Q!.!+Q!.qZ%%6s8N*!rr?O.rrE*!r;clt
+#@d`5!!*'!!<$C*s86@(s8?F*rr<&trrN3#s8;rtrtAlArr?O.rr?O.rr?O.rr<'!rrC)KJ#r[?
+@VTt!F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2
+F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2
+F)#c2F+7qGC3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2
+C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-Bc/.R_!;?Hd!!(m4
+`Hu?@C3+-2MrrRHmf34c%dr3(k)3DaF)#c2MrrRHrW!!!pAP%#e`McnF)#c2F3Xab0n9~>
+%KH:9WiiA)Wii2Lk2u76q@<5iio9+GTrP8qY,\Z)s5TpbJH/6perctpNS;rS!.k!Cs8N'!r2'Gn
+r;clt&Z,O-!!*'!!2]_q!2]_q!<<)u!<<',!2]_q!2]_q!2]_qqZ%&$s8N*!rrAnqrrE*!r;clt
+#GqJ#!!*'!!<&bms88_ks8Aemrr<&trrN3#s8;rtrtD7/rrAnqrrAnqrrAnqrr<'!rrC*9J("A6
+RAI'dY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y(*ISWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)Wii@uf&l)p!;cQc!!)$@
+cCq8@WiiA)U#t(go(r:b%eAW5k+Rp?Y,\Y)U#t(grVuuqpAP%#g?,)kY,\Y)Y2]K]@=S~>
+rr;lh"O6)sp@eFarpBgDc2757s#f`Cme6)Bme6)Bme6):p?qYBp?qYBp?qYBp?qYB`;iNehNY++
+Phsq_!58*op?qYBpAb-mp?qYBpAb0k!<<'2mf3:e!<<'!mf3:emf3:es8W&us8NH,mf3:emf3:e
+mf3=a!"AT$rrE*!!:Kme!<<)t!<<',mf3:e!<<'!me6)BrVm#gp?qYBr;Qlep?qYQrr<&trrN3#
+s8;rts&/:brrDKerrDKerrDKerr<'!rrDK\me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)BpAaj:mXb)*p'&_'me-V\rr;uus6]pEc272<^%UUVpAb'k
+"nqBHp:]#Sp&i#%k3i3Ks8W&u"6T<jebo.?rrAjF~>
+s7ZJ-!+PqB"(HW6k4eptk1+ff@VT@eCB+<C>%1ZE>%1ZE>%1ZE@Tm5E@Tm5E@Tm5E@Tm5E@Tlst
+XH^Eue\-mBk#u4t@Tm5E@Trg3!*Wi8@Trg3!*Wi8s8N*!rr?O.rr?O.rr?O.rrE*!!*Wk3rr?O.
+rr?O.rr?O.rr?M3qu7T8s8N(.s8N*!rr?53>6"U&s8N(.s8N(.>%1\6s)S0D@Tm7@rrE*!!*Wi8
+s8N*!!<3'!rrE*!!*Wi8s8N*!rr?O.rr?O.rr?O.rr?O.rr?M3@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E^&O!oC1@0W!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB#CG=ihX:+;pAP$qe`PD/@Uf=O"_)i8e^a*b!<:RXhKrF8
+C2.3mHf!<'me["aeHOfV>%25UrbDK5!%EE~>
+!VZBdWWJIFk4eoYk1Z)or2TesBVhE!Tr"HZTr"HZTr"TZV4j`ZV4j`ZV4j`ZV4j`ZD#bPq])U?m
+E?"sqV4j`ZV4j`Zs8N(mV4j`Zs8N(mV4mqh!<<'!V>pPqV>pPqV>pPqs8N(mV>pPqV>pPqV>pPq
+V>pPqV4med)Z]p<!2]_q!<<'!Tr"I_rrE*!!2]_q!2ZBcU&G"3!266_V>pPqs8N(mV4mqh!<3'!
+!<<'!s8N(mV4mqh!<<'!V>pPqV>pPqV>pPqV>pPqV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4lK?^6POGWhHEtQ/^rco(MqRrW!)Xk1Z)or2Kmb
+inE8WqZ$cUg>\B[r2KmbinE8WqZ$cUg>\B[ql9\r!+CB~>
+s8NDnp?qYBp?o<Up@nUpp?''Vme6)Bmf3=dp&OO[p&OO[p&jaVp?qqR!:Kj[!:Kj[!:Kj[%.9nk
+(j!Cje\-#H!1a&^!:Kj["Rc<i!:Kj[0(/c>!:KRSs8N*!rrDcmrrDcmrrDcmrrE*!!:KR\rrDcm
+rrDcmrrDcmrrDcdqu7H4s8N)ms8N*!rrDK\pAb-ms8N)ms8N)up&OOZs"aZKp?qYSrrE*!!:KRS
+s8N*!!<3'!rrE*!!:KRSs8N*!rrDcmrrDcmrrDcmrrDcmrrE&l!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6Qas8VfCmd>Sume6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6'Xp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qX]me6)Is8E!*me5eVmdBf:p?o<emK!:a!<2Bk[+4U4
+p?qX]rpBddqZ-W`$FJ@Op?qYBpAb/_J,~>
+%/0+(@VT@e@VTB7hVS)/rn[oi>&%M]@VYrCi*$B1s37XPc2Z&_>6"U&!<-1#rr<&u>6"UL!<<'!
+>6"U&>6"U&>6"U&s8N(&>6"U&>6"U&>6"U&>6"U&>6"X%!<<'+!<<'!>6"U&s8N)u>6"U-!<<'!
+>6"U&r*'%!rEB7$!ruO)s8H4%rsAc+!<3'!rrE*!!<-1%rt>D4rr?7&rr?7&rr?7&rr?7&rrC)C
+"K_Wf>$?Dj@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@aC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe@clP(k4\NJ
+!!)0\h?m^qC1:peC1?&EebK1Tc/)o-C2.3m@Ue3=e`QT(!"S/Ac/)o-C1:peC1@5C.=_~>
+s7Qf"V5gAlV5f73injM3/DfCKKpes;Whl`qs.,jSTq.mJTq.mJTq.aJSY;UJSY;UJSY;UJSY;UJ
+SSe0&%r%`.Tq.mJTq.nWrrAa`U&G!B!25sWs8N*!rrAVirrAVirrAVirrE*!!25t`rrAVirrAVi
+rrAVirrAVis8E#uru;%=rrAVirrE*!!25sWs8N*!rrAVirrAU`SY;VQ!&:1<Tq25`!1j/iTq.nW
+rrE'!rrE*!!<<'!Tq.nWrrE*!!1j/i!1j/i!1j/i!1j/iIfQ%5SY;UJSY;UJSY;UJSY;UJSY;UJ
+SY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJcMtbDSZ8NdV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV15MAWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhh&BV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAGk2P7_o()b[%dMp1k(T5'V5gAlL#U\;q#CoUie<Al
+Whl_lL#U\;lLOlR%dMd!ie<AlV5gAlV>pC#J,~>
+s8Vrh!2TV^q>gN_!MnlUpAb.8me6)Bme6)Bme6)BmdBf:p?qYBp?qYBp?qYBp?qYBV"k!$SG)CE
+me6)Bme6\\!;>jSrVnDKp?qYSrrE*!!:Kme!:Kme!:Kme!<<'!p?qt\!:Kme!:Kme!:Kme!:Kme
+rW)uu*!$$=!:Kme!<<'!p?qYSrrE*!!:Kme!:KRKp?qkZEVAhomf3:emf3=\me6\\!<3'!!<<'!
+s8N)mme6\\!<<'!mf3:emf3:emf3:emf3:eme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6ASp=8;Vp7_0[V#Kc`pAb0l!!)`lmK'-Gr:U5gmcNs5
+!!DBOUt,D:"f1SKme6\Z!!W)ak3f%qqtC'i!2P,~>
+%Hd(^@Tm5E@Tlslk1/Vl!'ou&k06e->%1ZE>6"V3;Hct%;Hct%;Hct%>#JO%>#JO%>#JO%>#JO%
+>#JO%;IZa-s/]Br>#JO%>#JO%>#JQ#rr<&rs8N*!rs\s3s8N(&s8N(&s8N(&qu6Zs>5S='!*]F&
+!*]7!#QXo)!*]F&!*]:"rrE*!*<9:Crr?5#>#JO%>#JO%>#JQ(rr?5#s8Q8#s8N)urr`?%rr?7"
+s8N)rrsJg1s8N(&s8N(&s8RQK>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#N'6HW"<V@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5j>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE
+>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE
+>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE3*Kcp@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@TqXNe`Q;n!!)HTe`P+S>$>B=@Tlsle^aHq%b9E>;Hd75>%1[le^a*Ur;[>qe^`M[
+;HdO5@Tm7/p*kL~>
+s7-PkV4j`ZV4i=ok2,D$!&*csk14g?Tr"HZU&Y.hSY;UJSY;UJSY;UJTq.mJTq.mJTq.mJTq.mJ
+Tq.mJO[T-J$qQAOSY;UJSY;UJSY>o[!!)orrrE*!%03+%rrAbmrrAbmrrAbirrE+nqu6g"U&Y,m
+U&+cp!<<'!U&Y,mU&4li!<<'>!29Gm!25sWSY;UJSY;UJSY?)`!25t`s.Q"`rrE&u"9AK%!29;i
+rrDrr9E:ddrrAbmrrAbmrrAa`Tq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJ
+Tq.mJTq.mJTq.mJTq.mJgAeUDTqQt4Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZ
+Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZ
+Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"H,V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`6hWE\[md^>Xo'YAsep3COV4j`ZIH&u7q#CoYidHf[Tr"HZIH&u7lL+TN%dMd%idHf[
+V4j`ZV=sUkJ,~>
+s8NJpp?qYBp?o$Mp?))H!&+'6p?&1-me6)Bmf3=\me6)Bme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+p?qYBhJ2uh$u4>dme6)Bme6)Bme6MW!!)orrrE*!%06,%rrDcmrrDcmrrDcirrE,nqu6g"pAb-m
+pA4dp!<<'!pAb-mpA=mi!<<'>!;?Hm!;>jSme6)Bme6)Bme6\\!;>j\s7Ym\rrE&u"9AK%!;?<i
+rrDrr9E=edrrDcmrrDcmrrDc\p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBs8VfCmd>Sume6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6'mp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qXUme5f:pAY*ms7YmSk+pl%p?qYBV!dC-q#LH_%&DGAme6)BV!dC-p@eFb%ef&Qm\JD$
+p?qYBpAb/_J,~>
+s5j;jr`TS:>$=P"hUU0ErW!/jk2+sr5t_)Z"(L-eF8f&;9)_]g9)_]j8lAPZr_`_gr_`_gr_`_g
+r_`_gr_`kk0f`-(r_`_gr_`_gr_`bh;Z6Xp!!#pqs8N'19)nnk9)nnk9)nnk9)nnk9)JVi!(p/e
+rrrHqs8N'k;Z?[u!<<'!rr3-os8N'k;Z6Xq!!l3srr>[krr>[j;?0>g;?0>g;@H1trr>Yh;ZHbp
+s8N)urriE&rr>YhrVult!D68frrE*lrr36rs8N'ks8N'kr_`_gr_`_gr_`_gr_`_gr_`_gr_`_g
+r_`_gr_`_gr_`_gr_`_gr_`_gr)*Mer_`_gr_a!Gs&r;u>$>D7=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=pAG>9!$n"ebnhGk2+sr5tY<a@Tlr$k0;H=r9agPe]m5B8m5^'=p..R
+c.1tR!!Lisk!;W<=p/;<md;f[~>
+s6f`W"b",EhVRPs!!`#Zio[shNVoJ.lMn/\R@Tb:R@Tb:R@Tb6SXH%:SXH%:SXH%:SXH%:SXH%:
+SXF2+SXH%:SXH%:SXH%:SXH&Is8DuuSc/Tg!"bRurrAJerrAJerrAJerrAJarrN1gSc&Kl!1Ele
+!1BDWrrW9$rrE&u"e#Dj!1BDVs8N'ARK*9eRK*9eR@Tb:R@Tb:R@Tb:RK*9eR@TcGs.02i!<3!%
+!<<'!R@X<Vrr<(fSc&Kg!1Eid7[a;V!1Ele!1BCGSXH%:SXH%:SXH%:SXH%:SXH%:SXH%:SXH%:
+SXH%:SXH%:SXH%:SXH%:SXH%:SXH%:SXH&.s.PF?JYAd2#(=5FhVRPcrpg6Xio[shNVoI\D<BR/
+lL+*2mdBAsg?*73r1O71k1\\WqZ$cUg?*73qk4)bnmR%~>
+s8W)l!:Kj[!OUDVmJut[!!`JsmdAVihZ!3Rme6\\p?qABrpBd[rpBm^mdBfJmJut[mJut[mJut[
+mJut[mKE7OS>>lXmJut[mJut[mK3+Mmf!1b!!)Hcs8N'1mf3:emf3:emf3:emf3:emed"c!:K:Q
+rrrJks8N)emf*4g!<<'!rr3/is8N)emf!1c!!hrlrrDKerrE&d!;?E[!;?E["SV9`rrE&ds8N2h
+s8N)urriE&rrDKTrVults6fgb!<DQers.ulrrDKerrE&d!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!qu'UrpBd[rpC$bs8VN;k4\6Bp&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&sgWp9`BLmf2tfs7ZKdmdAVihY-C:p(*DUk3hsCpAajdp?q)2Ph#a+
+"n%WCk3hs?!!M`PmZc9$p''mXpAb/gJ,~>
+s5"&[>#JO%>#It-k5O4,mJutKmcNYH0iCnQ;Hcu*s/\gj8lA8Z8lA8Z8lAPZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'jc!!>hk8lGTf&kZ%o!!#nh!!#nh!!#nh!!*'!rW)uu
+!ru4k;Z$M!;G$oh;G'jd!!?+!!)!4j"\Jap;G'jc!$Y$58cSih8cSih8lA8Z8lA8Z8lA8Z8cSih
+8lA7]!)`ds9)\eo8cSih8lGTf"%lH`;Z$Lq;G-og6qRFZ;G$oh;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;H!Pp8kOS:;Hct%;Hct%;Hct%;Hct%
+;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%
+;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct.>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>"WPlrn\:U!!)HTk2pD5;Gp[r>#IB;hUVE%s5")C
+8lAPj;Hc*;hUVT*s6fjds5")C8lAhj>#JPdjsbf~>
+s6BHOs+q3Iinihc!;?!Ok2qY7NVo=Kf)O%>RJd-aRJd-bRK!9eRK!9eRK!9eRK!9es8E#urr<&u
+RJ['bRK!9dRJm0gR/d5TrW!"f!!*"dr;chbrrE(errDYYrrE"crr<.h!!&Gd!!8Pg!</Db!<&>`
+!<8Jd!!\hk!1B5T!6CQ2ScA_<NIdXnSc=NUk2P7[mJm7XmcNYkAW?VY"(gKOhY@0OiW3VIr1*q$
+io8ho!!2NYrW)uX!G.,bScA*X@=S~>
+s8NDnp?qYBp?pJ4pAXIirrE)mp?qXUPhtj%me6)Js"s0;me6)Bme6)Bme6ABp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYQ!!DZ_me6SZ'(5J]!!)`\!!)`\!!)`\!!*'!rW)uu
+!s&&_pA=mpp?hn\p?qYR!!Dop!:Kgd"mu?jp?qYQ!$^k)mJm7\mJm7\me6)Bme6)Bme6)BmJm7\
+me6&K!;6Bmmf!1imJm7\me6SZ"7GmNpA=mkp?qn[7d^6Vp?hn\p?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qt\`RXDEJ+i=(me6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmU>hWp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp=68<rpC<s!!)`dme3`HhX:+*p?n1EmeHk_mK]!,
+mdBf:p6>RErVuums8E#umL#3/me6)Bme6\\S:C~>
+!T)B&;@Y^Ok2+tWmdBf2k05>89)MQiHiN5#62jIV62jIY5tXa8r^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m2W9)APi!(ojLr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m5X8jWGK!($TV"[S(H]fA]9;P-hs3L&[_hW=e<p?(M^.61#u
+;?/0FhY@-RhW?7Qr)*MDrndYTrpC!a!!(m<.7*i/!p8>gJ,~>
+!UAhCSITM:k2PC_mdfr:lIK*TOo1bL[f>c`Q'mo*Q'mo*Q'mo&R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*RJQr5!0rt;R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+-^g6fQ'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'moOs4VaXR=Up%SITM:k2PC_!!)TXlIK*T
+Oo1aP<T`<#q#LHW!EG!SSHW$Uio0q<rpC!]!!)0D<JgUD!q,>^J,~>
+s8NE!me6)Bme6@U`Vo6)p(.2sp?%:7hY-C2me6ASs7ZH[!;?E[!;?<X!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!qu'MqYpTsme6YJ
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;??Y!;?E["SV9Ws8RSUhX:+*p?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qWcme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BXMt/+rr<K-p@dX,XPW[=p?qX,rpKR^s6^,Ec1^l!
+p?mS4mf*8"pAajd!!)HTK?a,Xp?qYBs8SmF~>
+FNr?.;G'hZ;G'PI0pLhWk2uC2mZ]FK3D)nA8lA8Zec1P"5tXF85tXF85tXa88jQ'88jQ'88jQ'8
+8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88c\kj
+rW%F?5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXFm8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'89'6.g5tY$I;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8g.));G'hZ;G'50Pigibk4\N:PVF:@8kMuR;G&(g
+k2,7_rU(6jmcNXS5tXaI8l?egk2,7_rU(0hmcNXS5tY$I;G'j;hC3s~>
+!TN8;R1=pVWoiI/lLsr>Wa/GHOo(OJk5W0!PlLg`s8E"LQ/Ru3RI:*TI>rfGT:$1C?)m&LlK\*:
+m]'PhH'/#m%nu!Fk3D7"mdfrBmcrq.L&@>L9]G3slK[g*o()MBlK1coqjIKH!+CB~>
+s8W)d!;?BZ%b6KVp?qYJs8Vf3MhA_*rpEn^me6\\p@dqJme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qVSrr;rt
+J+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)BmO7esp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYSs7XFgmdBfJmJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mL[p,`V/`npAb0d`J]A^k3hsBmK8+0p?qnQ
+rr<#l!q(]crU'g^KC8I$rV$6js7QN^K?aD`"nqBPs8SU>~>
+s3:=2$ooG.PeH4uUfnTP0gYY.<g<XX;F*</3C,Yk3C,Yc5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4krW%F.5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4Z
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C0J@ZnXR56%MY#8dm^&;O"lW`M?ZS(bn>R
+8c]LcrndV9s6^$`md:WPr(6u$k5O69k5XiPp?q>[62O7Ue]fh!~>
+,3%IIQ'mo*Q'n&*I8G'_b3%-XI7-b?KpA'kR?a2*^An&#Y*&\`JW\iPJ'.fBD1Rh7R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R=:EhQ'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mnc:j&VWk0gP`6qh0GQ'mo*Q'k&&
+irA0>l4ECSp?qK>JXMpkR?^2&io]D%l4<=Rp?qK>JXMdkQ'mp"iaI?~>
+s8O27me6)Bme6ABc&8+2hY-*VS9'=QhX:+*p?qYBpAb/pmf!3;mbdG^pAaifc0"Hfme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BI.$^rp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?p1`SAj@Yk09E;K:Lfdp?qYBp2g3#
+!VYs[p'Uins)ZHYp?qYBF8bM-p?qnQ%KH/%F3XFHp?qYBs8SmF~>
+s2>")9)_*V9)LsU+;"MX#S7h%.60[d5t_,B"\M)"s5lrQ5l`qE5m',55rnp1!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!]`P,r]piN6&YdC5rh4s9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)V$V+;"MX"qVV#.60[dr]pTX5p5e*!"f,q
+"%kjF+S5pA&4&TSr]pWY`Q]i^~>
+%bfd%Q'%>oQ'%2oNIb5#r]CcX6rdfLNKoWkOd2&oQ/;Q/R=UKYOTN,os*p/RM34'cQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'#gHOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd1oW=[`6O$p[3\AV#i+Od2&oO^7TA
+#=O-*Od2&o?1^5d7"LJcOd2&ohVqso~>
+s8Vi]!nEffrc86XF,Qj=k54QIp?qq[!Uf[\mJut[mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;??Y!;?E[s7ZKm"R`t[me25"T'c[1S9t6V"_r+:Us8'!mJs'T
+ErgX4r9aQ\oQ(%[c26r/rrAR>~>
+!QDbG5liu#r$_Y$3VPfK9%Et(>!Y/73C,Yk3B;RT3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,ZF5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh6,s8Q7W3B;XVRm@'81&NI$0ff"p!BDV&+9<oOq`t6C
+.J=kb.678ks2=seJ,~>
+s4RpIOd2&oOd22oQ&UK?C&VBMBm#,hQ'%>oQ'%>oOd5)/m\,2kNf=@-b5_L8D1RP+OaiXYQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'#[DOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd1o[F_Uh\3,*MhNKoWkOd2&o
+Q%<XL=]JU)=]JU)=]K0eQ'IJsOd1K3<EW=)<EW=)<EW=9JX)@_Od2'cg0oL~>
+s8O&3me6)Bme6ABp?peNXIPNFXM*KYp?qYBp?qYRmf*7dmK_nBk3hC"k2q0]k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hAQmcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs2s8Veoe`Q;fJ+i=(me6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+mWJ6kp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?peNXIPNFXM*KYp?qYBp?qYJ
+/Cgh[P`(caP`(caP`)Wnp@dqJme524Mj0-aMj0-aMj0.$eb8G)me6)Ks.k/~>
+*ONL?5rh4k5rgqk3C,Yc0f^sK0f_6[3C,Yk3C,\)5n$ZAs8TH03C,Yk3C,r\3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,YkE&g3E
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5s^.cs8Q7O3B@()IlTeT5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+6$51R3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yc0f^sK0f_6[3C,Yk3C,Yc
+/3u!N0f^sK0f^sK0f^sS3B9Ac5rh4c3AENK3AENK3AENK5rh4k5rh6E]d\I~>
+s4/-KOc>K_Oc>?_NKK3[JUr6#JW5YONKK3_NKK5"OTh04s8UN@JW5hP#a)R`s8Sd,I>.Z_IuTSM
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_O`QMENKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3[JUr6#JW5YONKK3_
+NKO4"%"WhPI<g6dI<g6dI=_BW)j-,BNK&L;H$ssdH$ssdH$t7'NKK3_NKMfG@=S~>
+!VZQdmK)J,rm_&+k4n?EpAXLYrrDcljob&6k3i62!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK#4CXAk2u+*rr3)oXNfUQm[<JDk2-*f!T)u4mJtf2blH;imJtf2blH;j
+mf3:eS:C~>
+s0O:B3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh4k5rh4kXS2\om]<LBMh?Y3Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?B8_D#
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8Yu$`W#lAZoKQi0f_7D5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+ImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3@$mN5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k['VQ<~>
+*S/Z$NKK3_NKK3_NKK3_Oc>K_Oc>K_Oc>K_Oc>M%N<b<cqZ$TdcH_!PR(<XAdbaj#s43$@H%GpR
+J!#_QNKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NIR(MOc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc:QINKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK4OdU@Y~>
+s8W)d!9X:K!9X:K"6T%>k5OcKk5OcKk5OcQk3hC"k3hC0rrMinJbGH(r;R,thQ4]Hk2u*omcON:
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K"m57@s8SmF~>
+s/Z5]62ikE62ikE62NYB62ikE62ikE62ikM5rh4k5ri,MhLY]hrsHGS0ek[K5rh4k62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikH6*..:J,~>
+s3;R?NJWXONJWXONJWXOM2d@OM2d@OM2d@OM2dAiN<>$*cK]u\OoG[;V.FLlJVf6_NIQeEM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d"ANJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWW=M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OcI--O~>
+!VZQRjoFiKjoOoDJcCf2"R`@uc.2dT!:GF#J`bqR!quYaJ,~>
+*NZ&&3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh713<2AD3<M!.F*iJ.R%+A5C.^300erVe!($TE
+ImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3Ia=T5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rg,T3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,[,Ua^f~>
+.F-(qM2d@OM2d@OM2d@ONJWXONJWXONJWXONJWXONJWXONJWLCQ*.Fl`dbkF_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T$Q3`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`jVn4EG9E8JVAr;IuT;EM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM1:MA
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJT!AM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2dA;b$ff~>
+!WVlTjoF9;jp0c*hVQfFmd>Z"R.gRJ$Kf%']uAOPk2,7WJ`_OGhrY"?p8!3~>
+-Cgkd3AENK3AENK3AENK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKpb;atr\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%pG%.X0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^t<3AENK3AENK3AENK3AENK3AENK
+3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK
+3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK.60+C0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKS>7Ta~>
+.`TVVI<g6dI<g6dI<g6dH$ssdH$ssdH$ssdH$ssdH$ssdH$ss`F`h\Drb[.!D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j'Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$D/jQ@H%16fI<g6dI<g6dI<g6d
+I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6d
+I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g<jH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$sreI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g7\b$ff~>
+*VTNPc,IrHc,IrHc,IrH`QcBH`QcBH`QcBH`QcBublu)2`PoO(rj70V[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gWFXL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XSoO+^&Q(Jc%!^W`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`Q`nOc,IrHc,IrH
+c,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrH
+c,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IpO
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBHpA^Y5~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@p?mr=!<7W<JaS*W_X7L\Umrla~>
+!liB.p?mr@!<7W<JaS*W_X7MOb/Rk?~>
+!quZ5p?%B5!<7W4J`_OG_WCs>s7W7=~>
+!i2>Hp?m!"!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!
+!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!
+!<<(MmXaeWm_\Ao3LlloJ,~>
+!m8N2p?m!%!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4
+!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4!8[_4
+!8da,mXaeWm_\AoIE'E<J,~>
+!rqu=p?$Eo!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]
+!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]!-8-]
+!-A0kk(2ZGk/-6_c1_1-J,~>
+!h?&@p?hrZ!0R9^!<7W<JaS*W_X7L\Umrla~>
+!liB.p?hr]!0Q+=!<7W<JaS*W_X7MOb/Rk?~>
+!quZ5p>uBR!0M='!<7W4J`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\O59m:JaS*WJaUDC"+A23@=S~>
+!rqu=p>u?QO)k=$J`_OGJ`ai3"3pQ>S:C~>
+!h?&@p?hrZ!0R9^!<:+-rr@W<JaS*WrpBkCUmrla~>
+!liB.p?hr]!0Q+=!<:+-rr@W<JaS*WrpBl6b/Rk?~>
+!quZ5p>uBR!0M='!<:+%rr@W4J`_OGroO=%s7W7=~>
+!i2>Hp?hoYNrSb>q>f:<rrDo`quH?Vrr@W<JaSup"$)mI.=_~>
+!m8N2p?ho\O59m:o^;PUg[>(AqX47]oBuVYJaS*WRdL9+`l__?~>
+!rqu=p>u?QO)k=$o]GuMgZJM9qW@\UoB-&QJ`_OGRcX^spA^Y5~>
+!h?&@p?hrZ!7UrRe]#MPe\05ap;m77!<;`[rW)ob!!(dArrDrarrE&drrDi^rr@W<JaSil"#6UA
+.=_~>
+!liB.p?hr]!7Td1b.bU8cFUm8g;r+O!<;`[rW)ob!!(dArrDrarrE&drrDi^rr@W<JaSil"*r&/
+@=S~>
+!quZ5p>uBR!7Z&rH`Y3:hVQMrUjL1(!<E/mk5GAZjo>D9k5PGYk5PG\k5PGVk5PF4k(2Z\jo`U&
+p8!3~>
+!i2>Hp?hoYe,KLC^#&_f"8:9PhT,Zimf*:]mem.bmf*7gmJm7cmem.bmem+cmem.bmf*:bmf*:b
+mf*7emed%bmem+emJm7dmf!4cmf*7gmJm7cmem-:mXaf1mK5J>Ua^f~>
+!m8N2p?ho\e(t/[]%6i["7jmKb/iE>s7Ym\!;Gp[!<2Ed!!;Qg!<)?a!<2Eb!!)Hc!<2Ed!;u9b
+!;u9b!!)Hb!!)Hc!!;Qg!<2Ec!<2Ed!!;Qg!<)?a!.jQhm]c*]IE'E<J,~>
+!rqu=p>u?QdrPS;`TI.!"8:lrSB,aOs7YUT!;GXS!<2-\!!;9_!<)'Y!<2-Z!!)0[!<2-\!;u!Z
+!;u!Z!!)0Z!!)0[!!;9_!<2-[!<2-\!!;9_!<)'Y!.j9`k-3tMc1_1-J,~>
+!h?&@p?hrZ!7UrLp:]VdrrVo5e]Rmm!<;c\rrDi^rrE)errE)erW!Gr!!)HT!!)HT!!)HT!!*#d
+#QX;\!!)HT!!)rbrrDubrr<&erW!T!!!)Ee!:K7T!:K7T!:BgemdC&S#4;Hkmd:&TJaS*WXmQ9G
+Umrla~>
+!liB.p?hr]!7Td+f!a`=rrVc._TL^9!<;c\rrDi^rrE)errE)erW!Gr!!)HT!!)HT!!)HT!!*#d
+#QX;\!!)HT!!)rbrrDubrr<&erW!T!!!)Ee!:K7T!:K7T!:BgemdC&S#4;Hkmd:&TJaS*WXmQ::
+b/Rk?~>
+!quZ5p>uBR!7PujK>m9UrrLB?b&[R`s7YUT!;P^V!<;3]!<;3\!"S,k!9WDD!9WDD!9WDD!<2*d
+!9WDD!9WDD!;u!Z!;u!Z!!)0\!#"Do!9O7]k2lXDk2lXDjo>DDk5G>bjo>DDjo>C4k(2Zsjo`U&
+p8!3~>
+!i2>Hp?hoYdJj:A[-%8c!PR%*s7Ym\!<2Eb!<;Ke!<;Ke!<;Ke!<;Ke!<;Ke!<;Ke!<;Ke!;l3a
+!<;Ke!;u9b!;u9b!"ePu!:K7T!:Bgemd:&TmJm7dmf*7mmJm7TmJm7Tmf!3;mXaf/mK5J>Ua^f~>
+!m8N2p?ho\dG=rUY2]?Y!P6.jh>mTLmf*:dmem.cmf*:emf*:emf*:emf*:emf*:emf*:emf*:a
+mf*:emf*:bmf*:bmf*7umJm7TmJm7T!!)HT!!)Ee!<2Ed!!qum!:K7T!:K:S!.jQhm]Ps[IE'E<
+J,~>
+!rqu=p>u?Qd;oAA^$bdt!R7.WErc76k5PG\k5>;[k5PG]k5PG]k5PG]k5PG]k5PG]k5PG]k5PGY
+k5PG]k5PGZk5PGZk5PDmjo>DDjo>DD!!)0D!!)-]!<2-\!!q]e!9WDD!9WGC!.j9`k-!hKc1_1-
+J,~>
+!h?&@p?hrZ!7CfJp8mERrrK4hbl7\Ds7Ym\!;u9b!<;Ka!<;Ke!<;Ke!<;Ka!<;Ke!<2Ea!<;Ke
+!;u9b!;u9b!"ePu!:K7T!:Bgemd:&TmJm7dmf*7kmJm7TmJm7dmem-:mXaf1mK52>S1/s~>
+!liB.p?hr]!7BX)euIU)rrW%sd`gPK!<;c\rrDubrrE)eqZ-ZarrE)errE)eqZ-ZarrE&dquHcb
+rrDubrrDubrr<Vu!!)HT!!)Ee!:K7T!:BgerpKdd#4;Hkmd:&TrpK^bJaS*WYjMU=b/Rk?~>
+!quZ5p>uBR!7>ihK>$^MrrKfcb]<dbs7YUT!;u!Z!<;3Y!<;3]!<;3]!<;3Y!<;3]!<2-Y!<;3]
+!;u!Z!;u!Z!"e8m!9WDD!9O7]k2lXDjo>D\k5PDcjo>DDjo>D\k5>:2k(2[!jo`U&p8!3~>
+!i2>Hp?hoYci4(7Uu)%L!T(3+s7Ym\!;u9b!<;Ke!;l3a!<;Ke!<;Ke!;l3a!<;Ke!<;Ke!<;Ke
+!;u9b!;u9b!"ePu!:K7T!:Bgemd:&TmJm7dmf*7kmJm7TmJm7bmf!3;mXaf2mK5J>Ua^f~>
+!m8N2p?ho\ce\`OU"]GE!SX^"h>mTLmf*:bmf*:emf*:amf*:emf*:emf*:amf*:emf*:emf*:e
+mf*:bmf*:bmf*7umJm7TmJm7T!!)HT!!)Ee!<2Ed!!_ik!:K7T!;u9a!.jQhm]l0^IE'E<J,~>
+!rqu=p>u?QcZ9/?[-%;d!Tp3$Erc76k5PGZk5PG]k5PGYk5PG]k5PG]k5PGYk5PG]k5PG]k5PG]
+k5PGZk5PGZk5PDmjo>DDjo>DD!!)0D!!)-]!<2-\!!_Qc!9WDD!;u!Y!.j9`k-=%Nc1_1-J,~>
+!h?&@p?hrZ!87AQe_^-%!q)THrVlrmV"W(5!<E/mmf!4cmf*:emf!4amf*:emf*:emf!4amf*:e
+mf*:emf*:emf*:amf*:dmf*:emf*7emf!1kmJm7TmJm7TrW!Dq!!)HT!!)HT!!)HT!<2Ed!.jQh
+m]l0^0r1<gJ,~>
+!liB.p?hr]!8630_T)E.!n*M%rVlriU"7KF!<E/mmf!4cmf*:emf!4amf*:emf*:emf!4amf*:e
+mf*:emf*:emf*:amf*:dmf*:emf*7emf!1kmJm7TmJm7TrW!Dq!!)HT!!)HT!!)HT!<2Ed!.jQh
+m]l0^H-4-8J,~>
+!quZ5p>uBR!82GnMtqDqHaNMFrrVo-Hd-U4!<;`SrW)r[rrE)]rW)lYrrE)]rrE)]rW)lYrrE)]
+rrE)]rrE)]rrDrYrrE&\rrE)]rr<&]rW!2c!!)0D!!)0\!"J&j!9WDD!9WDD!9WDDroX4\J`_OG
+Z/u/-s7W7=~>
+!i2>Hp?hoYf`)#KSCRK9!kk,lr;Qf)hTPrjme["_mem.cmf*:emf*:cmem.cmf*:dmed(bmf*:`
+med(amed(amf*7gmJm7dmf!4cmf*:emf*:emed'9mXaf1mK5J>Ua^f~>
+!m8N2p?ho\f\ZY!!5eTh!j8*^rVlrqZGOiB!<;ZYqZ-T_r;clcrrE)errE#cr;clcrrE&dquHcb
+rrDo`quH`aquH`arr<,g!!*#drW)rcrrE)errE)equD<9JaTc1"+A23@=S~>
+!rqu=p>u?QfQ.+i[#=d%!gL(cr;Qf:Mp-5Bs7>CM!<)'Y!<;3]!<;3]!<)'Y!<;3]!<2-Y!<;3]
+!;bjU!<2-Y!<2-\!!;9_!<2-[!<2-\!<;3]!<;3Z!.j9`k-3tMc1_1-J,~>
+!h?&@p?hrZ!87ASPjY'lr;Qi3UuqUT!qsUXc2ReEs0h@q!.jQhmZ6c<0r1<gJ,~>
+!liB.p?hr]!8632Oli(Kr8%LXV;hFL!qs@>c/&I$s0h@q!.jQhmZ6c<H-4-8J,~>
+!quZ5p>uBR!82DqXR<HJr,Vq(^$bdt!R6kRErc:@[c[SiJ`_OGO6-P`s7W7=~>
+!i2>Hp?hoYf`))Es5oQrrr3A5V!e9Vs7ZKdp9_f^s0h@q!.jQhmZ6c<3LlloJ,~>
+!m8N2p?ho\f\Qb%p>V4Krn[^VSa-+G!qNe.bh`@"[dO.qJaS*WO7!*u`l__?~>
+!rqu=p>u?QfQ.2&s5pD8rc8I3[-mtfs7ZKdp;Ms6Erc6Kk5PF4k(2ZUjo`m%s."T~>
+!h?&@p?hrZ!87AYPkOh-Ph#f@SEB\A!q*G7c2ReEs+0ThmXafCmK52>S1/s~>
+!liB.p?hr]!8638Q1FM&NP=8LRHFA:!p[(sc/&I$s+0ThmXafCmK7aW`aOA~>
+!quZ5p>uBR!82E,XS2\VXFkSP[-mtfs7ZKds7XEic#Wmcs+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoYf`)V3mdBf!Mk$$gp?qYBp?qYBk*4`Gs+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\f\QUVrpBp?Kp@eWqX+INifV+%h>mS,mXaeWm_\AoIE'E<J,~>
+!rqu=p>u?QfQ.%_rq6KOUm.tCq=XmXXFn`<!<7W4J`_OG_WCsFpA^Y5~>
+!h?&@p?hrZ!87AQSAkKq!nEgtq!J4?HhP_a!<E.NmXaeWm_\Ao0r1<gJ,~>
+!liB.p?hr]!8630NQ1t_!n*Ljq!%q3IG2s&!<E.NmXaeWm_\AoH-4-8J,~>
+!quZ5p>uBR!82E+Ph#Kqp>31=p?qYBp?qYBp?%mhErc:@J`_OGJ`ai3"3(<6Ujr~>
+!i2>Hp?hoYf`),oUu(7rmf)>Kmf)>QmcNZgk+&Nrs+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\f\R:ES_iMgk2PO_k2PO_k2POWhOU4]h>mS,mXaeWm_\AoIE'E<J,~>
+!rqu=p>u?QfQ.+H[-%AU!9X(E"6T$YK?SB:s+0<`k(2[3jo`m%s."T~>
+!h?&@p?hrZ!87ARp2e4Gjp0GM^##RAhY,=r!<E.NmXaeWm_\Ao0r1<gJ,~>
+!liB.p?hr]!8632g3(-dpu2V:im,!Dg6n4k_U.-?!<7W<JaS*W_X7MOb/Rk?~>
+!quZ5p>uBR!8)>qMp:DPk5OcKk5OcTk3h*Fc/u)f.9b)>!<E.Nk(2ZGk/-6_`W,Y-J,~>
+!i2>Hp?hoYfDbokC<cM0$-g/s`Qd8rp=8l_s+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\fA7:KD8t;dg>:Q?g>:Q?cG%$4_P*gOOi%"P!92Ve!<7W<JaS*W_X7MS`l__?~>
+!rqu=p>u?Qf5h"?Mq.Ra$/WqOe]gu@3@S//Er^R=Erc5kk(2ZGk/-6_c1_1-J,~>
+!h?&@p?hrZ!8%5QUiWofqVD;(c-?7<"lAt@p=8lbrrE-"JaS*WJaUDC"#6UA.=_~>
+!liB.p?hr]!8$'CO_q8Hg=G!/g=G!+`l?<HRA%X#dZ),lh>mWVJaS*WJaUDC"*r&/@=S~>
+!quZ5p>uBR!7u8oK8[_*qW81Be^`O$;CO=C3@S.[Erc:@J`_OGJ`ai3"3(<6Ujr~>
+!i2>Hp?hoYec-#j>)T2i`QcB8^"(C+eHYa0p?qY!ma;(.mX\8e;Lq`u;YKM\3LlloJ,~>
+!m8N2p?ho\e_V(A?&>Dh_T'I$^=(<Td[?N?Ko)tTM8%Ep!<;c\JQ78$JQ:?&p?i$2`l__?~>
+!rqu=p>u?QeT2%DK;?3*e^_p`c2QQ+eP[hF#RD8%.8nT8!<;cTJPq%sJPt,up>uJ%pA^Y5~>
+!h?&@p?hrZ!7h)[m[RHqF*ht;>,9^*c.2OUrr<#l!QFKVrrE-"p?mM3JcC<$f`1[5"#6UA.=_~>
+!liB.p?hr]!7fpAcA>\8Fa7h8=eX9pQ'K(CR@0>G`eD.Vh>mWVp?mM3JcC<$f`1[5"*r&/@=S~>
+!quZ5p>uBR!7Z&kH\6tMPlH@F[-$4C.4Gf>#S8+5.9b5B!<E/nk(3P`s+14&s7YRW`W,Y-J,~>
+!i2>Hp?hoYdJjU)[&gskhI<"oc1^T'rr_u_`U;4TJaS*WJaUDC"$)mI.=_~>
+!m8N2p?ho\dG>SOTp_pp`a,!lOfjtGTr"HRZG(n(eD:3*JaS*WJaUDC"+A23@=S~>
+!rqu=p>u?QbB"/?X@aoa&/Yrq&/Z6=.8nZ:!<7W4J`_OG_WCsFpA^Y5~>
+!h?&@p?hrZ!6kHGhQ4uqpA4dkp?oW^f)GaNs+0ThmXafCmK52>S1/s~>
+!liB.p?hr]!6j:1^3,F@TrtQ(Y-P41[^pmuf%pE-s+0ThmXafCmK7aW`aOA~>
+!quZ5p>uBR!6fKpC,m^c(a'Y<(a'Y4+>G<KeoLils+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoYbPqY;[-%,_"8;/rk10K_mXaeWm_\Ao3LlloJ,~>
+!m8N2p?ho\bME<GH*6qR"L>VEH+MS`!<7W<JaS*W_X7MS`l__?~>
+!rqu=p>u?QbB!_o.4P!6!uNI9;V#mhs+0<`k(2[3jo`m%s."T~>
+!h?&@p?hrZ!6bBDk-XRMrrVVqk1K\7!<7W<JaS*W_X7L\Umrla~>
+!liB.p?hr]!6a4#\ok1Q`rEpU^&u6TFgfrZ!<E.NmXaeWm_\AoH-4-8J,~>
+!quZ5p>uBR!6]E`>5'HL+=SE^.9bAF!<E.Nk(2ZGk/-6_`W,Y-J,~>
+!i2>Hp?hoYao;G)XQK6V!p6TXfDgEiJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\akd-.EM^hWc2c#a\cS^Jb1PPNs+0ThmXafCmK7mWb$ff~>
+!rqu=p>u?Qa`@G[r[@q(.5<:K+TEkj@b>`%s+0<`k(2[3jo`m%s."T~>
+!h?&@p?hrZ!6P6Bk,d_=rrLB`g&D'Qs+0ThmXafCmK52>S1/s~>
+!liB.p?hr]!6O(.[V__`g=jELZC-u?ZF5aTg"l`0s+0ThmXafCmK7aW`aOA~>
+!quZ5p>uBR!6K9^>5frY3ADs"+:o(i+<W+!flI/os+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoYa8Z5'UuqFO!Ucc8s7Ym\p&`Kc>-C3p;M2s^p4;X_m]#UV3LlloJ,~>
+!m8N2p?ho\a5.<3BpmE3ZEC3mSY;1OWbL,B!<;c\"S2!#I9!I9"&OE_nq$4[m\oOUIE'E<J,~>
+!rqu=p>u?Qa)_A].3L'"rYPhF&.f*a(b+*Y!<;cTs6]s-HW'f.!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E#!"tI
+HbJk8J`_OGWTF<-pA^Y5~>
+!h?&@p?hrZ!6>*@hPB<.rrAkJrrE-"p$Q"R>.sY0me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmbY<SSG%O%
+JaTN*"#6UA.=_~>
+!liB.p?hr]!6<q*Z=T<PWiEpiQ(a2;Z=V_G!<E/mmTPlY]'fU`mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+eui/@nq$4[m]#UVH-4-8J,~>
+!quZ5p>uBR!69-i;CN_C(`4\%&.f*a(b+-Z!<E/mk$"!I[-%DNmcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+eZ;r=mXaMOk,IJF`W,Y-J,~>
+!i2>Hp?hoY`W$"rSDO&@!1_[@p?i",@cjin"nqBXhI=HTmXaf*mK5J>Ua^f~>
+!m8N2p?ho\`SM$/@?IC[cBX*KQ)1<cf\QW.p?i%"@H-j]rrqiUlIo[\JaS*WWU9k:`l__?~>
+!rqu=p>u?Q`H)Gc.3K0=.0onb#S7OrfQ.&mp>uIr>2J\NrrqiQk1*qSJ`_OGWTF<-pA^Y5~>
+!h?&@p?hrZ!6+s>hNZmnrrLZGg&D'Qs7Yj_K>$^HY5\Xmk3fp8Q<FB"PkOg%m[3DE0r1<gJ,~>
+!liB.p?hr]!6*e&Z<`<XY1gIiSY:aSg"l`0s7Yj_J[Xk3YQ"e&lJh*;JX'@=NUhYgQgOs$b/Rk?~>
+!quZ5p>uBR!6'!e;CNFo(bm-M&.fs=flI/os7YRWHaMr'YQ&_<k2,7-HWj<N;Hct%;Hct%;Hct%
+;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%
+;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%>)Vh:J``?^"3(<6Ujr~>
+!i2>Hp?hoY_uBegMr+C3!q)<'fDkR4"(LE\m]HM0k3hA8hWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\F>)W**m[3DE3LlloJ,~>
+!m8N2p?ho\_qka'=b2j+Q'n&&?*;i:!<;c\"'sdKk-"`*p>Y5k=k_`dhV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?c<6.tJaSon"+A23@=S~>
+!rqu=p>u?Q_fH/_+;b@q#S77Q+B$j5!<;cT"'XRDhQHk_p>4rg>1ML/eH"J*eH"J*eH"J*eH"J*
+eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*
+eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eHOg[`EIo^J``?^"3pQ>S:C~>
+!h?&@p?hrZ!5ngBeVh-7s8U?.^"E>c!<;c\"'Y-Tk,nXchWF60QL=e'!FkbRm[3DE0r1<gJ,~>
+!liB.p?hr]!5mY!Y#TJ$Q'$2lM:gYc!<;c\"'+L?iiW4_g>_6tQKA7sc<5_dQgOs$b/Rk?~>
+!quZ5p>uBR!5ij`;CN^o&-s*q6.g5Z!<;cT"&e:<hQ?fue_].dk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Fc!'Odk*Y95`W,Y-J,~>
+!i2>Hp?hoY_>a`-XG_^hPh"=ap?i#lmcNZ6s)R8YmTT>Pp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp=7\sP_&7imK5J>Ua^f~>
+!m8N2p?ho\_;5C9I8s*D@B.o8!<;c\"'t'Gg91HsqVKrk=mkSClL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*d`u!TJaSon"+A23@=S~>
+!rqu=p>u?Q_/fWd3W1B,;V#mhs7YRW>3=\lY5`S:hUUalmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNr^c!$$Vk*Y95c1_1-J,~>
+!h?&@p?hrZ!0R9^!<;c\"'Y-LhQ?hXh>ubJQL=e'!OQTmm[3DE0r1<gJ,~>
+!liB.p?hr]!0Q+=!<;c\"C:0@gA8#Q"T$^#iaJ/<s3:YNAV'9:mK7aW`aOA~>
+!quZ5p>uBR!0M='!<;cT"Bss<eb63H"SUBrhHH6-"3&Nd@Y*[/jo`U&p8!3~>
+!i2>Hp?hoYNrSh@")?uThY[?M!;-<j!6P6FhUV%/mdBfJmJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mKE76c.-!Km[3DE3LlloJ,~>
+!m8N2p?ho\O59m:p?i&pimu]Wr;ZWoo`+mjb5VV<f$`PhQKeS#cI,jHm[3DEIE'E<J,~>
+!rqu=p>u?QO)k=$p>uKmhUU0Mr;ZWoo`+mjb5VV<e]lr[QKA:o`Q_;3k*Y95c1_1-J,~>
+!h?&@p?hrZ!0R9^!<;c\"D[)LhY-mI!!)utrrD`l!!((>s4%25C?GN`!9X:Kq#CEWrpBdKrpBdK
+rpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBjMmdBuQ!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+"Qo+PmcON:!9X:K!9X:K!p8q=rm_!PJaSon"#6UA.=_~>
+!liB.p?hr]!0Q+=!<;c\"DQ`<ddm>9!!)utrrD`l!!(+?"SU9lhJ)fJq#K.2quGd>!!)QOrltLH
+JaSon"*r&/@=S~>
+!quZ5p>uBR!0M='!<;cT"Cg64c0kT2#kn8us7ZKm!!*#u!;?El!;?El"SMiqs7ZHl!;?El!;?El
+!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El&,-&'p<Ck4C>S+0k2,7Wk4o!(
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\m!&!-jhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\W!9W/#hWE\WhWE\WhWE\WhYtIo;M!ttjo`U&p8!3~>
+!i2>Hp?hoYNrSh@"*<VTebf@H!;uis!;6?l!6G0Cp>4?^F8##%!8$W=!8d,D!:fIZe]lWJJaSon
+"$)mI.=_~>
+!m8N2p?ho\O59m:p?l.)hU9jGs8Vrqq>gBlqZ$BlqZ$ElqZ$ElqZ$El!<;oqqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$-7cJEF3jo>D5jo>D<jo>DO
+joa&SdTM.hR-k')`l__?~>
+!rqu=p>u?QO)k=$p>uO"e]lA4p4*,9s7QHds7ZKd!;?Hds7ZKds7ZKdrrE)ms7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZK\e]lrck2,7Wk2,7Wk2,5#
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2&MghWE\WhWE\WhWEYphWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWEYphWE\WhWE\WhWE\WhWE\Wc,Iq*J``?^"3pQ>S:C~>
+!h?&@p?hrZ!0R9^!<;c\"EW_Ueb8q@!!)rs"p"Z'rrE*!rW)uurW)uurW)rt"9AH%s8W&urr3!!
+s8E#ts8;rts8E#ts8;rirs&2Ie_YB0mf)>Kmf)>OmcFN3mf)>Kmf)>Kmf)>Kmf)>OmJuD3mf)>O
+mJuD3mf)>Kmf)>Kmf)>OmJuD3mf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>OmJuD3mf)>K
+mf)>Kmf)>PmcN'Mc!#\dR-k&2Umrla~>
+!liB.p?hr]!0Q+=!<;c\(3/3VddHu*qY'acqY'dZq>g?lq>gBcrVuumqYgHqqY'mg#PS#f!;6Ed
+qYgHtqY'acqYgHrqY'da!!2firW!#rpA4^f&bc(pqY'dZqY'dZqYKX*cJ!F7iW&uIiW&uTiW&uL
+iW&u8iW&uKiWIKKb#s;`R-k'%b/Rk?~>
+!quZ5p>uBR!0M='!<;cT"DZK+c0"rt!!)rj"p">sp&Og[rW)ulrW)ulrW)rk"9A,qp@eIcrq6?m
+pAP'kpAG!kpAP'kpAG!`p&sg.c.-n/h>dQEh>dQPh>dQHh>dQ4h>dQGhYtIo;M!ttjo`U&p8!3~>
+!i2>Hp?hoYNrSh@"G>jeeb8q@!!)utrr=MJ!!*'!!<<'!!<<'!s8N*!rr<'!rr<'!rrE*!!!*'!
+!!*'!!<<'!!<)p&!<<'!!<<'!nc&ace^`f/p>u>Tqr[kXroO1\roX.Zr9!tYs5s7[q<%\WqW7k[
+jo>D[k5GAZk5GAZk5>8]joFQC!;5IVe]lWJJaSon"$)mI.=_~>
+!m8N2p?ho\O59m:p?i'/g<S"3r:U*jrV$6k.J<`Ap@\L[p&G*dp&Og[!;?*d!;?*d!;?*dp@\Id
+p@\Idp@\L[p&G*kp'1Tkp&G*dp&O[W(]*RFcJEj+hW!DOhW!DOhVnOphW!DOhYmKZhW!AlhW!Dj
+!!M<<ini\o!!2*9r;[\ohW!DOhW!Al!92kphW!DO!9*tYhW!DOrW!&[hW!Dk!!D*;hW"J6!o<q6
+rW!Jcini\Oini\Oini\Cb0F.@m[3DEIE'E<J,~>
+!rqu=p>u?QO)k=$p>uL)e]lA,r:U*jrV$6k.J<`Ap@\L[p&G*dp&Og[!;?*d!;?*d!;?*dp@\Id
+p@\Idp@\L[p&G*kp'1Tkp&G*dp&OXV"RaORhK/DI!!)oQrW)rS!!*#Tr;ccPrW)uTr;cZMrrDoP
+!s%0X!<(dR!<(dR!<(dQ!!;!WhYmNJh?2$Abu0,TR-"LqpA^Y5~>
+!h?&@p?hrZ!6tQD!6>*?!<;c\"afCVeaEJ9pA4jip&kBhp&G*lp'(Njp&Odd!<2Zs!;?*dp@\Id
+rq6Eop@\Lcp&b<gp&P'brrE&l"9A/h!!)Q_3mH43Hf!oAk2,7Wk2,7W!8ckpk2$*pjo>D<jo>D<
+!8ci<k2,7Wk2,5#k2$(<k2$(<k2,7Wk2,7WrW"Y/k2,7W!!)-]!8ci<k2$(<k2$*pjo>D<jo>D<
+k2,5#!8ci<k2,7Wk2,7Wk2,7WrlkFHJaSon"#6UA.=_~>
+!liB.p?hr]!6sC#!6<ps!<;c\$%:OMcKb,ko'Z)G!.+)(!:oOX!:oRK!:oOXmJm7Xmd^AKmJu\G
+!!)HXmJu\G!:oRK!:oOXmdff:!!)HXmJu\G!!)HXmdff:mdff:mdff:o'4NGg3ME/g>:Q?g>:Q?
+g&Tj`g>:N`g>2f0g>2f0g&Tj`!8cGdg>:Q?!8cE0!8cE0!!hB7hV-i?hV.r/1tpg?hV%r0h>dQ0
+h>lEd!!(m0!8?90!8?90!8?;`h>dQ0h>lEdhV-i?hV-i?hV-8tb#s;`R-k'%b/Rk?~>
+!quZ5p>uBR!6oTb!69-]!<;cT$%(4Ac0"`fmcNs7!"e;\!:JtL!:K";!:JtLmJm7dmN_f#mJuD;
+!!)0LmJuD;!:K";!:JtLmdB6*!!)0LmJuD;!!)0\mJuDKmJuDKmQTe$mcML5eU,j'e_\j5e_\j5
+eH".Ve_\gVe_U9+e_U9+eH".V!8c8_e_\j5!8c6+!8c6+!8c8_e_\j5ec#P&e_\j5eGoU+!!(R+
+!8c6+!8c6+e_U9+e_U9+e_\j5!!(R+!8c8_e_\j5e_\j5ec*Mf;M!ttjo`U&p8!3~>
+!i2>Hp?hoYq>^9kg].9RqZ$HnoDegjiW&W>",l$debf%?!;cBj!;?-`!<;`n!;?9is7QKop@e@`
+s7QEmrq6Eop@\LbpA4jhpAP'bp)a8%e^`f/k2,7Wk2,7Wk2,5#k2,7W!!)0<joFQ#k5G?#k2$*p
+k2,7Wk2$*pjoFQ#k2$*pk2,7Wk2,7Wk5G?9k2,5#k2,5#jo>D<k2$*p!!)0<joFQ#!8ckpk2$*p
+k2$*pk2,7Wk2,7Wk2,7Nc.-!Km[3DE3LlloJ,~>
+!m8N2p?ho\q;1rJgYVr1qVM,MoA9KIina\8p?i*<g<S"/o)7tV!;c*b!:K:P!<;Hf!:K^as6]pg
+mdBrPs6]jerpBjgmd:)Rme["`mf!4ZmKN1HcH=jdp=]KHrS%8Orn7>Prn@>Os4RGQqUu#Og=cQ*
+g&M-IgAV*Og&M-Pg&h?/!!*#P!s%$T!<1[S!8?-,r7V,Nrn7>Pp"BMnb0F.@m[3DEIE'E<J,~>
+!rqu=p>u?Qq/cB4gN3ApqK)Q7o5jp3ic>,"p>ua8e]lA$mdB6*mJuDKmKMb@mJuD;qZ$`\mJu\P
+!<;Hg!:K:P!<;Hp!9W_;!9W\LmcNs*qZ-W`rVuuek5OcKk5OcKk5OcPk0:lqF5HoH!8d_*"Q%\Z
+!8d_*rrE)L"Ps./e_^9*"Q%Z/e_^;U%,TM7e_U;Ve_\gVe_^;U!8d_*!8d\T(uEfn!8c8V!8[\U
+e_\gVeGoU"e_U;VeH#U!#i=)3e_\gVe_^;U!8d_*#2[n\c,IY"J``?^"3pQ>S:C~>
+!h?&@p?hrZ!;lfq!<)ot!8IPR!;lfr!<3#u!;QTo!8meW!<;c\?A%+ZeaE/!p?qVSp?qYBp?qVS
+p?hn\p?qYBp?hqK!!)`\p?qYB!:KO\!:KRKp?qVSp?qVSp?hqKp?qVS!:KRKp?qYBp?hn\p?qYB
+p?qYBp?qYBm`j;=Hf!W0rn[Y*rn[h/!8cS_hYR9Ue_]-_!<1gV!8cT3!<:mY!8cQ4ec+D,!8cT3
+!<:mUec+D4eGoU+eH"I_eH"J'!!(mQ!!Lj/!8c9*h>dQTh>dQTh>l+*h>l+*h>l+*blCpum[3DE
+0r1<gJ,~>
+!liB.p?hr]!;kXP!<(aS!8HB1!;kXQ!<1jT!;PFN!8lW6!<;c\"bk[QcK=Qnl2Uh\l3%+Pl2Uh]
+l2q%O!!)o]"9@`P!!)o]!!*#`!s%WO!<)3_!;PjZ!;>[]mcqs;g3NDC!!)uKqZ-WHrrE&L!W^g&
+rW)uL!s$p'!<(IM!7oa#!;b:H!<:UM!<1OM!7q#I!7q#Is4./Mr71iJrmh&Lp"',b!*Om@R-k'%
+b/Rk?~>
+!quZ5p>uBR!;gj:!<$s=!8DSp!;gj;!<.'>!;LX8!8hhu!<;cT"bY@Ec/.mejo>DXjob\Hjo>DY
+joYVG!!)oY"9@TH!!)oY!!*#\!s%KG!<)'[!;P^V!;,Ce`Qcq[c.1(hc.1(hc.1&=c.1(hqZ$uJ
+e]e'oe]lVEe]n'n%*d<&e]e*=e]lVEe]n'n&C&bMe]lXh!!(Qo!6s'=!6tB@!7grH(sUS2e]lXh
+eH".EeH".Ee]lXhe]lXhe]n*4!)eC1R-"Lis7W7=~>
+!i2>Hp?hoYqu?Zrp](0lrr;uu!ri6#rVufrrr;os!<;utrr;uur;Zcsr;Zcs!<;rs!<;ut!ri6#
+rr;rtrr;uu!ri6#rVufrp]'sT#)h?gc0k<!rpBadrpBd[rpBadrpBadrpC'cmd:)KmJu\KrpC'c
+!:K:K!:K:KrpBadrpBmhmd:&TrpBp_!:K:KrpBd[rpBadrpBd[rpBd[rpCj$ma]SEHf!<0e_\j5
+e_\j5!8c8_eGoU+e_\j5e_^9*;Voq(e_\j5e_\gVe_U;_e_\gVe_\j5e_\j5e_\j5eH".V!8c8_
+!8[\Ue_\j5eGoU+e_\j5eH".Ve_\gVe_\gVe_\j5e_\j5e_\j5e]lWJJaSon"$)mI.=_~>
+!m8N2p?ho\qqh>QpYPiKrndYT!o<nWrSIJQrndSR!8dYSrndYTr8.GRr8.GR!8dVR!8dYS!o<nW
+rndVSrndYT!o<nWrSIJQptc#Np?m$Vg<Rk'lK[NsjoFQ/k3D*ojoFQ/joFQ/k3D*o!:&\Hk3D*o
+k3;s3k3;s3k3D*ojoFQ/joFQ/!!)0Hk3;s3k3D*ok3D*ojoFQ/k3D*ok3D*ok3hBWb2.Epdaljt
+daljtdaeELdalhH!7oTLdaljtrW#jIdK%_HdaljtdK%_H!7oTLdK%_HdaljtdaljtdalhHdaeEL
+daeEL!!(HudalhH!7oTLdalhHdaljtdK%_HdK%_Hdaljtdaljtdal^dc<5_dR-k')`l__?~>
+!rqu=p>u?QqfDc;pN-95rcA)>!cn>ArH%o;rcA#<!-A)=rcA)>r,_l<r,_l<!-A&<!-A)=!cn>A
+rcA&=rcA)>!cn>ArH%o;pi?H8p>uI0e]l)1jo>DXjo>D\jo>DYjoYVGjoG;@!!*#\!!)oY!!*#\
+"9@TH!!)u[!!)cU!!)`T*q&18`SP[dc.1(hc.1(hc.)gEc.1&=!7f?Ec.1(hrW#jHblH#=c.1(h
+blH#=!7f?EblH#=c.1(hc.1(hc.1&=c.)gEc.)gE!!(9oc.1&=!7f?Ec.1&=c.1(hblH#=blH#=
+c.1(hc.1(hc.1(Xbu0,TR-"LqpA^Y5~>
+!h?&@p?hrZ!;uls!;QTo!<<*!!<<)u!"T#/!<<'!!<<'!!<<'!!<3!(!<<'!!<<'!!;uls!;uls
+!!*&u!##;3!<3$!s8N'!s8N'!rr<'!s8E!&rr<'!rr<&mrrE-"p?i?Ak0;HEp?qA2mJu\;rpC!Q
+mJu\;mdC#R"n(LQmdB69!<;Hf!9X:Kr;[/dmJu\;mJu\;mem.cmem+dk3i0Js6]mLrpBdKrpBdK
+rpF[Ke_Yr/hUUK5hUUK5hUMVVhUUK5!7frVhUUH_hUMVVh>lE_hUUK5h>lE_!!(m+!!(m+hUUK5
+h>lE_hUMT+hUMVVh>dQ+h>lE_hUUK5!7frVhUUH_!7frVh>lE_h>lE_hUUK5hUUK5hUVVM!*XsA
+R-k&2Umrla~>
+!liB.p?hr]!;t^R!;PFN!<:pU!<:pT!"Ric!8cQ4!8cQ4!8cQ4!<1g\!8cQ4!8cQ4!;t^R!;t^R
+!!(mT!#",g!8[\UhVJ54hVJ54h>dQ4hYmKZh>dQ4h>dQLh>mWVp?i*<g<._'meu8J!;bgX!<)'Y
+!<;0]!<2-Z!<;0]!<)'Y!<;0]!<2*\!<2-Z!<;3[!<;3[!;5JnlK6C;g3qE#daljtdaljtdK%_H
+dalhHdaljtdaeELdK%_H!7oTLdaljt!7oQu!7oQu!7oTLdaljt!7oTLdJs9udK%_H!!(Hu!7oTL
+dalhHdaljtdaeBudaljt!7oTL!7oTLdaljtdaljtdf.Ah=b6".mK7aW`aOA~>
+!quZ5p>uBR!;pp<!;LX8!<7-?!<7->!"O&M!-<2]!-<2]!-<2]!<.$F!-<2]!-<2]!;pp<!;pp<
+!!%*>!"s>Q!-8,?F)q<]F)q<]ErZ2]F8c.DErZ2]ErZ46Erc:@p?!-Ce]#eimb[*_joFQ#k2,7W
+joFQ#k2-%:"m4YAhWE\n!!_TB!8ckpk5>8dhW=h#hW=h#hWFb:!T)u;!!1s=r;[2]k2,7Wk2,7W
+k2-+""3&O8HhP\a!;t(A!;k"F!6ragc-67bbm4<obl@agbl@b?bl@bBc2ReDbm+6nbl@agblIXc
+!!)o@rrE#B!!*#C!!)]:rl"k8J``?^"3(<6Ujr~>
+!i2>Hp?hoYqu?Zrrr;oss8W*!s8W*!s8W*!s8W*!s8W*!s8W*!s8W*!qu?Zrs8W*!r;Zcsr;Zcs
+&H;_1s8N'!rr<'!rr<'!!!*#urr<?)!!*'!!!*'!rW)Wkp?i*BhUU0Mp9F$%p?'oUk(DO@hUUK5
+hUUK5h>lE_hUUK5r;[Mf!!(R+!!(OL!8c8_e_\gV!8c9)!!hB2hUUK5hUVK'!oDJar;ZrMhUUK]
+!!:^-eboILhUUK]!#=#ae_\gVe_\j5e_\j5e_\j5e]lWJJaSon"$)mI.=_~>
+!m8N2p?ho\qqh>QrndSRs5*bUs5*bUs5*bUs5*bUs5*bUs5*bUs5*bUqqh>Qs5*bUr8.GRr8.GR
+&DdBehVJ54h>dQ4h>dQ4!!*#Trr<>]!!(m4!!(m4rW)ZK!<;c\"c:sYcKai&jot&0cH>!pp<ip@
+qpPEC$.8eRdaA*qdJs:Edf0=Ides1Adea%Ddes1Edes1Fdes1Fdes.HdK'9p!!)]?"4"p/=b6".
+mK7mWb$ff~>
+!rqu=p>u?QqfDc;rcA#<s)\2?s)\2?s)\2?s)\2?s)\2?s)\2?s)\2?qfDc;s)\2?r,_l<r,_l<
+&9@gOF)q<]ErZ2]ErZ2]!!*">rr<=G!!%(]!!%(]rW)Y5!<;cT>D(JNc0"HVhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhTa$rHhP\a!;k%>!"$mM!6rag!6kKDqp#-@s3:KBq9Ad:rltBArQY9@rltBArltBA
+!R1WDbl@b9c2Y`_;M!ttjo`m%s."T~>
+!h?&@p?hrZ!;uls!;uls!<<)r!<<*!!<<*!!<<)r!<<*!!<3#r!<<*!!;uls!;uls!"f/1!<<'!
+!<3$!s8N'!rr<&us8N''rr<'!rr<&us8;rnrrE-"p?i3EhTaU=p?(f*q#EeMk3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC2mK:_a
+hM]8$!!(U#rlkFHJaSon"#6UA.=_~>
+!liB.p?hr]!;t^R!;t^R!<:pQ!<:pU!<:pU!<:pQ!<:pU!<1jQ!<:pU!;t^R!;t^R!"due!8cQ4
+!8[\UhVJ54h>dQThZ!Q[h>dQ4h>dQThYdHMh>mWVp?i3Cg<._'mc*Bgq#EeEio]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]8"k&/>e
+g4di#cI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"d
+cI1"dc2c/<cI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcI1"dcMkrd=b6".mK7aW
+`aOA~>
+!quZ5p>uBR!;pp<!;pp<!<7-;!<7-?!<7-?!<7-;!<7-?!<.';!<7-?!;pp<!;pp<!"a2O!-<2]
+!-8,?F)q<]ErZ4>F8l4EErZ2]ErZ4>F8Z+7Erc:@p>uO2e]#eimf))=!!)0\h>l^;h>l^;h>l^;
+h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h?i?$hSmai
+K?_Z[rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^
+rlkSb!6rd-rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rltD\!)eC1R-"Lis7W7=~>
+!i2>Hp?hoYqu?Zrr;Zcss8W*!qu?Zrs8W*!s8W*!qu?Zrs8W*!s8W*!s8W*!r;Zcsr;Zcs&H;_1
+s8N'!rr<'!rr<'!!!*#urr<9'!!*'!!!)rsrW)`np?i$QhUTmKmJuDKmJuDKmJuDKmJuDKmJuDK
+mJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmLJCQ
+ma]SEMr*"@e_\j5ebK2OhUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUH_hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5c.-!Km[3DE3Lllo
+J,~>
+!m8N2p?ho\qqh>Qr8.GRs5*bUqqh>Qs5*bUs5*bUqqh>Qs5*bUs5*bUs5*bUr8.GRr8.GR&DdBe
+hVJ54h>dQ4h>dQ4!!*#Trr<8[!!(m4!!)rRrW)cN!<;c\A!,Kjb3&!Oio]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7ck0D-'M:U,+daljtdeNlLf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-t
+f$`-tf$`+Lf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-p`l_G8m[3DE
+IE'E<J,~>
+!rqu=p>u?QqfDc;r,_l<s)\2?qfDc;s)\2?s)\2?qfDc;s)\2?s)\2?s)\2?r,_l<r,_l<&9@gO
+F)q<]ErZ2]ErZ2]!!*">rr<7E!!%(]!!)q<rW)b8!<;cT"-h?\`W#"$hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhTa$rMp9MsrlkJoc1qA>blH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;n
+blH;nbllPsc-=f<blH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nbllSA`Pk`+k*Y95
+c1_1-J,~>
+!h?&@p?hrZ!;lfq!<3#u!<<)u!;uls!<<*!!<<)u!;uls!<<*!!<<*!!<<*!!;lfr!<3#u!<<*!
+!!*&u!!iN(!<<'!!<<#u%K?D.s8N'!s8N'!s8N)us8N)qrrE-"p?knMk0;H=mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"rpF[Ke_ZP@hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUVVM!*XsAR-k&2Umrla~>
+!liB.p?hr]!;kXP!<1jT!<:pT!;t^R!<:pU!<:pT!;t^R!<:pU!<:pU!<:pU!;kXQ!<1jT!<:pU
+!!(mT!!h?\!8cQ4!8d\T%Gh'bhVJ54hVJ54hVJ83hZ!TPh>mWVp?l"IhTF.'lJgsck2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k3D5Lb0J_'daljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljt
+daljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljtdaljt
+dalkGaoGRqm[3DEH-4-8J,~>
+!quZ5p>uBR!;gj:!<.'>!<7->!;pp<!<7-?!<7->!;pp<!<7-?!<7-?!<7-?!;gj;!<.'>!<7-?
+!!%*>!!dQF!-<2]!-A,>%<DLLF)q<]F)q<]F)q?\F8l7:Erc:@p>uUEhSmark2,8"h>l^;h>l^;
+h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;
+h>l^;h?`9#hWEt>c..`<c2PZ^;M!ttjo`U&p8!3~>
+!i2>Hp?hoYq#C3krVufrs8W*!s8W*!rVufrs8W*!rr;lrs8W*!qZ$Hnrr;lrrr;uu!ri6#rr;rt
+rr;uus8W*!s8Vusp]'sT"/P)0eZ\BEp?pJ]k+%ao"4bZH>(Q+/mK5J>Ua^f~>
+!m8N2p?ho\ptklJrSIJQs5*bUs5*bUrSIJQs5*bUrndPQs5*bUqVM,MrndPQrndYT!o<nWrndVS
+rndYTs5*bUs5*YRptc#Np?i$VhU9]Qjot2<cHb:3QIZ/db0F.@m[3DEIE'E<J,~>
+!rqu=p>u?QpiH<4rH%o;s)\2?s)\2?rH%o;s)\2?rc@u;s)\2?qK)Q7rc@u;rcA)>!cn>ArcA&=
+rcA)>s)\2?s)\)<pi?H8p>uIIe]lA<joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;k',\Ek3hBVc/+]8c.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(X`DV9LR-"LqpA^Y5~>
+!h?&@p?hrZ!5/@3!8.;P!<;c\"K^b9e`O+(s7ZKC!T'W<hZ)+,c!#\dR-k&2Umrla~>
+!liB.p?hr]!5.1g!8--/!<;c\=f(-+dc0QSlK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7C&o$5O"hOW6Of%S^/
+f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/
+f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f$;F\=b6".mK7aW`aOA~>
+!quZ5p>uBR!5*CQ!8)>n!<;cT"Jjo!c/,\es6adDc./?/e]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]n*4!)eC1R-"Lis7W7=~>
+!i2>Hp?hoY]Dqm2f)PI3?F8kOeaDl!me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Ks4,ZfXPVgrrn[Y;rn[Y;
+rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;
+rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[e?e]lWJJaSon"$)mI.=_~>
+!m8N2p?ho\]AEPffA6N-p?i'hinDiCYj)Dgp<qCKV3]g;d`Tj<JaSon"+A23@=S~>
+!rqu=p>u?Q]6!uPf5grlp>uR\hUTm5k3i62!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjKs7ZK;!T'W<eH=(8bu0,T
+R-"LqpA^Y5~>
+!h?&@p?hrZ!0R9^!<;c\"MNsShWD'1s8N2OhWD3Eh>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;
+h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;
+h>l^;h>l^;h>l^;h>l^;hZ)+,c%CT8R-k&2Umrla~>
+!liB.p?hr]!0Q+=!<;c\"h*FEf&Gu"jotJTdamE\QJ)GhcH:Qdm[3DEH-4-8J,~>
+!quZ5p>uBR!0M='!<;cT>I<8;e_]HFk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7os39*NXHqE:blPe1J``?^
+"3(<6Ujr~>
+!i2>Hp?hoYNrSh@"3o]jhYlR:mf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>K
+mf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)?lmcOQLk2u*Fk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7We_[Zam[3DE3LlloJ,~>
+!m8N2p?ho\O59m:p?i%&g>^ici`+dohW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhX^Bsg>]Q+gAfS$Z@VG2mK7mW
+b$ff~>
+!rqu=p>u?QO)k=$p>uIre_\i[h?E?@hUUJiQ.>oZ!3Cb6R-"LqpA^Y5~>
+!h?&@p?hrZ!0R9^!<;c\>LhTmk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk3hBg`I\&?s0_k,;YKM\
+0r1<gJ,~>
+!liB.p?hr]!0Q+=!<;c\>LM6^hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?ip,O[_L_`<s0_k,<VGh_
+H-4-8J,~>
+!quZ5p>uBR!0M='!<;cT>Kt^ThUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hWE\F]n-37s0_k,;YK5T
+`W,Y-J,~>
+!i2>Hp?lltrrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!
+rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!
+rr;][!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?m!%h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4
+h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4h>lC4
+hVS;+mK!9<mXaeWmb7(/<VGh_IE'E<J,~>
+!rqu=p?$EoEr^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]
+Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]Er^7]
+F*%BTjoGF4k(2ZGk1\qt;YK5Tc1_1-J,~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYd/O+.rl##R`P'7(rP\fEhTl/pmK!9<mXaeWmb7(/;YKM\0r1<gJ,~>
+!liB.p?ho\d/O4-_S3b`\d,s\^:M%mZJ*V(p?hq\JaS*WJaV7[!*/a\"*r&/@=S~>
+!quZ5p>u?Qd/O+.rl##R`P'7(rP\fEhTl/pjoGF4k(2ZGk1\qt;YK5T`W,Y-J,~>
+!i2>Hp?hoYdJj:)XS2Sl#kn;ls7ZKdXR=F7p?hq\JaS*WJaV7[!)iOY"$)mI.=_~>
+!m8N2p?ho\dJj:-Wq-/cqXt$fm],Qus7Yj\s+0ThmXaf[mJp8\mK7mWb$ff~>
+!rqu=p>u?QdJj:)XS2Sl#kn;ls7ZKdXR=F7p>uATJ`_OGJ`b\K!)iOQ"3pQ>S:C~>
+!h?&@p?hoYdJj9]XR?&\q<e:6[*SdGmK!9<mXaeWmb7(/;YKM\0r1<gJ,~>
+!liB.p?ho\dJjKdY3PTOo()5:r9=@Gf!`p)p?hq\JaS*WJaV7[!*/a\"*r&/@=S~>
+!quZ5p>u?QdJj9]XR?&\q<e:6[*SdGjoGF4k(2ZGk1\qt;YK5T`W,Y-J,~>
+!i2>Hp?hoYdJj9][-mqe$L[WUmcNs"mcNB5ci<_,!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\dJj9ZY3Q#Ws6fpPs5jIDk2Ostci<_,!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QdJj9][-mqe$L[WUmcNs"mcNB5ci<_$!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYdJj<^XR>NUpAaRZjoaK&e[3[&p?hq\JaS*WJaV7[!)iOY"#6UA.=_~>
+!liB.p?ho\dJjchWp]0?o'Yf.k2tOWg>^\hci<_,!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QdJj<^XR>NUpAaRZjoaK&e[3[&p>uATJ`_OGJ`b\K!)iOQ"3(<6Ujr~>
+!i2>Hp?hoYdJjck[-mYMk3hs2mcNZghWE\%ci<_,!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\dJjchY3tl?hWjOolK7*_g>^hlci<_,!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QdJjck[-mYMk3hs2mcNZghWE\%ci<_$!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYdJjck[.a449%E@tk3hBoe`P_qci<_,!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\dJjchY4D;'7+UYgk2t[[f&GDhci<_,!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QdJjck[.a449%E@tk3hBoe`P_qci<_$!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYdJs6[%efq0C>S[HmcNZghWEt-ci<_,!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\dJs6X%eBY.A_QS7k2PCSf&G\pci<_,!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QdJs6[%efq0C>S[HmcNZghWEt-ci<_$!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYdJs6["8;cgk5OfIjoaK.k-WJ7p?hq\JaS*WJaV7[!)iOY"#6UA.=_~>
+!liB.p?ho\dJjch^@qEok3hO"k2t[[g?R\'ci<_,!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QdJs6["8;cgk5OfIjoaK.k-WJ7p>uATJ`_OGJ`b\K!)iOQ"3(<6Ujr~>
+!i2>Hp?hoYdJj6\c2%ADpAaj[s6d8?s7Yj\s+0ThmXaf[mJp/YmK5J>Ua^f~>
+!m8N2p?ho\dJj9^b4bi7s8)]fs7-6bk-E>5p?hq\JaS*WJaV7[!*/a\"+A23@=S~>
+!rqu=p>u?QdJj6\c2%ADpAaj[s6d8?s7YRTs+0<`k(2[KjoA<Qjo`m%s."T~>
+!h?&@p?hoYdJj9ec0##nrV$0h!Tpc8s7Yj\s+0ThmXaf[mJp/YmK52>S1/s~>
+!liB.p?ho\dJjBacJIjSmf)bYpA4XbrrM8jci<_,!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QdJj9ec0##nrV$0h!Tpc8s7YRTs+0<`k(2[KjoA<Qjo`U&p8!3~>
+!i2>Hp?hoYf)Ga<roP$R[)L#/c.1)$pAaRCk3hZfSDNDjhWEtNs7Yj\s+0ThmXaf[mJp/YmK5J>
+Ua^f~>
+!m8N2p?ho\fDc]alJgschQF`8b0&#Tipug.io9+_d[AhKrSH*)p?hq\JaS*WJaV7[!*/a\"+A23
+@=S~>
+!rqu=p>u?Qf)Ga<roP$R[)L#/c.1)$pAaRCk3hZfSDNDjhWEtNs7YRTs+0<`k(2[KjoA<Qjo`m%
+s."T~>
+!h?&@p?hoYf`)!GXS_,fhWE\WhVPs6hTb3NqrS%<k2+Xaf)PI3!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\f`)$DY3,ZA&`2O(iniP+k1[u?k2PCWio]8"h>u3$f)PI3!<7W<JaS*Wg?nr@p?i$.
+b/Rk?~>
+!quZ5p>u?Qf`)!GXS_,fhWE\WhVPs6hTb3NqrS%<k2+Xaf)PI+!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYf`(uZ^&7m2pAb-c"on;YXIRQ7rsJK"k1/o"pAaR;^"<;XmK!9<mXaeWmb7(/;YKM\
+3LlloJ,~>
+!m8N2p?ho\f`))[](Z!srUq#tp@@qJii\Qhs8)Tcp?'fkp@@qBf"Tc9p?hq\JaS*WJaV7[!*/a\
+"+A23@=S~>
+!rqu=p>u?Qf`(uZ^&7m2pAb-c"on;YXIRQ7rsJK"k1/o"pAaR;^"<;XjoGF4k(2ZGk1\qt;YK5T
+c1_1-J,~>
+!h?&@p?hoYf`(uB^&@['mK_nBk3hB=Mq.e""7F-uc2R/2joD4/s7Yj\s+0ThmXaf[mJp/YmK52>
+S1/s~>
+!liB.p?ho\f`(uC])D4"mf2PQk3Ds."0.@+pAXUhm_YC3mcrrok+UE,p?hq\JaS*WJaV7[!*/a\
+"*r&/@=S~>
+!quZ5p>u?Qf`(uB^&@['mK_nBk3hB=Mq.e""7F-uc2R/2joD4/s7YRTs+0<`k(2[KjoA<Qjo`U&
+p8!3~>
+!i2>Hp?hoYf`)&D^%UmnpAaOrk3hBohX7b8c2[5*me4W,V!dC-hX72ks7Yj\s+0ThmXaf[mJp/Y
+mK5J>Ua^f~>
+!m8N2p?ho\f`*%e[dr_SmdBB*k2t[_hWh8+cM$\smde5tV<[("hWgfds7Yj\s+0ThmXaf[mJp8\
+mK7mWb$ff~>
+!rqu=p>u?Qf`)&D^%UmnpAaOrk3hBohX7b8c2[5*me4W,V!dC-hX72ks7YRTs+0<`k(2[KjoA<Q
+jo`m%s."T~>
+!h?&@p?hoYf`)2H^%Um^p?qYQk5X9Mm^.nsp?qABhS%d1`TH%6m\JJ7p?hq\JaS*WJaV7[!)iOY
+"#6UA.=_~>
+!liB.p?ho\f`*%a](5.So'Yr.k2P7Og?Pu'cLU8go%(P3Oi$,3g?PB`s7Yj\s+0ThmXaf[mJp8\
+mK7aW`aOA~>
+!quZ5p>u?Qf`)2H^%Um^p?qYQk5X9Mm^.nsp?qABhS%d1`TH%6m\JJ7p>uATJ`_OGJ`b\K!)iOQ
+"3(<6Ujr~>
+!i2>Hp?hoYf`*%h^&RfohX8q^mcNB_eb6A7ec5(*p8$7=P^DQLhY*bss7Yj\s+0ThmXaf[mJp/Y
+mK5J>Ua^f~>
+!m8N2p?ho\f`*%e])(jWf':]Kk2P7Of']i+cMHhknt"A.Q$MBCf']6`s7Yj\s+0ThmXaf[mJp8\
+mK7mWb$ff~>
+!rqu=p>u?Qf`*%h^&RfohX8q^mcNB_eb6A7ec5(*p8$7=P^DQLhY*bss7YRTs+0<`k(2[KjoA<Q
+jo`m%s."T~>
+!h?&@p?hoYf`*%``W)`dC3,$amcNZ^eaC,8hZ*<CeWd0'P]PC*hX72ks7Yj\s+0ThmXaf[mJp/Y
+mK52>S1/s~>
+!liB.p?ho\f`*%a_YTgSBlS^\k2P7KddFE+f)"h&cBYR#NHN\#f']6`s7Yj\s+0ThmXaf[mJp8\
+mK7aW`aOA~>
+!quZ5p>u?Qf`*%``W)`dC3,$amcNZ^eaC,8hZ*<CeWd0'P]PC*hX72ks7YRTs+0<`k(2[KjoA<Q
+jo`U&p8!3~>
+!i2>Hp?hoYf`*%hc2WEKC4i>Ek3hBgec3=QhZ*<L^"&X"S@uo(hZ'D's7Yj\s+0ThmXaf[mJp/Y
+mK5J>Ua^f~>
+!m8N2p?ho\f`*%eb5-O7Bn;i3k2tOWf(QD?gAga?]$?RdQ+"QdhY*Yps7Yj\s+0ThmXaf[mJp8\
+mK7mWb$ff~>
+!rqu=p>u?Qf`*%hc2WEKC4i>Ek3hBgec3=QhZ*<L^"&X"S@uo(hZ'D's7YRTs+0<`k(2[KjoA<Q
+jo`m%s."T~>
+!h?&@p?hoYf`))Mec5@*r9jUI'AhmO]q"6bs7Z0:c-=5Xmb[+"Ut>Y?mK!9<mXaeWmb7(/;YKM\
+0r1<gJ,~>
+!liB.p?ho\f`*%ecN!ItlK[g&lK7*_hY+COhZ*<Cm`rht_U@T'k454ts7Yj\s+0ThmXaf[mJp8\
+mK7aW`aOA~>
+!quZ5p>u?Qf`))Mec5@*r9jUI'AhmO]q"6bs7Z0:c-=5Xmb[+"Ut>Y?joGF4k(2ZGk1\qt;YK5T
+`W,Y-J,~>
+!i2>Hp?hoYf`(uRebK.KpAajd]r^AkrrDclrrAkHs7Yj\s7GaW!;Gm]!:T=U!9ESI!;>g\!8$W=
+!:fIW!9rnO!8d,D!:0%Q!.jRXmJp/YmK5J>Ua^f~>
+!m8N2p?ho\f`(uKf)5RHqYp0ns0AZ]s8)clrVm&tp@e@ZU"B><mK!:Zmed(ZmJm7UmJm7Jmf!4[
+mJm7=mJm7WmJm7OmJm7DmJm7QmJm6<m`+Yp<VGh_IE'E<J,~>
+!rqu=p>u?Qf`(uRebK.KpAajd]r^AkrrDclrrAkHs7YRTs7GIO!;GUU!:T%M!9E;A!;>OT!8$?5
+!:f1O!9rVG!8ci<!:/bI!.j:PjoA<Qjo`m%s."T~>
+!h?&@p?hoYf`)/WhVRDWmdC&IrVm8=[+4$qk3h[2pAajbrrAkHs7Yj\s7Pd[!:oOX!7C37!;,[Z
+!64F,!9rnO!8d,D!:0%Q!.jRXmJp/YmK52>S1/s~>
+!liB.p?ho\f`*%if%T-Ck3DC&o(MqVs8TO1f%T-ClK[g*p@e@_s8&G@s7Yj\s7Pd[!:oOX!7C37
+!;,[Z!64F,!9rnO!8d,D!:0%Q!.jRXmJp8\mK7aW`aOA~>
+!quZ5p>u?Qf`)/WhVRDWmdC&IrVm8=[+4$qk3h[2pAajbrrAkHs7YRTs7PLS!:o7P!7Bp/!;,CR
+!64.$!9rVG!8ci<!:/bI!.j:PjoA<Qjo`U&p8!3~>
+!i2>Hp?hoYf`(uRk5F`JpA4dj]uB.4mf3"WrrAkHs7Yj\s7Pd[!:oOX!:oOX!9*>G!;,[Z!6OX2
+!:K7Tl0\NOhX1@Dlg=`QJaUPG!)iOY"$)mI.=_~>
+!m8N2p?ho\f`(rOroOCLmdfrFqY^@#]"[%`k3h[.pA4X`rrAbEs7Yj\s7Pd[!:oOX!:oOX!9*>G
+!;,[Z!6OX2!:K7Tl0\NOhX1@Dlg=`QJaUPG!*/a\"+A23@=S~>
+!rqu=p>u?Qf`(uRk5F`JpA4dj]uB.4mf3"WrrAkHs7YRTs7PLS!:o7P!:o7P!9*&?!;,CR!6O@*
+!9WDDl/hsGhW=e<lfJ0IJ`au7!)iOQ"3pQ>S:C~>
+!h?&@p?hoYf`*%hc,IrHc-=e`e^`O,hVOd(c,IrHc-=e`e^`O,hUSFRs7Yj\s7Pg[!;Z'^!<2Bd
+!<2Ec!<)?^!!2KfrpK^brpBdemf!4_mem.cmf!4amK3IW!!*#d!<DQe!<;Hh!:BjTr;cibr;cfa
+rW)rcr;c]^"9@lX!:Kgdr9jOa!q$'VrW)rcrW)f_!s%`h!<2Be!:Kgds6]shmJu\R!<2Eb!<)?b
+!;c*c!:BgerU0UarU0UarpBsjmd:)CmJqh+bjGI/p?i#;Umrla~>
+!liB.p?ho\f`(uKb5TE\b5]cedf7nug(9[P`koa8b0&#TdaH^tg<u\Hs7Yj\s7Pg[!;Z'^!<2Bd
+!<2Ec!<)?^!!2KfrpK^brpBdemf!4_mem.cmf!4amK3IW!!*#d!<DQe!<;Hh!:BjTr;cibr;cfa
+rW)rcr;c]^"9@lX!:Kgdr9jOa!q$'VrW)rcrW)f_!s%`h!<2Be!:Kgds6]shmJu\R!<2Eb!<)?b
+!;c*c!:BgerU0UarU0UarpBsjmd:)CmJqh+bjGI2p?i$.b/Rk?~>
+!quZ5p>u?Qf`*%hc,IrHc-=e`e^`O,hVOd(c,IrHc-=e`e^`O,hUSFRs7YRTs7POS!;YdV!<2*\
+!<2-[!<)'V!!23^roX.ZroO4]k5GAWk5>;[k5GAYjoYVG!!*#\!<D9]!<;0`!9O:Dr;ciZr;cfY
+rW)r[r;c]V"9@TH!9X7\r9!tY!p0LFrW)r[rW)fW!s%H`!<2*]!9X7\s5jC`joFQB!<2-Z!<)'Z
+!;bg[!9O7]rT=%YrT=%YroOCbk2l[+joBtpbiSn'p>uIrs7W7=~>
+!i2>Hp?hoYf`(s6o;qu!o;hrBfDkR4!<;]ZrW)la&ch@f!!)HT!:K7Tmd:&Tmd:&TrU(9umd:)C
+mJm7TmJm7TmJm7TmK!.PrrE)errE)e!!)oarr<Mr!!)HT!!)HT!:K7T!;l0d!:K7TqsF[hmd:&T
+md:)LmKWa[mJm7TmK!.P%KPqb!!)HT!:K7Tmd:&TqsOIa%IO2rmd:&Tmd:)CmJm7amK3IWmK!.P
+"9@lX!!)oarr<o(!!)HT!!)HT!!)HT!!)HT!!)HT!:BgeJaUYJ!)iOY"$)mI.=_~>
+!m8N2p?ho\f`)!3Y4Sao[e$L!f%9rqmK!:Zmf!4amLfNfmJm7TmJu\C!:K7T!:K7T!<)<u!:K7T
+md:&Tmd:&Tmd:&Tmd:)Pmf*:emf*:emJm7amf*7rmJm7TmJm7TmJu\C!!)oa!s%cW!;l0h!:K7T
+!:K7Tp[/7dmd:&Tmd:)PmLB6bmJm7TmJu\C!:K7T!;l3a!"J>r!:K7T!:K7Tmd:&TqsFOdmd:)P
+mK<OXmJm7amf*8(mJm7TmJm7TmJm7TmJm7TmJm7TmJuYT!.jR[mJp8\mK7mWb$ff~>
+!rqu=p>u?Qf`(s6o;qu!o;hrBfDkR,!<;]RrW)lY&ch(V!!)0D!9WDDk2lXDk2lXDrT4^mk2l[+
+jo>DDjo>DDjo>DDjoG;@rrE)]rrE)]!!)oYrr<Mj!!)0D!!)0D!9WDD!;km\!9WDDqrS+`k2lXD
+k2l[<jp(nKjo>DDjoG;@%KPYR!!)0D!9WDDk2lXDqr[nY%H[Wjk2lXDk2l[+jo>DYjoYVGjoG;@
+"9@TH!!)oYrr<nu!!)0D!!)0D!!)0D!!)0D!!)0D!9O7]J`b):!)iOQ"3pQ>S:C~>
+!h?&@p?hoYNrSh@!<;WXrW)udrrE&d"p")Z!:BgerpBjgmd:)QmKN[ZmJu\C!<)<f!:K7TrpBad
+qsFFarU'afmd:)PmJm7dmK3IWmK!7S!s%cW!;c*d!:K7T!<)?c!<2Bh!:K7T!;Psa!:K7TrpBad
+qsFOdmd:)SmK3IW!!*#d!!)oa!!*#d!s%cW!<2Bg!:K7TqX+Idmd:&TrU0[crpBadqsFFarpBjg
+md:)RmK3IWmK!4R"T[uY!:Bi<m`=er;YKM\0r1<gJ,~>
+!liB.p?ho\NrSh@!<;WXrW)udrrE&d"p")Z!:BgerpBjgmd:)QmKN[ZmJu\C!<)<f!:K7TrpBad
+qsFFarU'afmd:)PmJm7dmK3IWmK!7S!s%cW!;c*d!:K7T!<)?c!<2Bh!:K7T!;Psa!:K7TrpBad
+qsFOdmd:)SmK3IW!!*#d!!)oa!!*#d!s%cW!<2Bg!:K7TqX+Idmd:&TrU0[crpBadqsFFarpBjg
+md:)RmK3IWmK!4R"T[uY!:Bi<m`=er<VGh_H-4-8J,~>
+!quZ5p>u?QNrSh8!<;WPrW)u\rrE&\"p!fJ!9O7]roO:_k2l[AjothJjoFQ+!<)$^!9WDDroO1\
+qrRkYrT41^k2l[@jo>D\joYVGjoGDC!s%KG!;bg\!9WDD!<)'[!<2*`!9WDD!;P[Y!9WDDroO1\
+qrRt\k2l[CjoYVG!!*#\!!)oY!!*#\!s%KG!<2*_!9WDDqW7n\k2lXDrT=+[roO1\qrRkYroO:_
+k2l[BjoYVGjoGAB"T[]I!9O94k/cZb;YK5T`W,Y-J,~>
+!i2>Hp?hoYNrSh@!<;QVrr<&eqZ-Za!<DQb!<;He!;u6h!:K7Tmd:)RmK3IWmK!7S!!)oa!!)uc
+!s%cW!;l0a!<2Bg!:K7TrpBjgmd:)Rmem.bmf!4dme["`mf!4_mK3IWmK!7S!!)oa!s%cW!<2Be
+!:K^aqsFFarpBjgmd:)SmK3IWmK!4Rr;cibrW)udqZ-N]!!*#d!s%cW!<)<f!:K7TrU'dgmd:&T
+JaUSH!)iOY"$)mI.=_~>
+!m8N2p?ho\NrSh@!<;QVrr<&eqZ-Za!<DQb!<;He!;u6h!:K7Tmd:)RmK3IWmK!7S!!)oa!!)uc
+!s%cW!;l0a!<2Bg!:K7TrpBjgmd:)Rmem.bmf!4dme["`mf!4_mK3IWmK!7S!!)oa!s%cW!<2Be
+!:K^aqsFFarpBjgmd:)SmK3IWmK!4Rr;cibrW)udqZ-N]!!*#d!s%cW!<)<f!:K7TrU'dgmd:&T
+JaUSH!*/a\"+A23@=S~>
+!rqu=p>u?QNrSh8!<;QNrr<&]qZ-ZY!<D9Z!<;0]!;ts`!9WDDk2l[BjoYVGjoGDC!!)oY!!)u[
+!s%KG!;kmY!<2*_!9WDDroO:_k2l[Bk5>;Zk5GA\k5,/Xk5GAWjoYVGjoGDC!!)oY!s%KG!<2*]
+!9X.YqrRkYroO:_k2l[CjoYVGjoGABr;ciZrW)u\qZ-NU!!*#\!s%KG!<)$^!9WDDrT44_k2lXD
+J`b#8!)iOQ"3pQ>S:C~>
+!h?&@p?hoYNrSh@!<;NU!s%`h!;l0d!:BgeqsFFar9aahmd:)CmK!4R!s%cW!<2Bd!;l0a!<)<f
+!:K7TqsFFarpBjgmd:)SmK3IWmK!7S!!*#d!!)rbrr<,g!!)f^rrDra!s%cW!<2Bd!;l0d!:K7T
+rpBjgmJm7]mJm7dmK3IWmK!7S!s%cW!<2Bd!<2Bd!;u9b!!;Qg!;Gm]!<2Bg!:K7TrU'afmd:)R
+mKEUYmJuYTJaUVI!)iOY"#6UA.=_~>
+!liB.p?ho\NrSh@!<;NU!s%`h!;l0d!:BgeqsFFar9aahmd:)CmK!4R!s%cW!<2Bd!;l0a!<)<f
+!:K7TqsFFarpBjgmd:)SmK3IWmK!7S!!*#d!!)rbrr<,g!!)f^rrDra!s%cW!<2Bd!;l0d!:K7T
+rpBjgmJm7]mJm7dmK3IWmK!7S!s%cW!<2Bd!<2Bd!;u9b!!;Qg!;Gm]!<2Bg!:K7TrU'afmd:)R
+mKEUYmJuYTJaUVI!*/a\"*r&/@=S~>
+!quZ5p>u?QNrSh8!<;NM!s%H`!;km\!9O7]qrRkYr8n1`k2l[+joGAB!s%KG!<2*\!;kmY!<)$^
+!9WDDqrRkYroO:_k2l[CjoYVGjoGDC!!*#\!!)rZrr<,_!!)fVrrDrY!s%KG!<2*\!;km\!9WDD
+roO:_jo>DUjo>D\joYVGjoGDC!s%KG!<2*\!<2*\!;u!Z!!;9_!;GUU!<2*_!9WDDrT41^k2l[B
+jokbIjoFNDJ`b&9!)iOQ"3(<6Ujr~>
+!i2>Hp?hoYNrSh@!<;`[!!)ucrrE)e!!)oa!s%cW!;l3a!<)<q!:K7Tmd:&Tmd:&Tmd:)SmJm7a
+mf*:emf*:emJm7amKWa[mJm7TmK!7S!s%cW!<2Bd!<2Bd!;l0d!:K7Tp[/"]qsFOdmd:)SmJm7a
+mK3IWmK!7S!s%cW!;Gmd!:K7T!:K7TrpBjgmd:)SmJm7dmJm7amK3IWmK!"L)?B3n!!)HT!!)HT
+!!)HT!!)HT!!)HT!:K7TJaUYJ!)iOY"$)mI.=_~>
+!m8N2p?ho\NrSh@!<;`[!!)ucrrE)e!!)oa!s%cW!;l3a!<)<q!:K7Tmd:&Tmd:&Tmd:)SmJm7a
+mf*:emf*:emJm7amKWa[mJm7TmK!7S!s%cW!<2Bd!<2Bd!;l0d!:K7Tp[/"]qsFOdmd:)SmJm7a
+mK3IWmK!7S!s%cW!;Gmd!:K7T!:K7TrpBjgmd:)SmJm7dmJm7amK3IWmK!"L)?B3n!!)HT!!)HT
+!!)HT!!)HT!!)HT!:K7TJaUYJ!*/a\"+A23@=S~>
+!rqu=p>u?QNrSh8!<;`S!!)u[rrE)]!!)oY!s%KG!;kpY!<)$i!9WDDk2lXDk2lXDk2l[Cjo>DY
+k5PG]k5PG]jo>DYjp(nKjo>DDjoGDC!s%KG!<2*\!<2*\!;km\!9WDDpZ;GUqrRt\k2l[Cjo>DY
+joYVGjoGDC!s%KG!;GU\!9WDD!9WDDroO:_k2l[Cjo>D\jo>DYjoYVGjoG/<)?Ap^!!)0D!!)0D
+!!)0D!!)0D!!)0D!9WDDJ`b):!)iOQ"3pQ>S:C~>
+!h?&@p?hoYNrSh@!<;`[qZ-T_r;clc!!*#dr;cibr;Zug!!)EerpK^brpBadrpBadqX4:^rpBad
+qsOC_rpBadrpBjgmd:)SmeZtamem.amem.cmem.^mK3IWmK!7S!!)oarr<)f!<2Bd!<2Eb!;l3_
+!<2Bd!<2Bg!:K7TrpKX`!:KdcrU0UaqsOC_rU0UarU0UarpBsjmd:&TmJqh+bjGI/p?i#;Umrla~>
+!liB.p?ho\NrSh@!<;`[qZ-T_r;clc!!*#dr;cibr;Zug!!)EerpK^brpBadrpBadqX4:^rpBad
+qsOC_rpBadrpBjgmd:)SmeZtamem.amem.cmem.^mK3IWmK!7S!!)oarr<)f!<2Bd!<2Eb!;l3_
+!<2Bd!<2Bg!:K7TrpKX`!:KdcrU0UaqsOC_rU0UarU0UarpBsjmd:&TmJqh+bjGI2p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<;`SqZ-TWr;cl[!!*#\r;ciZr;Zu_!!)-]roX.ZroO1\roO1\qW@_VroO1\
+qr[hWroO1\roO:_k2l[Ck5,,Yk5>;Yk5>;[k5>;VjoYVGjoGDC!!)oYrr<)^!<2*\!<2-Z!;kpW
+!<2*\!<2*_!9WDDroX(X!9X4[rT=%Yqr[hWrT=%YrT=%YroOCbk2lXDjoBtpbiSn'p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<91h!!'.h!!%T<K^Jh<p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<91h!!'.h!!%T<K^Jh?p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<91`!!'.`!!%T4K]W84p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<;c\p]/.u!!'.h!!%T<K^Jh<p?i#;Umrla~>
+!liB.p?ho\NrSh@!<;c\p]/.u!!'.h!!%T<K^Jh?p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<;cTp]/.m!!'.`!!%T4K]W84p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYi;`fWg&M'Pg].!8!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\i;`fWg&M'Pg].!8!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?Qi;`fWg&M'Pg].!0!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYr;Zcsrr;uurr;uunc/UhqZ$Emk5YG]oDegjli6\H!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\r;Zcsrr;uurr;uunc/UhqZ$Emk5YG]oDegjli6\H!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?Qr;Zcsrr;uurr;uunc/UhqZ$Emk5YG]oDegjli6\@!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYqu6Wrrr;uurr2runGiLgqu?ZrrVlitk5YG]p](6nkPt8D!<7W<JaS*Wg?nr=p?i#C
+S>7Ta~>
+!m8N2p?ho\qu6Wrrr;uurr2runGiLgqu?ZrrVlitk5YG]p](6nkPt8D!<7W<JaS*Wg?nr@p?i$2
+`l__?~>
+!rqu=p>u?Qqu6Wrrr;uurr2runGiLgqu?ZrrVlitk5YG]p](6nkPt8<!<7W4J`_OGg?&B5p>uJ%
+pA^Y5~>
+!h?&@p?hoYqu?Zrs8W&us8N'!rr;rtrr;os!<;rsr;Zcsq>^Eorr;`nrr;lrs8W*!rr;oss8W#t
+!ri6#rr;rtrr;uu!ri6#q>^0V!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\qu?Zrs8W&us8N'!rr;rtrr;os!<;rsr;Zcsq>^Eorr;`nrr;lrs8W*!rr;oss8W#t
+!ri6#rr;rtrr;uu!ri6#q>^0V!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?Qqu?Zrs8W&us8N'!rr;rtrr;os!<;rsr;Zcsq>^Eorr;`nrr;lrs8W*!rr;oss8W#t
+!ri6#rr;rtrr;uu!ri6#q>^0N!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYqu?Zrs8W&u%K?D.s8N'!rr<'!rr<&us8N'#rr<&ss8N)qs8N'%rr<'!s8Duus8E!$
+rr<'!s8E!>rr<'!!!*'!!!*'!!!*'!!!*'!!!*'!!!*$!!<<)u!!<0#!;c`hmK!9<mXaeWmb7(/
+;YKM\3LlloJ,~>
+!m8N2p?ho\qu?Zrs8W&u%K?D.s8N'!rr<'!rr<&us8N'#rr<&ss8N)qs8N'%rr<'!s8Duus8E!$
+rr<'!s8E!>rr<'!!!*'!!!*'!!!*'!!!*'!!!*'!!!*$!!<<)u!!<0#!;c`hmK!9<mXaeWmb7(/
+<VGh_IE'E<J,~>
+!rqu=p>u?Qqu?Zrs8W&u%K?D.s8N'!rr<'!rr<&us8N'#rr<&ss8N)qs8N'%rr<'!s8Duus8E!$
+rr<'!s8E!>rr<'!!!*'!!!*'!!!*'!!!*'!!!*'!!!*$!!<<)u!!<0#!;c`hjoGF4k(2ZGk1\qt
+;YK5Tc1_1-J,~>
+!h?&@p?hoYqu?Zr!<;ut"oeQ&rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'Irr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!!!*'!!!*'!!!*'!!!*$!!<3#u!!`H'!<<'!!;c`hmK!:\mf3!3s+13$
+s7ZKkp@dnS;YKM\0r1<gJ,~>
+!liB.p?ho\qu?Zr!<;ut"oeQ&rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'Irr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!!!*'!!!*'!!!*'!!!*$!!<3#u!!`H'!<<'!!;c`hmK!:\mK<%JpA0@?
+JcC<$qYp`qp?qM>o(MJO<VGh_H-4-8J,~>
+!quZ5p>u?Qqu?Zr!<;ut"oeQ&rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'Irr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!!!*'!!!*'!!!*'!!!*$!!<3#u!!`H'!<<'!!;c`hjoGGTk5XlJp1=9t
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKm@.sWos7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds8QL#s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKm>5&!i
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds8VfmrV$3Xp>u?Qp>uIrs7W7=~>
+!i2>Hp?hoYqYpp'rrE*!!<3'!rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'8rr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!qZ-ZrrrE*!rr<-#!!*#urr<9'!!*'!!!)lqp?hq\p$VkRr;Zfb@HR"?
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNY>mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"k$[W>mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNY4mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs7jok,Gp?qYImJp/YmK5J>Ua^f~>
+!m8N2p?ho\qYpp'rrE*!!<3'!rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'8rr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!qZ-ZrrrE*!rr<-#!!*#urr<9'!!*'!!!)lqp?hq\p$VkNs7U()qXWq6
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io4A.io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7[@-6J2io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io4D/io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7WhW!DOk3hg.o(DDN<VGh_IE'E<J,~>
+!rqu=p>u?QqYpp'rrE*!!<3'!rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'8rr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!qZ-ZrrrE*!rr<-#!!*#urr<9'!!*'!!!)lqp>uATp#c;B#PRTcp?peo
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+G*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+G*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+G*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+G&eHFakmcNs1joA<Qjo`m%s."T~>
+!h?&@p?hoYqZ$Nps8W&us8W*!rr;uu$NC)+s8N'!s8N'!r;Zcsqu?Zrrr;uu)?0[:s8N'!s8N'!
+s8N'!s8N'!rr<'!rr<&rs8N*!s8N'#rr<&us8N''rr<'!rr<&qs7Yj\s7Yj`p?qA2p4<6ps+14M
+rrVWNhYlU9p@dnS;YKM\0r1<gJ,~>
+!liB.p?ho\qZ$Nps8W&us8W*!rr;uu$NC)+s8N'!s8N'!r;Zcsqu?Zrrr;uu)?0[:s8N'!s8N'!
+s8N'!s8N'!rr<'!rr<&rs8N*!s8N'#rr<&us8N''rr<'!rr<&qs7Yj\s7Pdaio]7cqZ$TpqI'$n
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4VnpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZqI'$npA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4VppA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZp?(5_hV-iGmdBZ>mJp8\mK7aW`aOA~>
+!quZ5p>u?QqZ$Nps8W&us8W*!rr;uu$NC)+s8N'!s8N'!r;Zcsqu?Zrrr;uu)?0[:s8N'!s8N'!
+s8N'!s8N'!rr<'!rr<&rs8N*!s8N'#rr<&us8N''rr<'!rr<&qs7YRTs7YRTmf)&Ek4\iPp&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OOZp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OOZp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OOZp&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p''mXmbZL=rRLo8p>u?Qp>uIrs7W7=~>
+!i2>Hp?hoYqZ$Nps8W&us8W&u$i^2,s8N'!s8N'!s8E#qs8N)ts8;p2rr<'!rr<'!rr<'!rr<'!
+rr<'!rW!*$!!*'!rW)lrrrE*!rr<'!rW!<*!!*'!!!*'!!!)lqp?hq\p?qtCrn`5+JcC<$rr3&^
+hUVS]o^2]Wp?i#CS>7Ta~>
+!m8N2p?ho\qZ$Nps8W&us8W&u$i^2,s8N'!s8N'!s8E#qs8N)ts8;p2rr<'!rr<'!rr<'!rr<'!
+rr<'!rW!*$!!*'!rW)lrrrE*!rr<'!rW!<*!!*'!!!*'!!!)lqp?hq\p?hq;rRq8FrVp=&s8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqI'@"s8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)S"s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqHX'ss8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)Tck17uZg&UF2mJp8\mK7mWb$ff~>
+!rqu=p>u?QqZ$Nps8W&us8W&u$i^2,s8N'!s8N'!s8E#qs8N)ts8;p2rr<'!rr<'!rr<'!rr<'!
+rr<'!rW!*$!!*'!rW)lrrrE*!rr<'!rW!<*!!*'!!!*'!!!)lqp>uATp?);'"Rc!`pA]^;JbFcj
+#O^Hnc.1(heb%u(;YK5Tc1_1-J,~>
+!h?&@p?hoYqZ$Qqrr;uur;Z`rrr;uurr;lrqZ$Ems8W&urr;uus8W*!s8W*!s8Vuss8W*!rVufr
+rr;uu!ri6#rr;rtrr;uus8W*!qZ$9W!<;c\"lAD(e_^"Ns+137rri&qpAajUrs%W9e`P`=hY$::
+;YKM\0r1<gJ,~>
+!liB.p?ho\qZ$Qqrr;uur;Z`rrr;uurr;lrqZ$Ems8W&urr;uus8W*!s8W*!s8Vuss8W*!rVufr
+rr;uu!ri6#rr;rtrr;uus8W*!qZ$9W!<;c\"k),Ydamu?s+137rrhWelMp/>rs/8SdaI"+cJ%sZ
+!*/a\"*r&/@=S~>
+!quZ5p>u?QqZ$Qqrr;uur;Z`rrr;uurr;lrqZ$Ems8W&urr;uus8W*!s8W*!s8Vuss8W*!rVufr
+rr;uu!ri6#rr;rtrr;uus8W*!qZ$9O!<;cT"jPTJc->\QrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDclrrhKak5XTCrrDcjrrDcjrsADee]l@h
+e]lY4p>u?Qp>uIrs7W7=~>
+!i2>Hp?hoY^&S*4eGo71!<;c\!R9d+eH#;os+137rrhcimf2_ErrDKdeH=[Qc0"`f!)iOY"$)mI
+.=_~>
+!m8N2p?ho\^&S*4eGo71!<;c\#0,BFcI2.WJcC<$Q2_!Ps6BXLnc&mgim,itg;_:tp?ho\p?i$2
+`l__?~>
+!rqu=p>u?Q^&S*4eGo7)!<;cT$bb*8`Pq95p@eO[s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'C]lhY,h"hY.!Kp&b9fs8M^$s7ZKds6ea_`QcrH
+`SU=N!)iOQ"3pQ>S:C~>
+!h?&@p?hoY^&S*4eGo71!<;c\"i]?Tc.265s+137rrhcimf2_Ers.uBc/.U%`THm^!)iOY"#6UA
+.=_~>
+!liB.p?ho\^&S*4eGo71!<;c\#JSp?`mX/KqLSZts-EZfk5XTDk48NYqY&po`mWST_W(:W!*/a\
+"*r&/@=S~>
+!quZ5p>u?Q^&S*4eGo7)!<;cT"hiI2^!5^<p4*,9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7UsBpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAai4s7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds5s@Ds5s@Ts7ZKds7ZKds7ZKkp'9Hn^!5*@
+^#&JF!)iOQ"3(<6Ujr~>
+!i2>Hp?hoYNrSh@!<;c\!OU__blI0_s+137rrhKak5XT6rrMi]rlkQ%[(Y>imJp/YmK5J>Ua^f~>
+!m8N2p?ho\NrSh@!<;c\#I`@/`ldT;p4<'kqNgs\hYQ+*hX^LLp@@@g`ld#D^>ASO!*/a\"+A23
+@=S~>
+!rqu=p>u?QNrSh8!<;cT#-?(g]uB.%JbFZgQ1b@2p=8lenb*7VhS$VAeZ?I7p>u?Qp>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<;c\$FJ[?`RX,NpAb-mhu<ZVl2UV\qu6`us8N)os8)csrrDio!!)or!!%TM
+LAqD=s5s@Do)B$is5qkNe_[[Hk4\3C;YKM\0r1<gJ,~>
+!liB.p?ho\NrSh@!<;c\7BY4a_TLm/o(r%[pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA+dcpA4LZpA4LZpA4LZpA4LZpA4LZpA4L[!##/%qY'dZ!;?6hqY'dZqY'dZqYL8Bp&Og_pA4LZ
+pA4I_pA4LZpA+dcpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+J+ia4qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqCD:9pA4LZpA4LZpA4LZgA9P"gA:O>pA4LZpA4LZpA4LZo((e__TLH4]&*/K!*/a\
+"*r&/@=S~>
+!quZ5p>u?QNrSh8!<;cT7BFbQ[)Lnime6&Kme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me-YSme6)Bme6)Bme6)Bme6)Bme6)Bme6)G!##"np?qYB!:KO\p?qYBp?qYBpA4i>mJu\Kme6)B
+me6&Kme6)Bme-YSme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+J+!$up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp+,S)me6)Bme6)Bme6)Beb7Peeb8G)me6)Bme6)Bme6)BmdAWE]uA6t[,1N=!)iOQ
+"3(<6Ujr~>
+!i2>Hp?hoYNrSh@!<;c\"f1#"`QdQEp4*)Bs7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7QHds7ZKds7ZKds7ZKds7ZKds7ZKds7ZHms7ZKds7ZKds7ZHms7ZKds7ZKds7ZKd!;?Hds7ZKd
+s7ZKds7ZKdrrE)ms7ZKd!;?Hds7ZKds7ZKds7ZKds7UsBpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAai-s7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7Y":eb7Pes7ZKdp]1<e#Nj:Mc/,80hY-@;;YKM\
+3LlloJ,~>
+!m8N2p?ho\NrSh@!<;c\#bBPd^;f$to(%;(!;?!Wo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MVSo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ!;?!Wo(MYJo(MYJ!;?!Wo(MYJo(MYJnc87So(MYJ
+o(MYJo(MYJo(E(Wo(MYJnc87So(MYJo(MYJo(MYJo(MX(p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJF8#1uo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MY"o$6gOo(MYJo(W4bnd+[?`kKIDS\!\OmJp8\
+mK7mWb$ff~>
+!rqu=p>u?QNrSh8!<;cT#+WrO[(Y#PrpBadhsLIEl0\NOp?hn\p$Me[na6AWqsFFaJaS9\"NBfJ
+m`#+lp]1?^#j0[N[(X_S[+4m4!)iOQ"3pQ>S:C~>
+!h?&@p?hoYNrSh@!<;c\#Fs>h`QdQ=p4*,9!;?Hds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd!;?Hd
+s7ZHms7ZKds7ZKdrrE)ms7ZKds7ZKds7ZKd!;?Hds7ZKds7ZKd!;?Hds7QHds7ZKdrrE)ms7ZKd
+s7ZKds7ZKds7QHds7ZKdrrE)ms7ZKds7ZKds7ZKds7UsBpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAai8s7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKCs4./"s7ZKds7ZKds7ZKds7ZKmp'9a)^!5)t
+^#o%V!)iOY"#6UA.=_~>
+!liB.p?ho\NrSh@!<;c\$C0&Z]#NUpmdfoKk4/KPqsj^eq!nCboC;k]p@81`r:0gfqsj^enaZY[
+qsj^eJb"Qd"O?S`o$6gss6^-K`k'1<Q+GiGmJp8\mK7aW`aOA~>
+!quZ5p>u?QNrSh8!<;cT$C&fS[)LS`k3hX;k3`3LqsFFaq!J+^oBlSYp?hn\r9aObqsFFana6AW
+qsFFaJaS9\"NBfJm`"bb$0L[+`O*V/PdK<@joA<Qjo`U&p8!3~>
+!i2>Hp?hoYNrSh@!<;c\!K5M-`<k\pp?qVSp@\LSrW)ulr;clk!Uf[\!!N#`p&Ogb!!)Hdp''ja
+me-YSrVurlrVuummem+dp?qqR!q,a^rq6K_p?qYJr;clk!<DQe!<;a%me6&Kp@dqJme-YSme6V[
+"8;0V!<2]j!<;`ome6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]
+me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]
+me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]
+me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]
+me6)Jp&a[Umf)n]me6)Jp'C*[m`"n=m`"Vnp&a[Umf)nbme6)Bme6)2rl"urMnS!@mJp/YmK5J>
+Ua^f~>
+!m8N2p?ho\NrSh@!<;c\%ZSoR]#*=dlK[d;mcjf;rVuuamem+flL*s*rW!)hlL"Z?r;[/hmcs6*
+!:&tPmf!1dmf!1emcs`N&+8`NlL*s*!:K.?lL*s*lMU\bmcjf;rW!Jomcs6*!:'";mcs3?mcs6>
+!!_lVmJu\?mem-8lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*J*QIemcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*_Wo#'_AMS+lL*s*lL*s*lL*s*lK[Ng_RdV4NOn!?mJp8\
+mK7mWb$ff~>
+!rqu=p>u?QNrSh8!<;cT#(t16[(Y#HroO=`k2l[+rW)u\r;cfYrW)r[!<D9\!;ts^!9WDDk5G>\
+k5GA\k5>;Vjo>DWk5>;[joGJErW)lY!!)oY!!*#\rW)r[!!*#\r;_E2L?8WPk.Tojn`C,6e\/?'
+c%ECRp>u?Qp>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<;c\'T:Md^!5F%me6>Sp@\Idp@\L[mK!4Z%IWoip@\Idp@\Idp?hqZp(Zrg
+!;?*d!;?*dp@\L[p&G*dmJm7dp'0sYp&Og[meukZ!<;a!!;?*dp@\L[p?qqR!W_r^rUpm)me-YS
+p&G*dp&Og[!!)`d!;>jYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOY
+p&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOY
+p&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OO[
+p&rA.`V.:Mp&OO[pA=pipAaOchT`aYeVh-'p?hoYp?i#;Umrla~>
+!liB.p?ho\NrSh@!<;c\FG\Gc]#NIdlL*p;lL"WPlL"Z?l2^,;lL*s*!:K+P!:K+P!:K+PlL*s*
+lL"Z?l2UhPl2^,;!:K+P!:K+P!:K.?lL*p;lL*s*lL*p;!:K+PlL"Z?l2^,;lL*s*!:K.?lL*p;
+lL"Z?l2UhPl2^,;!!%N6mJu\?mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs4ilL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL)OW$,Z,Imcs6*mcs6<!"A;\mcrrg`k'1<M7VR;
+mJp8\mK7aW`aOA~>
+!quZ5p>u?QNrSh8!<;cT'SFZD[(Y#HhWEr#k2lXDk2l[+joG;@$NT>O!!)0D!!)0D!;kmk!9WDD
+!9WDDk2l[+jo>DDjo>DYjo>DXk5PG]jothJjoFQ+!;kmY!;kmj!9WDDk2lXDk2l[+jo>DDjoBtp
+L?8WPk.TojqW@\UrT4CBc+UKt`IkPSp>u?Qp>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<;c\7>'I9]uAjjmcNp;mcFN3mcFN3mJm7LmcNp;!9W_3!9W\LmcNp;mcNs"
+mcFN3mJu\;mJu\;!9W\LmcNs"!9W_3mcNs7!#"G^!:K";!:JtLk3`6;k3hC"k552_k3`6;!!%N2
+mcFN3mJu\;!9W_3!9W_3mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNqek3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"'^"iGmcNs"mcM4F^#m#jmcNs"mcOEI"m578mcNC*`<4YC^#&JN!)iOY
+"$)mI.=_~>
+!m8N2p?ho\NrSh@!<;c\#(=q:]#*1Xro+"[io0t;iWK8@iW&uWir9#XiWB2?iW/u;!!)oU!s%??
+!<1s^!92u<io0t:iW&uUiqi`UiW&uXiW]DBiW.ut!;kdR!<;$\!9*tYro++^io0stiW/u;!!%T0
+L>i?EijRjTqVqDQrSe+>g;:G<dXA^`p?ho\p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<;cT#'8&&[(Y#?rn[_WhUMW*hA$%@h>dQ4hUUH_!8cS_!8cQ4hUUH_rn[k0
+hVJ7hh>mQ3%KPA9!8cQ4hUUK>!8cS_rndMPs5!_Urn[n\hUMV_h>lE_rSIGPs5"1bh>dQ4hUMV_
+h>lE_!<1gU!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(
+!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(
+!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h#(!7h&)#HZIW
+hQ5Sjec"A&!<(a[e]ke7^!1W*eb8,*;YK5Tc1_1-J,~>
+!h?&@p?hoYNrSh@!<;c\'RSBT^!5F%k3h@3k3`6;k3`6;k3i3K!Uf+I!(ZJ>!9W_3!9W_3mcNp;
+mcFN3mcFN3mJu\;!9W_3mJu\;mcNs"!9W_3mcNs"!9W_3!9W\LmcFN3mcNs"mJu\;mcNs"!9X.Y
+J*uG!k3`6;k3`6;k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k'ug]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcG)Kk3hC"^$`T%^$b%Nk3hC"qu@/nk3hC"hT`aYeU,!lp?hoYp?i#C
+S>7Ta~>
+!liB.p?ho\NrSh@!<;c\"aSP9]#N>"iWB2?iW/u;!!*#XrW)uXqZ-ZU!!*#X!!)oU!s%??!<1s^
+!92u<io0t:iW&uUiW&uTiW&uXiW]DBiW.ut!;kaU!;kaV!93kUs5F+\io0t;iW&t0ieHFq[c4aT
+[ef"]!;tg]f#G;@dWrF\p?ho\p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;cT%<KM%[(X`@e_]-_hVJ83h>dQThYmNThYR<Qh>dQTh>dQQh?*c7h>mQ3
+"p!N:!8cQ4rS@MSqq_;QqVD2Prn[hZhVJ7hh>mH0!!)oQ!<D!R!<:mX!8cQ4rn[VTJ_l.<"K^I]
+hQ6S1quH`Q$.[nW]sPJtF0sftjoA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;c\"_uT,]uAk,joYVGjoGDC!!)rZrr<,_!!)oY!!*#\!!)oY!s%KG!<2*b
+!9WDDk2l[Bjo>DYjo>DXjo>D\jothJjoFQ+!;kmY!;km\!9O7]qrRt\k2l[Cjo>C4k(`"$[-"aX
+[/B(]!<2*chSm1IhJ0a\p?hoYp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\"`;])]#*%thI,=Cina[lina[lini\O!!)!Y!8c_liniYpiniYpini\O
+ina[liW.upiW.up!8c]8ini\O!8c_liniYpini\OiniYpiniYpina[liW.upini\O!8c_liniYp
+iW&t.hW!DOhVnOph>lElh>lElhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOJ)92Aini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\OiY(,-hW!DOhW!CphQG_<hW!DOhY7*Mh?VWK]#)m4]&*/K!*/a\
+"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT"_,`i['\*VeH5g%eH#U!!W^d-rmh#K!o<nWrm_81e^XZMe_U<)eJ-lj
+!7fU"hUU-Ve^XZMeH".MhUMW*eHXm\eH".MhYkt6!8c8V!7fU"e^XZMe_^;U!W^d-rRCuMh>dQT
+eHXm\eH".M!<1LM!7fs(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(
+eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(
+eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J(eH"J*
+eHD\uUt):?eH+OWp]1<D#L0W_^!1#neb8,*;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;c\"_uT4^!5F4joYVGjoGDC!!)oY!s%KG!;kmY!<2*\!;km\!9WDDroORg
+k2l[+jo>DDjo>DYjo>DXjpD+Njo>DDjoFQ+!;kmY!;km\!9WDDqrS+`k2l[+jo>C4k(`"$[-"aX
+[/9"^!<)$bhT`aYeS;e[p?hoYp?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;c\"_lE)]#*%sh?*c7h>mQ3!!)oQ!s%37!;kUQ!<1gT!;kUT!8cQ4rn\"_
+hVJ7hh>dQ4h>dQQh>dQPh?j8>h>dQ4h>lEh!;kUQ!;kUT!8cQ4qq_PXhVJ7hh>dP,hM0kiWnsc4
+Wr(ZL!<(aZf###<dV6;Lp?ho\p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;cT%:[Sq[(X`7e_\gVe^X[!eGoUHeH5g%eH#Ks!!*#K!!)oH!s$m%!<1LV
+!7fU"e^XX"e^XX"qpbZHqUGoQe^XX"e^XZMeH#Ks!!)oH!s$m%!;k:O!7fU"e^XX"J^oM*"JjSD
+eYN)mq>^oRhUU0$]sPJl@^P"cjoA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;c\'4Th;]uAjbk2,5#k2$*pk2$*pk5>8^hWE\Wr;[bmjoFQ#jo>D<k2,7W
+!8ci<k2,5#k2$(<k2-%:#3Oe)hWE\Wq>_Mth>dQ<!9W,<hW=e<hWE\Wh>lEphWE\W!9W/#r;[)Z
+joFQ#jo>C2h>lEphWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WJ)9>Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2)ojU^5hQhWE\WhWE\m!!V6AhWE\Orl"ur@_LXlmJp/YmK52>
+S1/s~>
+!m8N2p?ho\NrSh@!<;c\"^TQn]"Zbog&h?/g&V-+!W^s.r;cfMr;clO!!*#PrrDuN!s%'/!<1[V
+!8?-,!8?0*!;bFG!<:dQ!!q9Yg=cP\g&M-Ng&M-Mg&M-PgAM$Og&M-PgA_-Rg&Q]XL=ud(g7d5o
+qV(iIr7VD,_RdV4?+SndmJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cT#$T9b['\*&rm_;Te]e*=e]e*=eboIMc.1(hr;[b\eH".EeGoToe]lXh
+!6s$oe]lVEe]e'oe]n$m#1^uKc.1(hq>_Mcbl@ao!7f<oc.)doc.1(hblH#=c.1(h!7f?Er;[)I
+eH".EeGoT!blH#=c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hJ'HNge]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]jW/S-[B0c.1(hc.1):!!(:Cec3noZin(e>-uiRjoA<Qjo`U&
+p8!3~>
+!h?&@p?hoYNrSh@!<;c\Ip1CI^!5ErhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWCWrXQH>@hWE\WhWE\o!"IfIhWE\WhT`aYhHIVT
+p?hoYp?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;c\#?fKp]#)nLg4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:P-hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-h[hP&f"hV-i?hV-i?rW!D]hV-i?g=!jL`mS#$
+hY-@;<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT"^90i[(X_8eUc88eHDDmSCO/*ec#RGeHa@4[)L9n[,1N=!)iOQ"3pQ>
+S:C~>
+!i2>Hp?hoYNrSh@!<;c\##a=&`Pp]jJ*,VMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE[jhPB#(hWE\WhWE\Wh>lEphWEZ$k2+t6`Qd7;
+^#&JN!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\"]3di^;A<Lg4@tBg'!u#S_BY0g&M-Lg'?3G^;e`#]&*/K!*/a\"*r&/
+@=S~>
+!rqu=p>u?QNrSh8!<;cT#"m.R['\*&J(;foc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc%"9ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]iToc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1('c'6J;c.1(hc.1(hblH#=c.1&Fe]l@P[(X^V
+[+4m4!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\Io>.R`Qd9%hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWCp%Uunc@hWE\WhWEYuk2,7Wk2-+"#N!_Ee_X3;
+k4\3C;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\In\G=_T($\g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>8O[U#)L"g>:Q?g>:NphV-i?hV-i?hU]]`cIP\#
+hY-@;<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT"\R%Y]tM[AeUc88eHDDmSCO/!eHa@<]uA5g[,1N=!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\$VK:+c,JPrk2,7Wk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?`9#Uu%p(Uu(85h?)irk5O3Hk2,7Wk2+t>c.1ZC^#&JN
+!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\#=R.k`kp0XhLXC3g6UFqU"Z3oU%6nDhV-Q'`mWF+]&*/K!*/a\"*r&/
+@=S~>
+!rqu=p>u?QNrSh8!<;cT#!pMQ]tM\8J(;foc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc%"9ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]iToc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(/c'6JCc.1(hc.1(hc.1(hc.1&Fe]l@P`Pp(f
+[+4m4!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\"^91-e]lYDjoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojp9i+XQHVHXQJC=joXE%hYuX=hWE\ojp0bne_\PK^#o%V
+!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\#?Aptb0&/dg4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:P5hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-h_hPK)*hV-i?hV-i?hV-i?hV-iC#iaR`cIU-3
+]&*/K!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cT!`H_^rl'H=J^p"8"JjSDeYM`c#i=+N`RVq"[,1N=!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuXChWEsrhPB;0hYuX;hYuX;hYuX;hYuX<mcON*"0>tFk4\3C;YKM\
+0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\#B?ctda$.hgA]r:g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?hI,'og>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:[og>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?hI>3qg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:PWg7d5og>:Q?g>:Q?g>:Q?g>:iKk2+\;g9+_m
+hY-@;<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT#BQ]kc,IZHc%4DreX"_gSCO.[SFb;1h?VTUc./Un[,1N=!)iOQ"3(<6
+Ujr~>
+!h?&@p?hoYNrSh@!<;c\!khLVrn[_,hVNhGJ``<]"K^aek,e.9$1@NTk2t2lMoFQHmJp/YmK5J>
+Ua^f~>
+!liB.p?ho\NrSh@!<;c\#eE^Pf%/9tf%P]3J_laM"JstOhPKf"$0(C8hVQOOKtcF;mJp8\mK7mW
+b$ff~>
+!quZ5p>u?QNrSh8!<;cT!jkS=rlkM`c-:giJ^p+;"JjSDeYMcd$/Xh$e^_W2K>#h/joA<Qjo`m%
+s."T~>
+!i2>Hp?hoYNrSh@!<;c\#53sIXOZ1irn_)GhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\Wk$['.hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEs.hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\Wk#U@$hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhYuXBmcNB58nt`X
+p$MfXp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\#P*jBV9[ZGeq)P+g4S)ZhYuL=euhPXZHD>'mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cTC[R*QUrCU/c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(heR6YPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1?Pc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(heQ0rFc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@
+p#Z6Pp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;`[#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r@.b$"B'lZ^#&GM!)iOY"$)mI
+.=_~>
+!liB.p?ho\NrSh@!<;`[C@\fE1b:%+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbp?n<]W-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n&IS-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbp@OroY-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&X
+p?ho\p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;`S"7EO*0nCd).=irG.0VG(K<2c:p#Z6Pp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\rq6H^k0:kr]n*kJ^&5PH`QdQ5p@dnS;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\#4h3QlJB\#J\$EDJ\(cj"N&=<lLOZ:!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cTrpFI^hSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJd@'mVS]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tIg\]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJd@^NhU]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tLed[(Wi[`STbF
+p>u?Qp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;`[CA.)hmdArohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\O@-6>.hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVMZ&hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\O@HQG/hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOk2,7WmdBfA
+mJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;`["S2!KlK3ZSJ_kt7qVD88lLaKE<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;`SC@:6Pk2t4Ne_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j,@,BGje_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^\'ae_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j,@G]Pke_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^`O,hUUK5k2u+)
+joA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;ZYqZ-Za!!)NV!!)<P!!)9O!!(mD!!)?Q!!)ES!s%cW!:T=U!;,[Z!.jR:
+mJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;ZYqZ-Za!!)NV!!)<P!!)9O!!(mD!!)?Q!!)ES!s%cW!:T=U!;,[Z!.jR:
+mJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;ZQqZ-ZY!!)NN!!)<H!!)9G!!(m<!!)?I!!)EK!s%KG!:T%M!;,CR!.j:2
+joA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;]ZrrE#c!s%cW!8-]>!9rnO!8d,D!:0%Q!:B1S!8d,D!.jR:mJp/YmK52>
+S1/s~>
+!m8N2p?ho\NrSh@!<;]ZrrE#c!s%cW!8-]>!9rnO!8d,D!:0%Q!:B1S!8d,D!.jR:mJp8\mK7aW
+`aOA~>
+!rqu=p>u?QNrSh8!<;]RrrE#[!s%KG!8-E6!9rVG!8ci<!:/bI!:AnK!8ci<!.j:2joA<Qjo`U&
+p8!3~>
+!h?&@p?hoYNrSh@!<;`[rrDl_!!(dA!s%cW!9rnO!8d,D!:0%Q!:B1S!;u6b!9EPJ!.jR:mJp/Y
+mK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;`[rrDl_!!(dA!s%cW!9rnO!8d,D!:0%Q!:B1S!;u6b!9EPJ!.jR:mJp8\
+mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;`SrrDlW!!(d9!s%KG!9rVG!8ci<!:/bI!:AnK!;tsZ!9E8B!.j:2joA<Q
+jo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;`[!!)f^!!*#dr;cibr;cib"9@lX!:KgdrpK^br9jOa!q$'VrW)rcrW)f_
+!s%`h!<2Be!:Kgds6]shmJu\R!<2Eb!<)?b!;c*c!:BgerU0UarU0UarpBjgmd:)Omf!4bmem.c
+mK!=UrW)ob!!*#d!!*#d"p"&kmd:)CrW)rcr;cibr;clc!!*#d!!*#d!W_WgJaU2=!)iOY"#6UA
+.=_~>
+!m8N2p?ho\NrSh@!<;`[!!)f^!!*#dr;cibr;cib"9@lX!:KgdrpK^br9jOa!q$'VrW)rcrW)f_
+!s%`h!<2Be!:Kgds6]shmJu\R!<2Eb!<)?b!;c*c!:BgerU0UarU0UarpBjgmd:)Omf!4bmem.c
+mK!=UrW)ob!!*#d!!*#d"p"&kmd:)CrW)rcr;cibr;clc!!*#d!!*#d!W_WgJaU2=!*/a\"*r&/
+@=S~>
+!rqu=p>u?QNrSh8!<;`S!!)fV!!*#\r;ciZr;ciZ"9@TH!9X7\roX.Zr9!tY!p0LFrW)r[rW)fW
+!s%H`!<2*]!9X7\s5jC`joFQB!<2-Z!<)'Z!;bg[!9O7]rT=%YrT=%YroO:_k2l[?k5GAZk5>;[
+joGJErW)oZ!!*#\!!*#\"p!cck2l[+rW)r[r;ciZr;cl[!!*#\!!*#\!W_?_J`aW-!)iOQ"3(<6
+Ujr~>
+!h?&@p?hoYNrSh@!<;`[!!)f^$NTV_!!)HT!!)HT!;l0o!:K7T!:K7Tmd:&Tmd:)PmLB6bmJm7T
+mJu\C!:K7T!;l3a!"J>r!:K7T!:K7Tmd:&TqsFOdmd:)PmK<OXmJm7amf*8(mJm7TmJm7TmJm7T
+mJm7TmJm7TmJuYT!;l0r!:K7T!:K7T!:K7Tmd:)CmK!1QrrE)errE)e+oq$2md:&Tmd:)CmJm7T
+mJu\C!!)HT!!)Ee!:K7T!:K7TJaU,;!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;`[!!)f^$NTV_!!)HT!!)HT!;l0o!:K7T!:K7Tmd:&Tmd:)PmLB6bmJm7T
+mJu\C!:K7T!;l3a!"J>r!:K7T!:K7Tmd:&TqsFOdmd:)PmK<OXmJm7amf*8(mJm7TmJm7TmJm7T
+mJm7TmJm7TmJuYT!;l0r!:K7T!:K7T!:K7Tmd:)CmK!1QrrE)errE)e+oq$2md:&Tmd:)CmJm7T
+mJu\C!!)HT!!)Ee!:K7T!:K7TJaU,;!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;`S!!)fV$NT>O!!)0D!!)0D!;kmg!9WDD!9WDDk2lXDk2l[@jphCRjo>DD
+joFQ+!9WDD!;kpY!"J&j!9WDD!9WDDk2lXDqrRt\k2l[@job\Hjo>DYk5PDujo>DDjo>DDjo>DD
+jo>DDjo>DDjoFND!;kmj!9WDD!9WDD!9WDDk2l[+joG>ArrE)]rrE)]+opa*k2lXDk2l[+jo>DD
+joFQ+!!)0D!!)-]!9WDD!9WDDJ`aQ+!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;`[!!)f^!s%cW!<)<g!:K7T!;u6e!:K7TrpBjgmd:)SmJm7amK3IWmK!7S
+!s%`h!<2Bd!;l0a!<2Bg!:K7TrpBjgmd:)OmK<OXmJm7cmf*:dmJm7amJm7dmK3IWmK!4R!s%cW
+!<)<h!:K7TmK!.PrrE&d!s%cW!<2Bj!:K7Tmd:)PmL0*`!:BjT!:K7Tmd:)SmK3IWmK!7S!s%cW
+!<)<l!:K7TmJuYTmJqh+\aBGqp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;`[!!)f^!s%cW!<)<g!:K7T!;u6e!:K7TrpBjgmd:)SmJm7amK3IWmK!7S
+!s%`h!<2Bd!;l0a!<2Bg!:K7TrpBjgmd:)OmK<OXmJm7cmf*:dmJm7amJm7dmK3IWmK!4R!s%cW
+!<)<h!:K7TmK!.PrrE&d!s%cW!<2Bj!:K7Tmd:)PmL0*`!:BjT!:K7Tmd:)SmK3IWmK!7S!s%cW
+!<)<l!:K7TmJuYTmJqh+\aBGtp?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<;`S!!)fV!s%KG!<)$_!9WDD!;ts]!9WDDroO:_k2l[Cjo>DYjoYVGjoGDC
+!s%H`!<2*\!;kmY!<2*_!9WDDroO:_k2l[?job\Hjo>D[k5PG\jo>DYjo>D\joYVGjoGAB!s%KG
+!<)$`!9WDDjoG;@rrE&\!s%KG!<2*b!9WDDk2l[@jpV7P!9O:D!9WDDk2l[CjoYVGjoGDC!s%KG
+!<)$d!9WDDjoFNDjoBtp\`Nlip>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;`[!!)f^!s%cW!<)<c!<2Ec!<2Bg!:K7TrpBjgmd:)SmJm7amK3IWmK!7S
+!<DQb!;l0a!<2Bg!:K7TrpBjgmd:)Rmem.bmf!4dme["]mJm7dmK3IWmK!4R!s%cW!<)<g!:K7T
+!;c-\!<;He!<2Bj!:K7Tmd:)PmL0*`!:BjT!:K7Tmd:)SmK3IWmK!7S!s%cW!<)<l!:K7TmJuYT
+mJqh+\aBGqp?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;`[!!)f^!s%cW!<)<c!<2Ec!<2Bg!:K7TrpBjgmd:)SmJm7amK3IWmK!7S
+!<DQb!;l0a!<2Bg!:K7TrpBjgmd:)Rmem.bmf!4dme["]mJm7dmK3IWmK!4R!s%cW!<)<g!:K7T
+!;c-\!<;He!<2Bj!:K7Tmd:)PmL0*`!:BjT!:K7Tmd:)SmK3IWmK!7S!s%cW!<)<l!:K7TmJuYT
+mJqh+\aBGtp?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;`S!!)fV!s%KG!<)$[!<2-[!<2*_!9WDDroO:_k2l[Cjo>DYjoYVGjoGDC
+!<D9Z!;kmY!<2*_!9WDDroO:_k2l[Bk5>;Zk5GA\k5,/Ujo>D\joYVGjoGAB!s%KG!<)$_!9WDD
+!;bjT!<;0]!<2*b!9WDDk2l[@jpV7P!9O:D!9WDDk2l[CjoYVGjoGDC!s%KG!<)$d!9WDDjoFND
+joBtp\`Nlip>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;`[rrDl_!s%cW!<)<c!;u9b!<;Hh!:K7TrpBjgmd:)SmJm7amK3IWmK!7S
+!s%`h!;Gm]!<2Bg!:K7TrpBjgmd:)SmJm7dmJm7bmf*7gmJm7]mJm7dmK3IWmK!4R!s%cW!<)<h
+!:K7TmK!.PrrDra!!*#d"p")Z!:K7TqsFjmmJuYTmJu\C!:K7TrpBjgmd:)SmK3IWmK!4R#lsD]
+!:BjT!:Bi<m^_`c;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;`[rrDl_!s%cW!<)<c!;u9b!<;Hh!:K7TrpBjgmd:)SmJm7amK3IWmK!7S
+!s%`h!;Gm]!<2Bg!:K7TrpBjgmd:)SmJm7dmJm7bmf*7gmJm7]mJm7dmK3IWmK!4R!s%cW!<)<h
+!:K7TmK!.PrrDra!!*#d"p")Z!:K7TqsFjmmJuYTmJu\C!:K7TrpBjgmd:)SmK3IWmK!4R#lsD]
+!:BjT!:Bi<m^_`c<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;`SrrDlW!s%KG!<)$[!;u!Z!<;0`!9WDDroO:_k2l[Cjo>DYjoYVGjoGDC
+!s%H`!;GUU!<2*_!9WDDroO:_k2l[Cjo>D\jo>DZk5PD_jo>DUjo>D\joYVGjoGAB!s%KG!<)$`
+!9WDDjoG;@rrDrY!!*#\"p!fJ!9WDDqrS:ejoFNDjoFQ+!9WDDroO:_k2l[CjoYVGjoGAB#ls,M
+!9O:D!9O94k.0US;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;]ZrrE#c$NTV_!:K7T!:K7T!;l0g!:K7Tmd:)SmKWa[mJu\C!!)oa!s%cW
+!<2Bg!:K7Tp[/7dmd:&Tmd:)SmK3IWmK!7S!!*#d!!)oa!s%cW!;Gn"!:K7T!:K7T!:K7T!:K7T
+!:K7T!:K7Tmd:)PmJm7amKrs^mJm7TmJu\C!;l3a!<2Ed!<;Hh!:K7TrpCF"md:)CmJm7TmJm7T
+mJm7TmJm7dmf*9<m^_`c;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;]ZrrE#c$NTV_!:K7T!:K7T!;l0g!:K7Tmd:)SmKWa[mJu\C!!)oa!s%cW
+!<2Bg!:K7Tp[/7dmd:&Tmd:)SmK3IWmK!7S!!*#d!!)oa!s%cW!;Gn"!:K7T!:K7T!:K7T!:K7T
+!:K7T!:K7Tmd:)PmJm7amKrs^mJm7TmJu\C!;l3a!<2Ed!<;Hh!:K7TrpCF"md:)CmJm7TmJm7T
+mJm7TmJm7dmf*9<m^_`c<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;]RrrE#[$NT>O!9WDD!9WDD!;km_!9WDDk2l[Cjp(nKjoFQ+!!)oY!s%KG
+!<2*_!9WDDpZ;\\k2lXDk2l[CjoYVGjoGDC!!*#\!!)oY!s%KG!;GUo!9WDD!9WDD!9WDD!9WDD
+!9WDD!9WDDk2l[@jo>DYjpD+Njo>DDjoFQ+!;kpY!<2-\!<;0`!9WDDroOjok2l[+jo>DDjo>DD
+jo>DDjo>D\k5PF4k.0US;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;ZYquH`a!!*#dr;cibr;cib!s%cW!<2Bd!<2Ed!!2KfqsOIa!U]semJm7d
+mem._mem.bmJm7dmK3IWmK!7SqZ$War;cfar;c`_r;cfar;cfar;cib"9@lX!!)oar;cibrr<>m
+!:K7Tmd:&TqsFFarpBadrpBjgmd:)SmJm7dmf*7fmK!7Sr;cfa!!*#d!!*#d!!%T<]^>btp?i#;
+Umrla~>
+!m8N2p?ho\NrSh@!<;ZYquH`a!!*#dr;cibr;cib!s%cW!<2Bd!<2Ed!!2KfqsOIa!U]semJm7d
+mem._mem.bmJm7dmK3IWmK!7SqZ$War;cfar;c`_r;cfar;cfar;cib"9@lX!!)oar;cibrr<>m
+!:K7Tmd:&TqsFFarpBadrpBjgmd:)SmJm7dmf*7fmK!7Sr;cfa!!*#d!!*#d!!%T<]^>c"p?i$.
+b/Rk?~>
+!rqu=p>u?QNrSh8!<;ZQquH`Y!!*#\r;ciZr;ciZ!s%KG!<2*\!<2-\!!23^qr[nY!TjC]jo>D\
+k5>;Wk5>;Zjo>D\joYVGjoGDCqZ$WYr;cfYr;c`Wr;cfYr;cfYr;ciZ"9@TH!!)oYr;ciZrr<>e
+!9WDDk2lXDqrRkYroO1\roO:_k2l[Cjo>D\k5PD^joGDCr;cfY!!*#\!!*#\!!%T4]]K2lp>uIr
+s7W7=~>
+!h?&@p?hoYNrSh@!<::2rrD3L!!%T<JaTZ.!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<::2rrD3L!!%T<JaTZ.!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<::*rrD3D!!%T4J`a)s!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<:C5r;bsI!!([>q>c*7JaV@^!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<:C5r;bsI!!([>q>c*7JaV@^!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<:C-r;bsA!!([6q>c*/J`beN!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\s7V$DJcC<$pAb*bp?hoYp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\"7kmRqLSZts+14Hrrr8mmdff:p?ho\p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<;cTs6fjZAcMK(pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAb/#pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds'YR#pAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAb.rpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7ZKkpAOFQjoA<Q
+jo`U&p8!3~>
+!h?&@p?hoYNrSh@!<;`[s7ZBjs6a=XmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+k$[W>mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNY>mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"k#Up4mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mec,Lme6ABp@[hR;YKM\
+3LlloJ,~>
+!liB.p?ho\NrSh@!<;`[s763`B)h_ulK7*gio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7[@-6J2io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io4A.io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7[@HQS3io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_iniPOhW!\co'Z)A
+mJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;`Ss6^-cmf3"KhVQf^h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+hZ).*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hZ).*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*hZ).*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hYYh+hWF7gme,]B;YK5Tc1_1-
+J,~>
+!i2>Hp?hoYNrSh@!<;c\"SV9Ok4XB+JcC<$s8N/gk2-(!rq?'R!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;`[#3+e)lMCP\rq^$rqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'd^@.sHjqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqYFUnqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'd^@eTZlqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*
+p?ho\p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<;cT!:KjC!p94Vqt:$Xrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6N`p?pefc2H2lme5cC;YK5T`W,Y-
+J,~>
+!h?&@p?hoYNrSh@!<;c\s5s=;JcC<$JcG`L!p8@irSI27!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\!8d\.!;?Bk@J^$#s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)S"s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqI'@"s8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)Rss8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqY'(&df%l"lLjQF
+<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cTr7(r<pAajdJbFZgK_>Z=hTa<qc.1A:joA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;c\"lAD(e_^"Ns+137rri&qpAajUrs%W9e`P`=hY$::;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\"k),Ydamu?s+137rrhWelMp/>rs/8SdaI"+cJ%sZ!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT"jPTJc->\QrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDclrrhKak5XTCrrDcjrrDcjrsADee]l@he]lY4p>u?Qp>uIr
+s7W7=~>
+!h?&@p?hoYNrSh@!<;c\!R9d+eH#;os+137rrhcimf2_ErrDKdeH=[Qc0"`f!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\#0,BFcI2.WJcC<$Q2_!Ps6BXLnc&mgim,itg;_:tp?ho\p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;cT$bb*8`Pq95p@eO[s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'C]lhY,h"hY.!Kp&b9fs8M^$s7ZKds6ea_`QcrH`SU=N
+!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\"i]?Tc.265s+137rrhcimf2_Ers.uBc/.U%`THm^!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\#JSp?`mX/KqLSZts-EZfk5XTDk48NYqY&po`mWST_W(:W!*/a\"*r&/
+@=S~>
+!rqu=p>u?QNrSh8!<;cT"hiI2^!5^<p4*,9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7UsBpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAai4s7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds5s@Ds5s@Ts7ZKds7ZKds7ZKkp'9Hn^!5*@^#&JF
+!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\!OU__blI0_s+137rrhKak5XT6rrMi]rlkQ%[(Y>imJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;c\#I`@/`ldT;p4<'kqNgs\hYQ+*hX^LLp@@@g`ld#D^>ASO!*/a\"+A23
+@=S~>
+!quZ5p>u?QNrSh8!<;cT#-?(g]uB.%JbFZgQ1b@2p=8lenb*7VhS$VAeZ?I7p>u?Qp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\#IN@<`RX,NpAP$k!;6?l!;ZZp!<3#u!<)p!!<3&hrr<&Ss82kJs+14H
+rrhKak5XT7rsAE!k1.H$hR'uYp?hoYp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\B!0_-_TLm/o(r(Vp&G*hpA4LZpA4LZpA4I_pA4LZpA4LZ!!)`hp&G*h
+pA4I_p&Og_pA4LZpA4LZpA4LZpA+dcpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+quD6CpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4K4qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZ,l762pA4LZgA9P"gA:O>pA4LZpA4LZpA4LZo((e__TLH4]&*/K
+!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cTAus7r[)Lnime6)BmJm7\me6)Bme6)Bme6&Kme6)Bme6)B!!)H\mJm7\
+me6&KmJu\Kme6)Bme6)Bme6)Bme-YSme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+quD6?me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6'up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYB,kg["me6)Beb7Peeb8G)me6)Bme6)Bme6)BmdAWE]uA6t[,1N=
+!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\"f1#"`QdQEp*Kb4rr<&ms7ZKds7ZKds7ZHms7ZKds7ZKdrrE)mrr<&m
+s7QEmJ,]NKpAajdpAajdpAajdpAagdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+!<;cmpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdp4*,9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7T1epAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAaj:p=8lepAajdp@nXep'9a)`Qd88^#&JN!)iOY
+"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\/tLS5^;f$to()MFp&G*`p@@qJp@@qJp@@nWp@@qJp@@qJp&OgWp&G*`
+p@81`J+`m9o(MYJo(MYJo(MYJo(MVSo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+!;?!Wo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJnpgB(p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@:rOo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MY"o$6gOo(MYJo(W4bnd+[?`kKIDS\!\OmJp8\
+mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cT#+WrO[(Y#Pr9jRbp$Me[q!J+^rpKddrpKdd!U]sXmJm7CmJm6<mXag!
+mKCMs`U:_Cme?e^mKht*]sPJtS@$i?joA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;c\$_5bl`QdQ=pAajdpAP%1pAajdpAajdpAagdpAajdpAajdp&Ogdp&G)B
+s7ZHms7QHds7ZKds7ZKds7ZKd!;?Ems7ZKds7ZKds7ZKds7ZKds7ZKdrrE)ms7ZKds7ZKds7ZKd
+!;?Hds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKdJ,f6BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdp1F?us7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKCs4./"s7ZKds7ZKds7ZKds7ZKdp?'W5c./>t
+k4\3C;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\#F3`W]#NUpmeu_U!;>s`!;Q*b!<2Qh!<2Nk!:o[\o^W(ao'ueInc/[]
+nc/Z@nq$B)nc[8/cLT9Oo)J+_hT!.HdZqE#p?ho\p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<;cT#F*KP[)LS`k5F`I!;>g\!;Ps^!<2Ed!<2Bg!:K7To^2e]md:)AmJm7Y
+mJm6<mXag!mKCMs`U:_9mKr%De]"o7c'5Tlp>u?Qp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;c\!K5M-`=:ttp?qYB!!)]mp?qYJr;cij$ip"h!;?-Sp?qVSp?qkZ#57Hb
+me-YSrW)rkrW)ulrW!#f!;?Bl!q,dUrW!/jp@\LS!:Kj[rW)ulr;cij#k%ESp&G*\p?qqR!:Kdc
+"8;-_!<2Zn!;>j[!!;T^mf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp'C*[m`"n=m`"Vnp&a[Umf)nbme6)Bme6)2rl"urMnS!@mJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;c\&rk>V]#*=dlK[g&!!)Eemcs6*r;[ArlL"Z?l2^,;lL*s*!:K.N!!_lV
+!:&tPmf!1fmcs6>!!2NQrW!#b!:'O`!p]4=rW!8imcjf;!:'";mf!1emcs`N&+8`NlL*s*!!)<P
+lL*s*lMU\hmcjcPmcs3?mcscOJ*QIemcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mXONilL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lGDi'lGDiSlL*s*lL#5Kmcs6*mcs*"hSQk@dZ(ipp?ho\
+p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;cT#(t16[(Y#HrT=+[!TjC\k5>;ZjoYVGjoG;@!W_BFr;cl["9@TH!9X7\
+roX1[s5s:\!p0LFrW)r[rW)r[!W_?_rT=(Zs5s7[qW@eXqW@_Vs5s=]roO7^k2uXCJ``!T"MNs2
+k.U<I#i=+F[(X_:[+4m4!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\#E.-W^!5F%mf)n^!;>g\rUp3kr:U?_!;6Bmp?qnQ/-,,3!;?*dme-YS
+p&G*dp&Og[!;?*d!;>g\p@\Idme-YSp&OOS!!)`d!!)uk%.<fhp@\Idp@\Idp?qkPrW)rk!:KdY%
+06+q!;?-S!;6Edp&G*kp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp
+&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp
+&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OO[p&rA.`
+V.:Mp&OO[pA=pipAaOchT`aYeVh-'p?hoYp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\Ar4sU]#NIdlL*s*!:K+PlL*s*!:K.?lL*p;l2UhPlL*s*l2^,;!:K+P
+lL"Z?l2UhPl2^,;!:K+P!:K+PlL"WPlL"Z?l2^,;!!)<P!!)<PlL*s*!:K+P!:K+P!:K.?lL*s*
+rW!`%lL*s*lL*s*!:K+PlL*p;l2^,;!!%N6mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs4glL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL)OW_X>;/lL*s*lL+QM%.<EKlK6g?]#N0T]&*/K
+!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT#D::7[(Y#HhYuX>!9WDDrT4([qrRt\jo>DYjt$MpjoFQ+!9WDDk2lXD
+k2l[+joFQ+!!)0D!9WDD!9WDDk2l[+jo>DDjo>DYjp1tLjo>DDjo>DXk5GAUjoYVGjoGDC"p!cc
+k2lXDJ``$U"MNs2k.UWRquH]X#i<h>[(XG2[,1N=!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\BS50\]uAjjmcNs"!9W\L!9W_3!!)HLmcNp;mJu\;mcNs"mJm7L!9W\L
+mJu\;mJu\;mJuYT!9W_3!9W\LmcFN3mcFN3!!)HLmJu\;!9W_3mcNs"!9W\LmcNs"!9W_3mcNs"
+mcOKK&E`ECmcNs"!9W\LmcFN3!!%N:k3`6;k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hA]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcM4F^#m#jmcNs"!Uf+J!!VNQk3hBgrl"uiK>$.8
+mJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;c\#(=q:]#*1XrSdq[io0q<ro3qXr8IbXiW/i7rr<8_!92u<iW/u;!!*#X
+!s%<\!<1s^!92u<io0t;iWB2?!!*#X!s%??!;b[W!92u<rSdeWpu;8QqVhe]io0stiW.s<!<1sX
+!.j-jiWQ^L[c4aliqrfTiX"Dp_RdV4ICe;/mJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cT#'8&&[(Y#?rS@h\e_U9+hVQc_!<1gZe_U;_!8c9(hZ!Q[h>lEh!8[_T
+h>dQTh?*c7!!*#T%04r8!8cQ4e_]-_h>dQTh?*c7eH#R)#1_Se!8cQ4rS@PTebn8*e_]0^!!(RI
+h@A'9hVJ7heH"G+!8c8_!<1gTebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(
+ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(
+ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ec">0
+XOXE/XPVgarSIGPrS@h1c+UKtc#^8Bp>u?Qp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\$%(4I^!5F%k3hC/!!DZOmcOKK*p2nQ!!)HLmcNs"mcNp;mJu\;!9O:D
+mcFN3mcFN3qZ$ukjoFQ3!:K";!:K^a,3J:nmcNs"mcNp;mcFN3mcNp;mcNs"mcNs"mcNp;!9W_3
+r;[&ijo>DL!:K^aJ*-1]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mX=6ck3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"^$`T%^$b%Nk3hC"qu@/nk3hC"hT`aYeU,!lp?hoYp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\"aSP9]#N>"iqi`Sir/rWir9#RiWfJC!92u<iW/u;!!*#X!<D-V!<;$\
+!92u<ro*qYiqi`UiW&uTiWB2?iW/r:!!)`PrrE&Xr;clWrr<,[!93kUJ`;aM"Ld<uijS^CquHZS
+#M-o+`mT.DhY-@;<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT$$4)![(X`@e_]0[!<(dR!<1jT!;PCU!8[_4h>lC4rn[VTrn[YUhYR<Q
+h?*c7h>mQ3!<D!R!<:mU!;bOS!8cQ4rS@MSp>5fLrndSRs5*bU!o<q6qZ)3(O5:#@hQ5S8qVM,M
+rn[t3hT`a@^!1W*hY-(3;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;c\"_uT,]uAk,jo>D[jo>DYk5PG]joPPF!;YdV!<;3\!<2*\!<2*_!9O7]
+qrRt\k2l[CjoYVG!!)oY!!)lX!s%KG!<)$[!;5IV!9WDDroO1\roO@ajoFND!.j9jjoi'R[-"an
+k4erUjp0b^]uAiC^#&JN!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\"`;])]#*%thAbGSini\O!8c_liniYp!8c]8iW.upini\OinjY7!T)i8
+!)MV2iW.upiW.s<!8c_liniYpina[lina[l!!)$8ini\O!8c_lini\O!8c]8ini\O!8c_lini\O
+ini\OiW.up!8c_l!8c_l!8[_4!!%N.hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!CAini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\OingipY26><ini\Op]1<M#M-c'_U<;4hY-@;<VGh_
+IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT"_,`i['\*VeHGs'e_\gVrm_G6e^XX"e_U;V!7fWVr71cHs4.)Krm_5R
+hUU-VeGoUIeI::7e^XZMhUMVV!!(mReGoUIeHXm\!7fU"hYu%,!7fs(eH"J)eH5g.eH#U!!!*#K
+#QWBTeGoU"e_^5S!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(
+!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(
+!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8d_*"JjSDeYN2p
+!T)B%!<1LRc*Xjkc!n'1p>u?Qp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\"_uT4^!5F4jo>D[k5PGYjothJjoFQ+!;bjX!<)'[!<2*\!<2*_!9WDD
+qrRt\k2l[CjoYVGjoG;@!!)lX#QX#L!!)0D!!)oY!!)u[rrE)]!!*#\!!*#\rrE&\!!%T4Mrk/L
+k-X9Xqr[_TrT4@Ac+VBPC;&d'mJp/YmK52>S1/s~>
+!m8N2p?ho\NrSh@!<;c\"_lE)]#*%sh>dQShZ!TQh?Eu:h>lEh!;bRP!<(dS!<1gT!<1gW!8cQ4
+qq_DThVJ83h?*c7h>mH0!!)lP#QW`<!!(m4!!)oQ!!)uSrrE)U!!*#T!!*#TrrE&T!!%T,Mr"T:
+hQ#G4qqh/LrS@e1_Rdb8BtE0pmJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cT$=_8n[(X`7e_\gVrRLoJqpblNe^XZMeH#HrrrE#JrrE&K!!*#K!s$m%
+!;k:K!7fU"rm_)Ne^XZseGoUGeHc0*eGoU"eGoUHeGoUJec,XLeGoUKeGoUKec,XKeGoT#eVhr\
+Ut)9kV#/^=!"7?6e^_pX[(XFf[,1N=!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\&n9_:]uAjbk2$(<k2,7WjoFQ#r;[u&hW=h#h>dQ<hWE\Wh>dQ<hWEYp
+hWE\W!9W/#!9W/#r;[8_jo>D<!8ckp!8ckpr;[;hh>lEphWE\Wh>dQ<hYdEYk2,7Wk2,7t!!;$>
+hYR9Xk2$(<k2,7Wr;_?0hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE[Ck2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2)ojUu%p(k2,7Wk2-"9"lACuk2+to`<4t+^#&JN!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\"^TQn]"ZbpgA_0Ng&_9.gAM$Ng&qE0g&M-MgA_0Og&M-Og&M-Pg&M-P
+gAM$OgA_-Rg&V-+!!*#Pr;clO!!)lLrrE)Qr;c]JqZ-WLqZ-ZMrrE#Or;_E&O4j`1g7d5oqV(iI
+r7VD,_RdV4?+SndmJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cT&mEPn['\*&e^XX"e]lXheH".Er;[tjc.)gEbl@aoc.1(hbl@aoc.1&=
+c.1(h!7f?E!7f?Er;[8NeGoTo!6s'=!6s'=r;[;WblH#=c.1(hbl@aoc2@VHe]lXhe]lYA!!:Eq
+c2.JGe]e'oe]lXhr;_>tc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1'ee]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]jW/SB[SKe]lXhe]n!l!6tMns3:SN"MN&`[+4m4!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\Ip1CI^!5ErhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWCWrXQH>@hWE\WhWE\o!"IfIhWE\WhT`aYhHIVT
+p?hoYp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\#?fKp]#)nLg4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:P-hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-h[hP&f"hV-i?hV-i?rW!D]hV-i?g=!jL`mS#$
+hY-@;<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT"^90i[(X_8eUc88eHDDmSCO/*ec#RGeHa@4[)L9n[,1N=!)iOQ"3(<6
+Ujr~>
+!h?&@p?hoYNrSh@!<;c\##a=&`Pp]jJ*,VMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE[jhPB#(hWE\WhWE\Wh>lEphWEZ$k2+t6`Qd7;
+^#&JN!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\"]3di^;A<Lg4@tBg'!u#S_BY0g&M-Lg'?3G^;e`#]&*/K!*/a\"+A23
+@=S~>
+!quZ5p>u?QNrSh8!<;cT#"m.R['\*&J(;foc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc%"9ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]iToc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1('c'6J;c.1(hc.1(hblH#=c.1&Fe]l@P[(X^V
+[+4m4!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\Io>.R`Qd9%hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWCp%Uunc@hWE\WhWEYuk2,7Wk2-+"#N!_Ee_X3;
+k4\3C;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\In\G=_T($\g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>8O[U#)L"g>:Q?g>:NphV-i?hV-i?hU]]`cIP\#
+hY-@;<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT"\R%Y]tM[AeUc88eHDDmSCO/!eHa@<]uA5g[,1N=!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\$VK:+c,JPrk2,7Wk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?`9#Uu%p(Uu(85h?)irk5O3Hk2,7Wk2+t>c.1ZC^#&JN
+!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\#=R.k`kp0XhLXC3g6UFqU"Z3oU%6nDhV-Q'`mWF+]&*/K!*/a\"+A23
+@=S~>
+!quZ5p>u?QNrSh8!<;cT#!pMQ]tM\8J(;foc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc%"9ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]iToc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(/c'6JCc.1(hc.1(hc.1(hc.1&Fe]l@P`Pp(f
+[+4m4!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\"^91-e]lYDjoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojp9i+XQHVHXQJC=joXE%hYuX=hWE\ojp0bne_\PK^#o%V
+!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\#?Aptb0&/dg4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:P5hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-h_hPK)*hV-i?hV-i?hV-i?hV-iC#iaR`cIU-3
+]&*/K!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT!`H_^rl'H=J^p"8"JjSDeYM`c#i=+N`RVq"[,1N=!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuXChWEsrhPB;0hYuX;hYuX;hYuX;hYuX<mcON*"0>tFk4\3C;YKM\
+3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\#B?ctda$.hgA]r:g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?hI,'og>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:[og>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?hI>3qg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:PWg7d5og>:Q?g>:Q?g>:Q?g>:iKk2+\;g9+_m
+hY-@;<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT#BQ]kc,IZHc%4DreX"_gSCO.[SFb;1h?VTUc./Un[,1N=!)iOQ"3pQ>
+S:C~>
+!i2>Hp?hoYNrSh@!<;c\!khLVrn[_,hVNhGJ``<]"K^aek,e.9$1@NTk2t2lMoFQHmJp/YmK52>
+S1/s~>
+!m8N2p?ho\NrSh@!<;c\#eE^Pf%/9tf%P]3J_laM"JstOhPKf"$0(C8hVQOOKtcF;mJp8\mK7aW
+`aOA~>
+!rqu=p>u?QNrSh8!<;cT!jkS=rlkM`c-:giJ^p+;"JjSDeYMcd$/Xh$e^_W2K>#h/joA<Qjo`U&
+p8!3~>
+!h?&@p?hoYNrSh@!<;c\#53sIXOZ1irn_)GhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\Wk$['.hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEs.hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\Wk#U@$hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhYuXBmcNB58nt`X
+p$MfXp?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;c\#P*jBV9[ZGeq)P+g4S)ZhYuL=euhPXZHD>'mJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cTC[R*QUrCU/c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(heR6YPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1?Pc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(heQ0rFc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@
+p#Z6Pp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;`[#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r@.b$"B'lZ^#&GM!)iOY"#6UA
+.=_~>
+!m8N2p?ho\NrSh@!<;`[C@\fE1b:%+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbp?n<]W-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n&IS-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbp@OroY-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&X
+p?ho\p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<;`S"7EO*0nCd).=irG.0VG(K<2c:p#Z6Pp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;c\rq6H^k0:kr]n*kJ^&5PH`QdQ5p@dnS;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\#4h3QlJB\#J\$EDJ\(cj"N&=<lLOZ:!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cTrpFI^hSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJd@'mVS]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tIg\]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJd@^NhU]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tLed[(Wi[`STbF
+p>u?Qp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;`[CA.)hmdArohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\O@-6>.hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVMZ&hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\O@HQG/hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOk2,7WmdBfA
+mJp/YmK52>S1/s~>
+!m8N2p?ho\NrSh@!<;`["S2!KlK3ZSJ_kt7qVD88lLaKE<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;`SC@:6Pk2t4Ne_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j,@,BGje_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^\'ae_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j,@G]Pke_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^`O,hUUK5k2u+)
+joA<Qjo`U&p8!3~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@JPq%sJPt,up?i#CS>7Ta~>
+!liB.p?ho\NrSh@JQ78$JQ:?&p?i$2`l__?~>
+!quZ5p>u?QNrSh8JPq%sJPt,up>uJ%pA^Y5~>
+!i2>Hp?mq?JaS*WJaUDC"#6UA.=_~>
+!m8N2p?mq?JaS*WJaUDC"*r&/@=S~>
+!rqu=p?%A7J`_OGJ`ai3"3(<6Ujr~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@p?mK0JPq%sJPt0!p?i#CS>7Ta~>
+!liB.p?mK3JQ78$JQ:B'p?i$2`l__?~>
+!quZ5p?$p(JPq%sJPt0!p>uJ%pA^Y5~>
+!i2>Hp?mM3JcC<$JcFF'p?i#;Umrla~>
+!m8N2p?mM3JcC<$JcFF'p?i$.b/Rk?~>
+!rqu=p?$r+JcC<$JcFF'p>uIrs7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@p?ocjJaS*Wna?AL"4a2o;Z8s)3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3W25G
+;M1dqrV$-V]Cu-iZhF+\"$)mI.=_~>
+!liB.p?k09mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+o'Z):o'Z):o'Z("mXafrmK`=No'Xr&I8JTZ#>fiFddH\oo)%iDo'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)>mdff:mdff:mdg8C:%I`Cmdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+o'Z):o'Z):o'Z)BmK7mWb$ff~>
+!quZ5p?'3ZJ`_OGn`Kf<"O3`h8jV8n#!k708pdAYrU0RF]C,RYZgRPL"3pQ>S:C~>
+!i2>Hp$P!:me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6):
+p?qYBp?qYBp4;X_mdKR$p?n_:5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+3C,Yk3C,[$me6JE6h]sAme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6):p?qYBp?qYBpA+,Lp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qABme6)Bme6)Bp$Mo:Umrla~>
+!m8N2p$P!6mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff6
+o'Z):o'Z):nq$4[mdKQFo'W(G4<caI3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3;P`=
+SaQ(EmR-R5o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):mdff:mdff:mdg2A9ChNAmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff6o'Z):o'Z):o(DDQH-4-8J,~>
+!rqu=p#\F*k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBo
+mcNs"mcNs"mXaMOk3qF6mcL%e3<G`5meQ!4mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcN["k3hC"k3hC"q;t?<k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2u*omcNs"mcNs1jo`U&
+p8!3~>
+!h?&@p?qtSa8c,3JaS*Wna?GN"+*="3W;;j3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk5rnp1"Z\k7HhR11mf3!ss8DZgmf3!ks8DZbmK5J>Ua^f~>
+!liB.p?i%Rme6M#rrr8mmdff:JaS*Wna6JLmWHi<!d3r%qsFRWme6Lrrrr8mmdff:qsFRWme6Lj
+rrr8mmdff:p?i$2`l__?~>
+!quZ5p?)DCrUquGpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0d
+s8DZimXaMOk4.U6mJq>-3<2@u3<2AE3<VW.F7/Jnk5XlJp,E$Fs7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmpAb*brU0RFs6fjZ5QCHWpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0ds8DZime5cFc1_1-
+J,~>
+!i2>Hp$VkRr;Zfb.H^'\mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs7jok,G
+p?qX*mXafpmKT1A5ri\ek1Tb=k-Sk`5rkJ2mf3"Ys8VL?k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"qrS%Lp@dqJq<n:Vr;Zfb2s0PjmcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mec,Lme6ABp@[hU0r1<gJ,~>
+!m8N2p$VkNs7SJQqXWq6io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7W
+hW!DOk3hg.nq$4[mdKQDQ2WltBsQIhs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+qZ$EGZ>';#!1!BJs763`5QCTNlK7*gio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7WhW!DOk3hg.o(h_Ro)JDRs8)<Ok2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2P7Sini\Wmdff:p$Mp-b/Rk?~>
+!rqu=p#c;B#PRTcp?peoec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D,e_]0\
+eHFakmcNqgk(2[`joCYF3<Erse_0WteZ<Nb3<5<>k5XiSp?qtSmbZgNrn[Y*rn[Y*rn[Y*rn[Y*
+rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rndP&"Q&;/k3i'-s6^-cmf3"KhVQf^h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hYYh+hWF7gme,]E`W,Y-
+J,~>
+!h?&@p?i(WmdB62d/O18k2-(!rq:p2JaW'r"k>n)3McBIs8MEdk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5F`Ijp(8IUcC_,c26o3p?qA2p<*C:mcNC)k5P)OmKE7OmcO5[rrVWNhYlU9p@dnV
+3LlloJ,~>
+!liB.p$N%Dk2P\&s8W)p2"pe>qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+k2+\Gg>:iWmdbqsJaW'r!7(R+.%0Z&pAb!Oio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io^4!!p8p=r]C2'qX+RIk2P\&s8W)p3qiFDqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*qX+RIk2P\&s8W)p6MC9LqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*p?i$2`l__?~>
+!quZ5p>uACrn[_=pAb$`!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj["7G$r
+c2H2lmXaMOk4.R6c2K^,Pj\85s7Y.&"m2%05rlp]joFiKh?)j5s82Kimf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n`me6)*e]n'CrpK[G!:KjC!p94Vqt:$Xrq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6N`p?pefc2H2lme5cFc1_1-
+J,~>
+!i2>Hp?qtCrnc!$!p8@irSE+nJaW!p#Fn(GF6;oQp>#ZTmcNBghWEsA5s_%<mf2GKhT>d!k2+Ye
+hYHU>k5O5RrrV?>ec"@smK52>S1/s~>
+!m8N2p?hq;rRq8FrVnPIs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)Tc
+k17uZg&UDhmXafqmPgP!4Dj*?ip-7;pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LF
+g=G-7hVN675ahN;!8d\.!;?Bk2>[@Ls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)Tck17uZg&UF7mJu,Bg&UjFs#p5YqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$Egp?'rSrRq8:p$Mp-b/Rk?~>
+!rqu=p?);'"Rc!`pA`\:#O^Hnc.1(heUck6k3qFcPX.<EhVQfFmf2_Kme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)BmbZL=rRD!b3C/o,k5<a4me6\Ss3LBDmbZ45e]lXpq<%V*"Rc!`pA`2,
+#O^Hnc.1(heb%u+`W,Y-J,~>
+!h?&@p?i+@k2t4Np<WaCk1/#EhUUJ6mXafqmK7f.9!nT[!8cK1!q+pqroO<i8kOI-mKMJ0k1/>^
+ao;S-e^`g=e_^/j"lAD(e_^#9rs%W9e`P`=hY$:=3LlloJ,~>
+!liB.p?i+4g=k!+o$ICAp>46GhV-9/JaS*WnEquQ6qFK7hV-]Ws8)HcpA4LZqY'dZqY'd^pA4LZ
+pA4XZqY'dZqYKp^pA4LZqW?M[rn7IW847UtmKM%mg="RCb5V_?hU9j/g<SFKmKM%mg="RC_Z'l7
+hU9j/g<SFFmK7mWb$ff~>
+!quZ5p>uP'e^_phmeZq`pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAP!tp?pJUc.1@heaA"NJ`cLb
+"*6b#V#AgEpAb-c!:KaX!:KaX!:KaX!:KaX!:KgZ!oDJPrm_+P8jROqjos#[e]lA,qYpQhr;Qcj
+r;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;QcjrVm2tma]S,e^_ppmec,Mc.1@hc0kH.!;??j!;??j!;??j
+!;??j!;??j!;??j!;??j!;??j!;?<i$23f;c-=ehc.27Ujo`m%s."T~>
+!i2>Hp?ht+k5Nm2p<Wa=mf(`=hTa=-JaS*Wna?ET#"m.shUUKVg]%Q9e^`g=bt:l3qsFL0k5Nm2
+p<!=7mf(`=hTa=-qsFL0k5Nm2p;-b/mf(`=hTa=-p?i#;Umrla~>
+!m8N2p?i.)g="9pmeY?2#kmE+cI1Fdb2S!?JaW'r2c*1=b1bRtf(/k;s8)cls8)TlqZ$ElqYL6g
+s8)clqZ$ElqZ$Egs8)cls8)chhTjF#g<)r[;#BYb`nJkdddHtTrs8>\cHakl`ld<<mKU\bda$;/
+qSW==p?'ZGdb;^`iqDdBH-4-8J,~>
+!rqu=p>uChec*Mlk3hs:s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'(Ki
+pAaR;rl"ui]uAiZk(2[bk5S$X6,h+!`Qdi+p'0s8`PpBP`VrL,joN0Grl#*(me6ASpAb-c!rquo
+rq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6Nqp@eOShYtIre\/rYqrRpmec*Ml
+k3hs:s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp':Wk
+s7Z0dmb[r^"4b*(hY-(6`W,Y-J,~>
+!h?&@p?i+'hUTm$ma(n<ma]S4k/G$rJaS*Wna6N`;Hh?-rm_#Bg]%9Arm_/6c!""KqsFX,hUTm$
+m`GJ6ma]S4k/G$rqsFX,hUTm$m_So.ma]S4k/G$rp?i#CS>7Ta~>
+!liB.p?i1"g="!hlLt)'rsAPqim,Qlg:k;\JaS*Wna6]`:fYBdd`U#+qVD/Xp?'ZCdb;Q<:f[D\
+#JSp?`mX/GqT]$HqY&po`mWST^>f%X#JSp?`mX/GqSiI@qY&po`mWST^>ekS"+A23@=S~>
+!quZ5p>uOce]kePk5G!'s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKl
+p'9Hn^!5*7^#">&J`cLbr_b;\e]#MPk4\iKs7ZKds8VfmpAajds7ZKds7ZKmpAajdpAb0ds7ZKd
+s8VNDrl"og^&Cq,jor-Bc+VBarUqrFpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdrq6TR`P'OH[(Y>njor-Bc+VBarUr5NpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdrq6TR`P'OH[(Y>ijo`m%s."T~>
+!i2>Hp?hsghYtb#me6;Q!!)rs!!)fo!!)Kf!VYs\blch0^#">.JaW'rr`TK=hUTm$me$PX!<)ot
+!<)ot!;?Erk1.H$hS&nlqsFKlhYtb#me65OrrDKe!!)Ng!VYs\blch0^#&YS!OU__blR8+o)JRe
+jSo2[pAY0emf(H5hR'uQp?i#;Umrla~>
+!m8N2p?i0kf#kkPk486=q>^Nnq>^Njq>^Nbq?cldk/tQ`f!;mDJaS*Wna6]d?!4bicGIllp@\Ia
+!<)ot!<)ot!;QTop'B[#_Tp`D=^>2-mK^&Kb/2<`o(M\OrrDK`!!)Qc$23rPb/2<PZF\oimK^&K
+b/2<`o(M\OqZ,^R!!)ci$23rPb/2<PZF\odmK7aW`aOA~>
+!rqu=p>uOSc,IB0hYupDp?qqR!q,dMrq6Bnp?qqR!W_r^rq6Wcp?qVSp?qYBrq6E]p?qqR!Uf[[
+mK_U^]uA6l[+0`iJ`cLb#uXr)[*?S'`SU%^p&P-ip&Y3er;Zuos7Z-drq6Bm!;uNjs8M`lmKh[g
+]uA7';HcuqjoqR*`P&tArpBg\mf)n]me6)Jp'C*[!!)`dme6)Jp&a[Umf)ncme6)Bp&OOSmf)n]
+me6)Jp&XUTrU'pI]tMD0UpS\LjoqR*`P&tArpBg\mf)n]me6)Jp&XUTqZ$Warq6E]p?qqR!q,dM
+rq6E]p?qqR!q,dMrq6E]!:Kj["Rc!Op@eLR#N!/-`Qb3ceb8,-`W,Y-J,~>
+!h?&@p?i0ehTa$ik4\NHrrDcjrrMfnrVlol!<)otpAP!l!;??j!;??j!;?Bks7Q][e]#eiXM*bI
+mXafrmK@96C96:kblR8+pAY*mrr;uurr2rurr2rupAY0emf(H6hQ1I$CA[E(XPV4@e`QT!r;Qcj
+r;Qups8N'!s7ZBj!;??j!;??j!!)rs!;??j!;?Bks7Q][e]#eiXM*cnmK]iMc,J5qp@eFa!;??j
+#kn8u!<<)mrrE&u!;??j!;??j!;??j!;??j!quWorr2ulqu?]i#NjRUc/,P8k4\3F3LlloJ,~>
+!liB.p?k/Ad`T;HhX^72o(MYJo(MYJo(MVSo(MYJnc87So(MYJo(MVSo(MYJo(MYJo(MYJo(MYJ
+p@@e2b.c$HV7PN7mXafrmPe]cAZF>(_TM$3s8)cls8)cqqZ$BlqZ$Qq!;c`l!<;oq!<;oqs8)cl
+s8)cho&@g/b1<S(@:f?(7A\GT^<5='o(MYJo(MYJo(MYJo(MVS!;?!Wo(MYJo(MYJo(MYJo(MYJ
+!;?!Wo(MYJo(MYJo(MYJp@@e2b.c$HV7PO\mS0P+b.c$To()MFp@@qJp@@qJp@@nW!:ojSp&OgW
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@nWp@@qJp@@qJp@e(JhTERTd\XP3p?i$2`l__?~>
+!quZ5p>u^Xc,I'/eaDSnme6YJ!qu'UrpBgfme6YJ!W_Z^rpC'cme6&Kme6)BrpBj]me6YJ%JK5`
+p?qA!`O*V/UpT!0k(2[bk5JfpUs6ll^#&2Wrq6Hop@eOcp(7;upAY*mpAagds7Z-ds7Z0drq6^!
+p@dqBhS$VAc(t>JqrS6]c,I'/eaDSnme6YJ!qu'UrpC'cmJm7Tme6)BrpBj]me6YJ#km][md:)K
+me6YJ!qu'UrpC6hme6ABma]:``Qb3chYZFBUs6lc`RXD=p?qYRmK3+MpAXI]p&G*lmK3(^pAXI]
+p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p&OgcmLT$Zp?qABmdAWE[)L:c[,1N="3pQ>S:C~>
+!i2>Hp?j`,hSmIYk3hs:s7ZKds7ZKds7ZHms7ZKdrrE)ms7ZKds7ZHms7ZKds7ZKds7ZKds7ZKl
+p'C*Kc,IZYSA!d1mXafrmL3iOC8BD)^!5^5s8Vflrt4u)s7QEms7ZKm!!*'!!<<'!rr3)os8Vfl
+s8M]thT`aYeYHr$CA[E6SDM6(c0"HfpAajdpAajdpAajdpAb*l+TM08pAajdpAajdpAajdpAagd
+pAajdpAajdpAajdpAb-c#k$j"`Pp](^#&YS6(HfN`QdQ5p@eO[s7ZKds7ZKdrr<&ms7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7QHds7ZKds7ZKlp'C*Kc,IZYSA!eQmK52>S1/s~>
+!m8N2p?i-Md_``<hX:%,!!)rf!!)fb!!)KY#k$Qh^;A<`]&&#+JaW'r$#+6jS^PNh`np.XpAY-k
+pAY-mp&b<gp&Og[s6^0L`k'1<SS;qTqsFZRd_``<hX9t*rW)EX!!)NZ#k$Qh^;A<`]&*>P#*mWR
+^;f$to^`"^hXUXHp@8LWhT!:HdZqE#p?i$.b/Rk?~>
+!rqu=p>uRDc+UKte`QMl!!)rb!!)f^!!)KU#j0[N[(X_K[+0`iJ`cLb$Y!j[SB\aS^")Q=pAXIs
+p?qABmJm7\mdBcK!:KO\me-YKme6):pAXIgp?q)2e\/?'`LLCP@f,9lPg-nK^")99mf!4TmJm7V
+mKht*]sPJtPdK!<jp%'p]sPK'k4J*A!8d,D!;>gdk1./P^!2eKeb8,-`W,Y-J,~>
+!h?&@p?i*Ke]kePhXgF@!;uNj!<2]k!<2Zr!;?*dp&G*bp'9a)^!5)l^#jn6JaW'rrd-AahTa$a
+k3i9Cs7ZKds8Vfm!<;cms7ZHms7QHm!!)`mpAb0ds7ZKds7YmCc,IraPl?%,mKJj*c+VBYo(N(`
+!VQNlp&b<g!!*#l!s&#p!<2Zo!;6Bmrq6<lp@\aRc+VBPPeH5VmKJj*c+VBYoC`.aq"FXdrq6?m
+pAP'kpAG!kpAP'kp&G*cp'9a)^!5)l^#o%V"$)mI.=_~>
+!liB.p?i0Jd`/l<g?RtrmJm7bmJm7dmf!4cmKN[ZmJuYT!;>j\l3H%_]#N0\]&&#+JaW'r2gKOk
+Oj_+\`np"So(MYJo(MeJp&OgWp@e(N!;>s`p&G*`p@@qNo(MYJo(MM:hT!:HdZJftH2I"7Oj_7\
+`nK_Co^;_Z!U]sdmK3IW!!*#d!s%`h!<2Bg!:BgerpBadq!S1I#MR2/`mU!\hYZ^GOj_7\`nK_C
+p$Me[q!S(\rpBdemf!4cmem.cmf!4cmJm7]mf2PWg;^_DdZM,tp?i$2`l__?~>
+!quZ5p?!BR`P&Xle`Q#^k3hC"k3hC"k3h@3k3hC"joFQ3k5G?%k3h@3k3`6;!!)0Lk3hC"k3hC"
+mcNZ^]sPJtMmV>lk(2[bk5KE+Mp8rB^")9>mJm7amKN[ZmJuYT!;>j\jos;K[(X_Brc@u!7>o-u
+[(Y#Pk3hC"k3hC"k3hC"k3`3LjoFQ3k3`6;!!)0LjoFND!:K";!:Bgek3h@3k3hC"k3hC"mcNZ^
+]sPJtMmV@<jrKB!]sPK'k2u*omcNs"mcNs"mcFN3mcNs"mcNs"r;Zugk3`6;rW!#fk3i0J!TrhL
+!#P(cmJu\;mcNs"mcNs*k2t4-[(X_B[,1N="3pQ>S:C~>
+!i2>Hp?hs6ec*MfhYupmp?qYBp?qYBp?qVSp?qYBp&OgS!:KO\!:KO\p?hn\p&G*\p?qYBp?qYQ
+mK_mn]uAi\^#">.JaW'r$%%;WMq-(cc/.m_p&G*ip&Y6fpAP'bpAaOdhT`aYeVed,KDY';K@Tt?
+!8d_C0_Xr.me6)Bme6)BmJu\K!;>jSmJm7\!!)H\!!)Ee!;>g\me-YSme-YSme6)Bme6VI#Nj"=
+`SQ6\hYZ^AK@Tt?!8d_C3;2e6me6)Bme6)B!;>jSme6)Bme6)Bme-YSmJm7\mJu\K!!)H\me-YS
+mJm7\mJu\Kme6)Bme6VI#Nj"=`SQ6\hY-@>0r1<gJ,~>
+!m8N2p?i-=d_`T4g?/%m!!)r^&HM+]!:&hL!:&hLlKS?Ll2UhXl3QP+_RdV4Kt?,lmXafrmf%V=
+M9a,P`nKSLmJm7amK*CVmf!4Zmf2DQg;^_DcADOKqsFZBd_`T4g?/"l!s%WO!<)3_!"\>p!:&hL
+!9sOalKSB7l2^hK!!)cY#j0jX]#)mL]&*>P#)1LB]#*1`o]cDVo]cealKS?LlKSB7l2Uh_l3@=S
+l2UhLl2^PC#j0jX]#)mL]&*/K"*r&/@=S~>
+!rqu=p>u^/c+UKte_]HFk2-+"!oE(rroO7^k2-+"'EI:P!9WDD!8ci<k2$(<jo>D<k2-+"%Gp7(
+hWE\F]sPJtHaM=Sk(2[bjp?*UH\9;N[(X`@roO4KqrRkYqrRq[k2uXC!TrhIjoFiKk5X9Dc+U3l
+`Ii5YHi)q4Hd072^")!%hWE\ojoXE%hYuXUh>lEp!9W/#h>dQ<!!(m<!!(jU!9WDDhW=h;joPPF
+hYuXHhWE\Ok2+Y%[(X_2[+5'9$@C%2[(Y#Hk2,7WroO:=k2-+"!W_B>roO:=k2-+"%c6=Jk2lXD
+k2$+#jo>D<roOIdk2$(<k2$*proOaJk2,7_hWE\F]sPJtHaM>sjo`U&p8!3~>
+!h?&@p?i0<e]kePhX9P(mJuDImJuDG!"A8q!:K";!:K7Tk3`6KmJm7bmJuDJmKr%DhT`aYeUtQt
+JaS*Wna6^JMj/kNc,IZak5P&Smec\X!;lHp!;?*dp&OgSqt:$Xrq6]ek2+(rc/+);Mj4,,#D:RO
+^!5F%k5=WIk5=WOk3`6;mJm7dmM#Zhk3`6;mJuD;mJu\C!:K7Tmd:)QmJuDJmKr%DhT`aYeUtQt
+qsF]Ae]kePhX9P(mJuDImK)GMrU'[Jr9adOmd:)CmK!7S!s%cO!<)?c!<2Bg!9W\LrpBdKqsFdQ
+mbZ4%c..H[k4\3F3LlloJ,~>
+!liB.p?iTFd`/l<f&G]Oio]7_io]7_io]7s!$pP(!9W;'!9W8@ioU7'ioU7'io]7_io]7_k2PCO
+`k'1<J\']hmXafrmf&%tIF?!D_V4#;lL*s*lL+**mJu\?mdBB.!:K+PmJu\?mcs6.lL*s*lL*Zk
+g;:G<dXD+OqsHn(d`/l<f&G]Oio]7_io]7_io]7_!9W8@!9W;'!9W;'!9W8@io]5#ioU7'iW/!#
+!9W;'io]7_io]C_imu,\`mTFLhYZ_8J^VQL`n'//k2PO_k2PO_k2PO_!93/#k2PO_k2PO_k2HC#
+joFQ'joFQ'!93/#jo>D@k2HC#joFQ'k2PO_k2POcio8P/]#N0L]&*/K"+A23@=S~>
+!quZ5p>uU,c+UKtc/."DhYI3Rh>dQTh?Eu:h>lEh!<1gT!;51Rc+UKt`I"uKJ`_OGn`C.9K7eNq
+]sPK'ebA2+!;km^!9WDDjoG):$Js=`]sPJtH]*N/qrS-1c+UKtc/."Ch?3i8h>dQTh>dQTh?*c7
+h>mQ3#lri=!8cQ4hVJ8*h?V<=[(XG*[,1]B#CF_/[(X`@eb.c!!;,+M!8cQ4rn[_WhVJ82hZ!TT
+h?*c7h>m6*#L0rh]u>?*hY-(6c1_1-J,~>
+!i2>Hp?i**hSm1IhYuXMmcNs"mcNs"mcNp;mcNs"mJu\P!#F_b!:JtLk3h@3k3hC"k3hC"k2u*o
+hYtIreT8F\JaS*Wna7olS<SBNc+VBYk2u*omcNs"k3h@3k3hBomcFN3mJuAL!:K";k2u*omcNs:
+jp9hg^!5)SPan!8mKI[g`P'7IroORUk3hC"k3hC"k3i*H,j+OW!9W_3!9W\LmcNp;mcFN3mJm7L
+!9W_3mcNs"mcN["k2-*V"4_J+hYZ^EF5FmL`SUUV(%15Pk3hC"k3hC"!:K";k3hC"k3hC1!"JAY
+!9W_3!9W\LmcNs"qZ%/pjoFQ3k3hC"k3hBomcNC*`<4Y3^#&JN"#6UA.=_~>
+!m8N2p?i--d_`T4f&$&Y!!)rV!<D-V!<;$\!92u<ro*nXp>QA7f###8dWN.XJaS*Wna?C="a/,-
+[_gVhiW&uUiW]DBiW.s<!;>CWhW!,'[_g=4rfR*G#'JA2]#*%To]#`Jro*nXro+"[io0t;iX#VE
+iW.ut!!)!Yp>QA7f###8dWN.XqsFZ2d_`T4f&$&Y!!)cQr;clW!!*#X!s%??!<(pS!<;$Y!;>CX
+hU]QT_U<S<hY-@>H-4-8J,~>
+!rqu=p?!</c*Xjkc.1\$hUUK5hUUK5hUUH_hUUK5h>lF0!$0VH!8c6+e_\gVe_\j5e_\j5e^`O,
+c+UKkc"aW9J`_OGn`Kh/"`qYrXM)mXh>l+*h@\;phUMV_hUUK>eH"I_!8[\Urn[b-hVQf^hZ)+1
+hT`a8]u>'lMu2WMC<a,m^!5*ae_\j5e_\j5e_\j5qZ&.shUMVVhUMVVh>lE_h>lE_!7fp+!7_)"
+hUUK5hUUK5e_\j$]sP/kC:)OgjrS9^['[Nke_\j5e_\j5e_\j5e_U;_e_\j5e_\j5eboIWhUMVV
+hUMVVh>lE_hUVK'(>dRAe_\j5e_\j5e^`O,c+UKkc"aW9p>uIrs7W7=~>
+!h?&@p?i**e]kePhXfk0!;ts]!9O7]qrRt\k2l[Cjo>DSjp0bf^!5)K^#jn6JaW'rrhKR0hYtJA
+hWF7gmcNs"mdB6*!!)0LmcFKLmcFN;jo>DLk3h["mcNs"mcNZgrl"opCAt%+mKI[^c+VBYoB$#Q
+rT4([roO1\roO:_k2l[CjoYVGjoGDCrW)WR#N!_=c.-mKk54QMF4JOKc//'SrrDlW!!*#\!s%KG
+!<2*_!9WDDrT=+[qrRkYp#ZM9c+VBPF1p`0mK5J>Ua^f~>
+!liB.p?k.^d`/l8f&#9ChW!DOhW!DOhW!AlhW!DOh>lC4!92kphW!AlhVnOphVnOphW!DOhW!DO
+iniPC_Rdb8D7\STmXafrmf&a]C!sl0_UdT<ir9#Wir9#YiWK8@iW&uQir@j=f###8dV8]OqsH(R
+d`/l8f&#9ChW!DOhW!DOhW!AlhW!DO!92kp!92kp!92i8hW!AlhVnOphW"M7'B7m.hW!DOhW!PO
+hU]QT`mS_8hYZ_8D:6G8_UdT#ini\Oini\Oini\O!!)$8ini\Oina[lina[liW.upiW.up!8c_l
+iW&u8ini\OiW.upini\Oini\ShVQi#]#N08]&*/K"+A23@=S~>
+!quZ5p?"SS`P&Xlc/."-e_\j5e_\j5e_\gVe_\j5eH","!8c8_e_\gVe_U;_e_U;_e_\j5e_\j5
+hUUK-]r\olC:)iKk(2[bjpR]DS79aV[(X`7hUVV^(tIL"e_U9+e_]05!!(m+!8c6+!8c8_hUVV^
+!S-'+eH`dp^!1#VPaqX5/o&A=[(X`@e_\j5e_\j5e_\j5eH".Ve_U;_e_U;_e_U;_eH".VeH".V
+!8c8_rW!Vge_\j5e_\j5hUUK-]r\olC:)jpk"TU0]sPJthUUK5hUUK5hUUK5hUMT+hUUK5hUUK5
+!7frV!7fp+hUUH_hUMVVhUUH_!7frVhUUH_hUUK5hUUK5hVQf>c+U3lc"aWBp>uJ%pA^Y5~>
+!i2>Hp?hrjec*PfhDjZSk2,7Wk2,7Wk2,5#k2,7WjoFQ#!8ckpk2,5#k2$*pjo>D<k2,7Wk2,7W
+hWE\O`P'7I@_LWLmXafrmL$&&XCB`)]uAOahYuX>hWEtWroOdmk2tO_!9W/#!8cl#!!)0DhYuXH
+hWEtWk2+(jc.-:)[&j/m!FjUY`W+dYk2,7Wk2,7Wk2,7WjoFQ#k2$(<k2$*pjo>D<joFQ#!!)0<
+!8ckp!!)0<k2,7Wk2,7WhWE\O`P'7I@_LXqmK$eIrl+oo7crRihWE\WhWE\WhWEYp!9W/#h>lEp
+!9W/#!9W,<hWEYphW=e<hWE\W!9W/#hWEYphWE\WhWE\WhVRDOhSm1IhI=1Tp?i#;Umrla~>
+!m8N2p?i,nd_`T0f%U,[2;6p@hV-i?hV-fdhV-i?h>lEd!8?;`hV-fdhV%t`h>dQ0hV-i?hV-i?
+hVQu;^:M20@Ck<HmXafrmf'3j@Eu`u_U@03h>dQSh>dQTh>dQThZ!TNhZ):5d_`H0c=-^PqsFYs
+d_`T0f%U,[45/QFhV-i?hV-fdhV-i?!!(m0!8?90!8?90hV%r0hV%t`hV%r0hV-i?hV-i?hV-iC
+g=F!L_U;l(hYZ^F@FE$(^=M$;hF$#Rg>:Q?g>:Q?g&M-0g>:N`g>2hdg>2hdg&Tj`g&Tj`!!(a0
+g>2hdg>:Q?g&Tj`g>:Q?g>:Q?hV-Pp]#)m(]&*/K"*r&/@=S~>
+!rqu=p>uQ_c+UKkc-?7<29j[re]lXhe]lVEe]lXheH".E!6s'=e]lVEe]e*=eGoToe]lXhe]lXh
+e^_ph['[Nk>-uh2k(2[bk5M.[@`?$^^!66#!!)uJ!!*#K!!*#KrrDiE#L1fD]r\od@fE2#jp##6
+]sP/kc2Q6Tc.1(hc.1(hc.)gEc.1&=!7f<oc.)doc.)gEbl@aoblH#=bl@aoc.1(hc.1(hc.1@h
+c*Xjkc!%L)qrS)dc+UKkc-?7<6d=0+e]lXhe]lXh!!(Qoe]e*=eH".EeH".E!6s'=!6s$o!6s'=
+eH".Ee]lXh!6s'=e]lXhe]lXpc-<W&^!0`feb8,-`W,Y-J,~>
+!h?&@p?ir1e]kePhWE\WhWE\WhWE\WhWEYphWE\Wh>lEphYdEWk2$*pk5>8ohWE\WhWE\WhWEtW
+k2+@rc.-::k(2rOmd]]O`P'5ohTa$YhVS7o!8dV8!T)u;!!MH@k2l[CjoO<=r8n"9rT=.:s2>/d
+hHIn3`V]'C@b&`:c/.U>k2,7Wk2,7Wk2,5#!8ckpk2$*pk5>8]hWE\n!$14YjoFQ#jo>D<k2,7W
+k2,7Wk2tO_hT`aYeRH5SqsG2.e]kePhWE\WhWE\WhWE\WhWE\WhY[?ThWE\l!!q]ek2,5#k2,8!
+!!1s=r;[VijoFQ#k2,7Wk2,7_hWE\>^!5):^#o%V"$)mI.=_~>
+!liB.p?ir,d`/l8db<F3g>:Q?g>:Q?g>:N`g>:Q?g&Tj`gAM!ShV%t`hYdEgg>:Q?g>:Q?g>:]?
+g=!jL`mS/(hLY*Gmd]`E\e8/s`kK=@g>:Q?g>:Q?hV-i?hYdEmhV-i?!8cGdg&Tj`hV-i?hV-iC
+g=F-T`n";l])1n8?.-a(_U@/lhV-i?hV-i?hV-fd!8?;`hV%t`hYdEUg>:Q^!$0qMh>lEdh>dQ0
+hV-i?hV-i?hVQu?d_`T8dTsH@qsG2)d`/l8db<F3g>:Q?g>:Q?g>:Q?gACpPg>:Q\!!qE]hV-fd
+hV-ib!!1g1r;[Veh>lEdhV-i?hV-iCg=jul]#N0(]&*/K"+A23@=S~>
+!quZ5p>uN^c+UKtc1BHc!;t@I!<1OI!<:RN!7fWu!;+eHc+UKtc!%L2J`_OGn`KhX"]EUY[(X`V
+eboLHeGoUJeGoUCeHO42[(X^^rj;Rb"^90a[(X`Vec,XIeH,a$eboLIeboLIeGoUKec,XAeHa@4
+[(X^f[,1]B"^90a[(X`SebfFHeb]=IeH#U!!!*#Kr;clJr;clJ!!)]B#L0rh^!0`fhY-(6c1_1-
+J,~>
+!i2>Hp?k.ChTa$YhVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7Wk2,7Wk2,7W
+hWE\O`Pp*Y;SCq<mXafrmPi,0`DYRC`QcrqhWE\WhWE\Ok2,7Wk2+tWhWE\WhVRDOk2,7WhWE\W
+hWE\Ok1._qe_X3Cc,KSJ78i!e`Pp]jk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7WjoFQ#k2,7W
+k2,7W!8ckpk2,7Wk2,7WhWE\O`Pp*Y;SCramS-U9c,IZYhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOhSmIYhGV&Dp?i#;Umrla~>
+!m8N2p?i)af#GG@dbrgZ!:ebJf##/@elB<<JaS*Wna6\"`kkR'b.bmDgY)q]`kKUH:r:5hqsFVf
+f#GG@dd#Nd!;kIM!;G1I!;"nLf##/@elB<<qsFVff#GG@d_XWBf##/@elB<<p?i$.b/Rk?~>
+!rqu=p?"S;c+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]e*=e]lXhe]lXhe]lXh
+c.1(`]sPJt;RFu*k(2[bk5N%K9$P>^^!5*Pe]lXhe]l@hc.1(hc-=e`e]lXhc.1(hc.1(`e]lXh
+e]l@hc+UL'bt@uKqrU=Fc+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXh!6s'=e]lVEe]lXhe]lXh
+e]e*=e]lXhe]lXhe]l@hc-<r/^!0H^ebeK';U)n^^!4gPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(`e]l@P[(X^^[+4m4"3(<6Ujr~>
+!h?&@p?i)^hUTTiec+\;hWE\WhWE\WhWFS5,NdkFhWE\WhWE\W!9W/#hWE\WhWE\WhWEtWk2+A%
+e_X3;k(2rOmd]`FeI^S0hUTlqhVRDOk2,7Wk2tOp!#j_Vk2,7Wk2,7_hWE\WhWEtWhTa<qk"=1S
+hYZ^E;VosCc.2gU$/Xh$k2,7Wk2,7q!%I%1k2,7Wk2$*pk2,7Wk2,7WjoFQ#k2,7Wk2,7Wk2tO_
+hTa$ihGV&LqsFVchUTTiec+\;hWE\WhWE\WhWFP40](sKk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7_hWE\>`RWgC^#o%V"$)mI.=_~>
+!liB.p?iPef$;.Pdb`^7g>:Q?g>:Q?g>;T),Mq/2g>:Q?g>:Q?!8cGdg>:Q?g>:Q?g>:]?hU]]`
+cIP\#hLY*Gmd]]Xda$93g<R^Xf%T!7hV-i?hVQu\!#jSJhV-i?hV-iCg>:Q?g>:]?f#G_Tg.9Z;
+deiGF9\.M+`mW_thV-i?hV-i?hV-i]!%Hb)hV-i?hV%t`hV-i?hV-i?h>lEdhV-i?hV-i?hVQuC
+f#GSPekE[3qsG(jf$;.Pdb`^7g>:Q?g>:Q?g>;Q(0\YC;hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-iCg>:E#_Tp_+]&*/K"+A23@=S~>
+!quZ5p>uNNc,IB0c1KQ]!;=qC!:eSEc+UL'bt>A"J`_OGn`C/&`Q^^!`P&t0c1oi`!:JD;]`lC*
+6-[BnqrS&Sc,IB0c1KQ]!!1UMqpbZHpXK6Do@4)j]sPc'9!mIPjonB%`P&t0o[W[9f[U5O]sPc'
+9!mIKjo`m%s."T~>
+!i2>Hp?i5QhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9k5='9k5='9k5F-Ck2+t>c.1Z:^#">.
+JaW'rrn[fVc/-^iec">)k54!8k54!8k54!8k54!8k5F-@k2+Y5hT\sthYZ^I6/L/:`STJ6hWFgo
+!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X7:$0L+$c-=eq6+u.PmKl29e]l(ihWE\Wrn[Y;
+r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9qq_YAhVQN%e_WU*hY-@>0r1<gJ,~>
+!m8N2p?i/Rf$;:Pdb<R,g'QWif#l"Xg-iO/JaS*Wna?G2#1cVnf#l"Xh:hnc#hI;Df#gh?g=lGl
+#=R.g`kp0XhTaa\hV-Q'`m3:+]&*>P#=R.g`kp0XhSn1ThV-Q'`m3:+]&*/K"*r&/@=S~>
+!rqu=p?"S*c,IB0c-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+c.1(`]tMD86+#0nk(2[bjos#[bt>t"rl+o^/Ci"qc.1(`e]lXhe]l@hc.1(hc-=e`e]lXhc.1(h
+c.1(he]l(Pc,E<"e]n!R77#2;]tM\8e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhc.1(`]tMD86+#2>k"S.d`P&t0c.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc-=e`c+Ug0eNpRmp>uIrs7W7=~>
+!h?&@p?i/hc/-^qe_]0\joF99joF99joF99joF99joF99joF99joF98jp0bne_\PK^#jn6JaW'r
+$23fTF0sf\c.1\MjoF98joF98joF98joF98joF9;jpLP=k1/>FZubs/pA=7_>0YpKe^`O5r8n"9
+r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9qrS.?e^`O$;SD5imKZq?hTaU$hVS1m!8dY9!8dY9
+!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dP6#N""]hT\s3k4\3F3LlloJ,~>
+!liB.p?j_:b1=_Xdb<F3g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q_
+h?`,pcHb"`9Y0)3mXafrmPjFnl><iXf#lFlhV-i?hV-iCg>:Q?g>:]?hV-i?hVQuCg>:Q?hV-i?
+hV-iGini,7f!9/Xk3Dj33E=5Qb0&/dg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q_h?`,pcHb"`9Y0*XmQjjqf#l.`g=kE;hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?rn[q?g<S!pb"TD'p?i$2`l__?~>
+!quZ5p>uNV`QcB@c-XuHhTa<ac,E;^hLXg?k4%L=hWARSc-=5Pc/."Nh>l+*blb%^k2,ss"]E=a
+`Pp*EeHk$Vc,IrH9!mIPjonZ%c,IZH_USqKc-=5P`CdMop>uJ%pA^Y5~>
+!i2>Hp?i0,XPVgae_]0\joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF99joOo4
+rn[aY@_LoTmXafrmf*4f`DY7bh>m!CjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjpLP=k3hs2
+k2t2l`W#o7mK[g7hVQf5hVS1m!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!Uf+Lh?0ig^#o4[#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX<mcON*"0>tFk4\3F0r1<gJ,~>
+!m8N2p?i0*WnPnHcIU_KhDEsCg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+io9+Wf$`9T?+SmDmXafrmPjk9qS#YKg=F^#ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\SmcrZcdSR[SqY'gS#B?ctda$.hgA]qig>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?io9+Wf$`9T?+SnimK[a3g="9lf%U,[6JC;MhV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hW!PWhU^-/Y$JWqp?i$.b/Rk?~>
+!rqu=p>uU$Ut*`/`QcZWec+D1e]l@hUft.^J`_OGn`KiE"11\>ec*fChUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK>k2t4Nbt>ABpA<tWF/7@2`Pp*HcIMpN#M%)DeYHBUhYZF?F/7@2
+`Pp*H`mt(F#M%)DeYHBUhY-(6`W,Y-J,~>
+!h?&@p?i!q;U,3t!nH/aeE.)*p?q)*eP_=EhLY*Gmd]]FpAY'oPY/%-gti7tp@d@M8sK>T!;?<X
+!khLVrn[_,hVQQ?$1@NTk2t2lMoFQMmK1("c2QQ$e_]0&jpCJLmcNZ^;N&NNp?i#CS>7Ta~>
+!liB.p?i3t9Zkr;daH_#eD:MkmcNB_c:ir+hLY*Gmd]]Fo)AYBO[Q%kf%S^/f%S^/f%S^/f%S^/
+f%S^/f%S^/f%S^/f%S^/f%S^/f&#iceuhQ+rr2uhqsFa$9Zkr;daH_#cJAlemcNB_c:ir+hYZ^H
+\kL8tf$`!tg;_tUipPschTefK^>ASO"+A23@=S~>
+!quZ5p>uF`9#^eS!l`F/eC=l^k2+Y=`CbcreUck6k4.R6mf*5>Ma<lPc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1tEc(msirr2udqrRse9#^eS!l`F/cIE6Xk2+Y=`CbcrebeJ1
+ZqA=:blYl/c,S9?hWE\Fe\t.5^")i="3pQ>S:C~>
+!i2>Hp?i.YMb:)$hWFgo.H]LLhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\o
+jp1>:hR#mi[*=0iJaW$q!;?Bk/^8W.0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+
+0ek+36$(<LrrDcimKWBC9!$S"k5O3jk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7WroOIRk2*I;C:)7^mKWBC9!$S"k5O3rk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WroOIRk2*I;C:)7YmK52>S1/s~>
+!m8N2p?i1VNC9Vgf%S^)g&U"/iWdu:885BPk(2rOmd]]Go(r@c/]Mcm/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1`2#4E8C?rrMueqsF^[NC9Vgf%S^#g&U"/iWdu:885BPk54QO
+nr6&6cIU_#`nCFLro+.5Y"394b3&Ec"*r&/@=S~>
+!rqu=p?"1!Mb9eac.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1)<
+ec4J0c(ms@XMobQJ`cIa!Uf[\rrTlT3S>h_3HMn5rrMi]qrTp,Mb9eac.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@qW:*3Mb9eac.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8n
+h?D0"8n+m@p#Z@qs7W7=~>
+!h?&@p$N%X]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=@"s"OXS
+K=&>KJaS*Wn*U2Lc2Re;q<eI\]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=F$s"OXSK=&>Kq<eI\]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=F$s"OXSK=&>Kp$MoBS>7Ta~>
+!liB.p$P$7[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbp
+/1<&+<J@`mg?O7WJaW$q!V6*5rrMueq<gZA[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&XqX.&J[Uh9H-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&Xp?i$2
+`l__?~>
+!quZ5p#ZAEZskc7.0VG(K<2c:J`_OGn)aZ=p<Wa>p?qb="7EO*0uk^H0iEY*^")r@"7EO*0u#.@
+0iEY*^")f<"3pQ>S:C~>
+!i2>Hp?qqR"7G<r`Qc(!`QdQ5p4;X_md]`Ep<Wd<pA=:Wp&jaFc,I`:"NAXJme6PGrq6H^k0:l[
+]`c=!k3hs:mK52>S1/s~>
+!m8N2p?i.UmdfZ"b/2E7"N&=<lLKMoJaW'r"7kmNqU,<FqXX(FqsF[ZmdfZ"b/231"N&=<lLOi?
+#4h3QlJB\#^UaQbb22FSp?i$.b/Rk?~>
+!rqu=p?)AB4QbM>]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd
+[(Wi[[(XH8k3df_J`cLbrpBd[dJj4?rpK[GrpE,8hSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd[(Wi[[(XH8k3i-/rpED@hSm18]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd[(Wi[[(XH8k3hs*
+"3(<6Ujr~>
+!h?&@p$P!:me6):hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\O
+k2,7Wk2,Oop4;X_mdKQGp?qYJe,TIA!Uf[WmR-^9p?qA*k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WhWE\WhWE\_me6JE9D7fImdArohWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Ok2,7Wk2,Oop@[hU
+3LlloJ,~>
+!liB.p$MtRmdBB&bME9^l@JASmdBKHo'Z)>qYJhDs8)cd!UfOSmKE+KmcrrRh>ud(q!J:UmdBB&
+^"rePlLaKHIE'E<J,~>
+!quZ5p#\F*k3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,
+hUUK5hUUcNmXaMOk3qF9mcNs*p@d,<s7ZK\!TrhGk!SS!mcNZ^hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5e_\j5e_\j=k3i'-9CCs1k2t4Ne_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,hUUK5hUUcN
+me,]Ec1_1-J,~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+"JhPs@VYmOrFu=Arb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+qe?+?rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;ICCAqZFC1=!/0n9~>
+!QrFYV1GXtWe%1$Wm7XAV#nfZ@=S~>
+"98)gmf)n[mXb(_p4;pgp<*(4me6ASp8!3~>
+!M#taF8]hRF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnV
+F)#H2rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrG):?!h?&8J,~>
+!QN:\Xok],WiCQOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)Wii@OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)-EaAOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA%J$,fSWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)Wdh1OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,Vo5WiiA)WiiA)WiiA%rM9S8b$ff~>
+!quZ^rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6H^p@dqRp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p'U6]me6)Bme6ASS:C~>
+"f.Z'@VTZVEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Es$/uF)(\q!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLSs(_OB!i2>8J,~>
+"Nn`\V5f*LJZaR,JZd+ts/Q'p!m8MkJ,~>
+!<7WDJbFZgJbHqR"7H3_Ujr~>
+$(Reh>$>BEC1:Y%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peIqiG-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@O>i!C1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:pe@Xi-%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1;[-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT?cC1:peC1:peC1:peC1:XU>+DB;J,~>
+$-(,YTqS<ZWhlPAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lJ#]?FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV'`4=Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lV15MAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhk3FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5g@*Whl_lWhl_lWhl_lWhlD[TuP5`J,~>
+$24Dep?qYBp?q?up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBJ+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmO%Yqp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBmXOrup?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?mG(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6&^p?qYBp?qYBp?qYBp?qYBp@eNVJ,~>
+"/MGb;Z0f!@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO5
+@TlrEr`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2
+r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2
+r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2
+r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2
+r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`TS:>%1Z=;P]g;J,~>
+!QrF\SUmJcTn/ngTuiu4V4F<Nb/Rk?~>
+#QOMkme6)BmeuhZmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mec\Xmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n`me6)Kp8!3~>
+!M#tb8d&$a;G'Q2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8g[G.;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ8q0`2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G)F:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA7j;G'hZ;G'hZ;G'hZ;G-pd!h?&8J,~>
+"NJTLR?`>kJXM(WJXOQH"eD'P`l__?~>
+!VZQmmJutZmJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[s7QKnS:C~>
+$)F)eS>;[NS>;s1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NJ"3=)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUaDV-S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NUjno1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>:Y)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"4oS>;[NS>;[NS>;[NS>;[NS>;Z(J,~>
+$-L91`lc<D`lcGR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<DJ&]XNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDasP-N`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<Db(%FR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`l`eNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VR;`lc<D`lc<D`lc<D`lc<D`lc;0J,~>
+$30`!pAajdpAb/BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds!II>pAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajds*sbBpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpA]X9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZI+pAajdpAajdpAajdpAajdpAai^J,~>
+JLQ.!JLQ.!]IA@~>
+JRO+<JRO+<]O?<~>
+$(Rf]Un"6NUn!s)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NJ#&U1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS0k&%Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NS:@?)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUmuq1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;YgUn"6NUn"6NUn"6NUn"6NUn"6NJ,~>
+%%EndData
+showpage
+%%Trailer
+end
+%%EOF
diff --git a/doc/kmouth/kmouthcpref.png b/doc/kmouth/kmouthcpref.png
new file mode 100644
index 0000000..75bbb8b
--- /dev/null
+++ b/doc/kmouth/kmouthcpref.png
Binary files differ
diff --git a/doc/kmouth/kmouthctts.eps b/doc/kmouth/kmouthctts.eps
new file mode 100644
index 0000000..726dfc4
--- /dev/null
+++ b/doc/kmouth/kmouthctts.eps
@@ -0,0 +1,2856 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: GIMP PostScript file plugin V 1.15 by Peter Kirchgessner
+%%Title: /local/src/kde32/kdeaccessibility/doc/kmouth/kmouthctts.eps
+%%CreationDate: Sun May 30 14:52:20 2004
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%Pages: 1
+%%BoundingBox: 14 14 596 357
+%%EndComments
+%%BeginProlog
+% Use own dictionary to avoid conflicts
+10 dict begin
+%%EndProlog
+%%Page: 1 1
+% Translate for offset
+14.173228 14.173228 translate
+% Translate to begin of first scanline
+0.000000 342.077918 translate
+581.132369 -342.077918 scale
+% Image geometry
+581 342 8
+% Transformation matrix
+[ 581 0 0 342 0 0 ]
+% Strings to hold RGB-samples per scanline
+/rstr 581 string def
+/gstr 581 string def
+/bstr 581 string def
+{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
+true 3
+%%BeginData: 178625 ASCII Bytes
+colorimage
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+g]%?3[%r82QAYj0XMsmas+14"s*t~>
+g]%NDd`T;<]"Yn.]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"YbiBtD$i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%qcJJDKs+14"s*t~>
+f`)*Js7ZKmJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds(;!)pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+p4<6ps3^js~>
+h>[fLUk=SXMh?q?K7Af3Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh>c&K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?Mp6hQJcF:#J,~>
+h>[NHb(7-c\cKP)JcC<$ec1.~>
+g])iuO7n/)JcF7"J,~>
+hZ!r-Mh?q?Mh?q?Mi3(;Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q(K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YAXmXbChs4@:$~>
+hZ!W5^4EkT\cKtEJcC<$fDg@~>
+h#@EKs8M]os7Z0drq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6En
+pAb-c!WVkEs+14#s*t~>
+q>UNQ[&!)I"-iNZ]n(fnK*.&"s3:P$!/#i\JW&iP".Z13pA"Z<~>
+q>Vc+d`T;<]"Yni^:M%i^:M%i^:M%i^:M2Ts44ci]!f2Y]!f2Y[XYls]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!cUi[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^ro]pAa-`\pqH*^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:Jg.]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Y`p^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i`ld<7q#>j~>
+pAYj#s7ZKmpAajdpAajdpAajdpAaj[rr7QCM>$rKrUta@pAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAai9s7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd(]X4/pAajd
+pAajdpAajdpAajdpAajdp@eN:~>
+qu7W'Uk=SXMh?q?K8YA?K8YA?K8YA?K8YA?ec4KWK8>-]SH&V=P`(0PK8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?ItNZ3Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?M]RM/
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?`W#l;^&@t]~>
+qu6]fb3QVL^?5I\]!f2Y]!f2Y]!f2]J$uqs]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y\oY<k[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roes8TgE]"Wa,J\('V!P[FirrCdOs*t~>
+q>]aRrr<#l!<<&l!<<&l"98)gs8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8;Qjs8M]ms7ZHlrq6?lJbFZgkP"]NJ,~>
+r;Rb]Mh?q?Mh?q?Mi34GK8YA?K8YA?K8YA?MuWg8JU<0!"jR(lH\6s#Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?IuAr;K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K--#(Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mkp(Hs-3N_J,~>
+r;QfS^?W9?^An5IZF7'IZF7'IZF7'EJ$uYkZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZ?*I[[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?Iir@l@]!d1$J\(!T"NpH<s2+d8J,~>
+qYpTis8M]os7Z0drq6?lrq6?lrq6?lrq?BlJbFilrr3)gp@eOcp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lpAY'lpAY)B~>
+rVlr4K7!QL"+,[%hZ!3Lc(t>k!.4Wr"FIi^eT:_:!-A-d!-A$a!-A-d!-A-d!-A-d&9E2NXJBT?
+HZOO\@VVF7K6.$=!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-ds8W+G!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-ds8W+G!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A'b!-A-d"`o$Ks5n\,K)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK*-IQXPWsM!R7G>K)g8tK+rZbK?a,ipAajdpAajdpAaj2
+K7eOMK+?0"s7ZKds7ZKds7ZKdc2N>"Mt[2N9)npA~>
+rVm5U]!f2Y[^roYcKbE&%c5LB[^roY[^roY[atK@jK\nJ!#/+`rNZQ_9G@Id]s@\<]<_J:^Tr@'
+s73>$]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f1c[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^scLrq8A/
+cFUHq[^roY[^rp(pA4LZpA4LZpA4LZp>3Bh[^roYhY-g>qY'dZqY'dZqY&dW[^s'Ds8SAas*t~>
+r;ZTdqZ$<`rr;'Q"B#4:C;p/F"N>*m!)gN(s8T_)s8Th,s8N)eJbGT,qZ$<`o)JU\o)J[^rr3&f
+s8RT~>
+rr3GXK6r5tK7eNHc0kW*mf)>W`M@j5H\6ZtH\9TCUucY.;ZG#As5p+\>,:Tds3:R9q/cN7mW8C-
+!d"DAj)b8#!s!EBs5S2#s8I*>s8R0>s8I*=s6k%/rrW7Bs8TrW!Ug!eH[gZpK6r5tK6r5tK6r5t
+K6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5t
+K6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6q6`H\6Zt
+H\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6Zt
+H\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH_epSs7Ym[jq#G,H\6ZtH\6Ztk5Y/Tp@eIQ
+r8nB6K7eN'HfkA%s7Z0bmel2RH\6ZtPlLcs3WFU~>
+rr2u\qR-RIhX:72mf)JPg;`rs+6*=CZECL9ZECL9ZECL9Y-P49Y-P49Y-P49Y-P49Fo24A&7Ju]
+qu@"FY-P49Y-P49rVmM5ZECL9ZECL9ZECL9ZECL9ZEF3,9s4NrZECL9ZECL9ZECL9ZECL9ZECL9
+ZECL9ZECL9ZEF6-!3ZA%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZEF6-ZECM5s/r[,rrTL/
+ZMsl-ZECL9ZECL9ZECL9ZECL9ZEF6-!3ZA%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9
+ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECM(s0Aq][[so2`np.[o'ZMB!SYQh[LVTrpAb!_
+o()5:lK[NslMJ""lLsrOqY'LNmdBB*k3D71[KXPJs43&,J,~>
+rVuWc!<<#k!:KUTs8W&k!:Kj[!:Kj["7GmVmf)n[mf)n[mf)n]me3a[!!='rM\u?l"/PYamf)n\
+me6VZs7QH\rq6?[rq6?[rq6?[rq6?[rr3,hs8Vf\rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6Wc
+s8N)es8Vf\rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6Zds8Vf\pAb0\pAY*kpAY'mp?qqR!:Kj[
+!:Kj[!:Kj[#k%`m!:Kmep?qqR!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:KdY!:Kj[!:Kj[s8N,nmXb)$p&P-kp&OOSpAFpkpAb*b!q,dMqY'je!VZQlp&a[UmeleX
+rrM9^J,~>
+rr2tVqg/aAhWFP3s7YmCk2+XQqKiD>s+>B6CAr8SCAr8VC3+H2rc8'Src8'Src8?[F)ssT]qhaS
+rVm,AXIQu*8onbHErg#sqZ$P9!,DLS!,DLS!,DLS!,DK4!s&B$!<.$>CAr8SCAr8SCAr8SCAr8S
+CAr8SCAr8SCAn/7F8u7?rc8'Src8'Src8'Src8'Src8'Src8'Src8E]F8u7?F8u7?!-A/>!W[:V
+rr2rurc8'Src8'Src8'Src8'SrVlt@s8N)uEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSErp)tCAr8SCAr8WC=W?KF+J\1HOQG$k4\iTp?q)*hURkeHNVg\me6SY
+s7ZHS!S)8hHNVg\me6SYs7ZHS!S)8iHN_Uns#L+0~>
+rr4"QZF7'IZEh@(lLt8Xo'Yf.inhPX[^*?I[^,W,]&g'tFTB!a*;]^=*+?DYFo&9;s7*8jrrW9$
+rrD/`rVlu&s8N)[Y5eM+!3ZA%!!'2$rrN2'Y5\G$!:d5jrr]G(rrBs>J*-dJWj]4AZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZ@96f[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I_VXSOs8VZXlK[Bc_QpVU[^*?IhWjP&
+s8Dctp@@M6k2-*C#I^qHhWjP&s8Dd)p@@M6k2*DL[^*@$s8RrUJ,~>
+rr;ff!Uf[[s8M`lmeQSUs5iqWU]A);)#F:9+C`"aV#'f]s7,g]rrW9$rrD0SrVluns8N)[pAb-s
+!;?Hm!!)`lrrN2opAY'l!:fd]rr_uprrBt1rr2u\JbG]/!Uf[[s8M`lmeQPWme6GUs7ZH[r:U0Z
+pA"[fpAXLYpAY'mk5Tr~>
+s8N,MF8gLjF*i88hX9h2rsA,UhWE@iHZOOTrd4\FjD#3'k$$Wu]p,U_Pf;M9;XRH[CB+>4!<<'"
+!,DK4rbDB2s(_N4"T\T&!,?9Hs8Qj6s8Qj6s8Qj6rrQs8CAe)3CAn/9!<<'!C23_IrbDB2nnS4)
+"p"]'!!$bKrr3$"C23bJ!WZtMrVuk3s8W+6s8N(6rVlitr;X`N"MOi*F*%>-!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d"`o$lhX9h0!!V6AeZ=+=rd+ijHbJS(me6SY!:KjK
+$b^"rHZOO\^#nJFpAFpjmf)>U]jc>0H[C\Ns/\52~>
+s8N)]qQ^4ChX9t6q??<Pk3Cg?qQg/$1od^YY,\Y)Y,\Y)Y,\M)WiiA)WiiA)WiiA)Wih$U=k;<<
+OfFP']%5S8!/7GUWiiA)s8W#ts8N*"Y5SA%WiiB"rrK.&rVm$$s8N)!Y5J;0Y,_O%Y,_O%Y,_O%
+Y5b[&rrB5#rriE&rrB(%rVlr!Y,_F"(TOX<Y,\Y)Y,\Y)Y,\Y)s8N*!rr<&!Y5\G&!334$rrN2#
+Y5SA,WiiB%s/rC%s/u>#!!)rs5cUueY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y1EWmV65BTTX"[>hX9t4!!DBKhST,p&'F2&meZt[s8)T_lK76O
+U&;2,b3J9[qZ$ElqYKdJk2sg[rNZR?s8UAqJ,~>
+rr;ig"6T%FpAY*lp&jaVk2uO6s8W,m1@Fl(p?qYBp?qYBme6)Bme6)Bme6)Bme6)B]`;6mhS#/T
+Pa'/DhGO?mme6)Bme6\\r;clt!<DilrrVW^mem(cme6VZ"T\T&!:KRYrsnbjs8Vf\s8Vf\s8Vfm
+pAFpjpAP!p!<<'!me6VZ!q,dMr;RT$p?qYBp?qYBp?qYBp?qt\!<<'!!:KR[rrN2gpAY'n!:KRZ
+rsA,emf3=\mf3=\rVlitr;T%Mp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYSs7YUCJbGc1"6T%FpA=mmme5f*qXsp>rq?6hs7QQ_p>4[(p&NYB
+pA=mip&jaVhVS5)rVllJJ,~>
+s8N(pqf;mm^#nJNrVm&hhVRD.KDT`irrHkDrb;FBrb;FBqe?+?rb;FBrb;FBrb<!RC5]0XMj2cl
+e_Z4KMl_hGrb;gMC23eK!,?7XC&e82s8Qj2s8Qj6s8N*!rrE+7qu6s&CB+;6CB+;6CARr1!<3!(
+CB+;6!<<'!CA\&2CA\&2C&h`BC&h`BC&h`BCAn24!<6d6@f?<,CAn/5!,DE2s(_T6#ln`?rr?g6
+rr<&rs8Qg6@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@f0s@@fC*H
+@VTYBs35;0F.dRVK>$F0q>^WSk.QEEEr`<@jpUn_rr<'!p>4roXCD*K!3H1^rrE#trrE)]!N]c.
+Es(k1p*kL~>
+s8N)AqlUC6`ocRWqZ$Ecmc*6k`qlk<s5U*g,WLpGOk0Q`er>fO3$e@#s8N'!rMoktqu?\rqu?\r
+s8W*!s8N*"Wr)f&!36)!!36)!!35nq!!*#u#cdq)!!*'!!35qrs/Ptro;_chrrE%urVlktrVllu
+Wr)hrWrN)*!36)!!36)!!!)or`i9-Xs5KT#Y+Vp"ZGu%lq>^TVlGi\'!4r0l$hjGs!!)ldio]C7
+Q2Icb])Ljl!"&]%s7u]qk2s7?r2p.qs7U/W~>
+s8W&k#4D3Ymb[[2r;QromdBf*k5=oSmf3=Ip'i`:P`(dVs4,taP`%OVqY'sh!!)ukrrDrrs7Z?i
+s7ZKmrrE*!!<Dijrs8]!s8N)ms8N)mqYpNqrr38ts8N'!s8N)mqu?]iqu?9]rVultrq?<j!;?Bk
+!<Dijs8Vfmrs8]!s8N)ms8N'!qu=\0rr2uTrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6N`p?pf2pA+akme5N"rq6Qap@d&1p?qq[rrE*!#4D3Qc.2OUrq6NGp@dnS!<)rt
+!!Dr_c.2dd!:Kjd!3C\~>
+s8NX_C3+-2C3,$PhWF8+pAaj[rn[t#HYRV:F)#drs5RPt9(&5+hNY++Phsrdk">JZs8N'!r*o^+
+r;clt&Rte?!!*'!!+Q!.!+Q!.!<<)u!<<',!+Q!.!+Q!.!+Q!.qZ%%6s8N*!rr?O.rrE*!r;clt
+#@d`5!!*'!!<$C*s86@(s8?F*rr<&trrN3#s8;rtrtAlArr?O.rr?O.rr?O.rr<'!rrC)KJ#r[?
+@VTt!F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2
+F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2
+F)#c2F+7qGC3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2
+C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-Bc/.R_!;?Hd!!(m4
+`Hu?@C3+-2MrrRHmf34c%dr3(k)3DaF)#c2MrrRHrW!!!pAP%#e`McnF)#c2F3Xab0n9~>
+%KH:9WiiA)Wii2Lk2u76q@<5iio9+GTrP8qY,\Z)s5TpbJH/6perctpNS;rS!.k!Cs8N'!r2'Gn
+r;clt&Z,O-!!*'!!2]_q!2]_q!<<)u!<<',!2]_q!2]_q!2]_qqZ%&$s8N*!rrAnqrrE*!r;clt
+#GqJ#!!*'!!<&bms88_ks8Aemrr<&trrN3#s8;rtrtD7/rrAnqrrAnqrrAnqrr<'!rrC*9J("A6
+RAI'dY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y(*ISWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)Wii@uf&l)p!;cQc!!)$@
+cCq8@WiiA)U#t(go(r:b%eAW5k+Rp?Y,\Y)U#t(grVuuqpAP%#g?,)kY,\Y)Y2]K]@=S~>
+rr;lh"O6)sp@eFarpBgDc2757s#f`Cme6)Bme6)Bme6):p?qYBp?qYBp?qYBp?qYB`;iNehNY++
+Phsq_!58*op?qYBpAb-mp?qYBpAb0k!<<'2mf3:e!<<'!mf3:emf3:es8W&us8NH,mf3:emf3:e
+mf3=a!"AT$rrE*!!:Kme!<<)t!<<',mf3:e!<<'!me6)BrVm#gp?qYBr;Qlep?qYQrr<&trrN3#
+s8;rts&/:brrDKerrDKerrDKerr<'!rrDK\me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)BpAaj:mXb)*p'&_'me-V\rr;uus6]pEc272<^%UUVpAb'k
+"nqBHp:]#Sp&i#%k3i3Ks8W&u"6T<jebo.?rrAjF~>
+s7ZJ-!+PqB"(HW6k4eptk1+ff@VT@eCB+<C>%1ZE>%1ZE>%1ZE@Tm5E@Tm5E@Tm5E@Tm5E@Tlst
+XH^Eue\-mBk#u4t@Tm5E@Trg3!*Wi8@Trg3!*Wi8s8N*!rr?O.rr?O.rr?O.rrE*!!*Wk3rr?O.
+rr?O.rr?O.rr?M3qu7T8s8N(.s8N*!rr?53>6"U&s8N(.s8N(.>%1\6s)S0D@Tm7@rrE*!!*Wi8
+s8N*!!<3'!rrE*!!*Wi8s8N*!rr?O.rr?O.rr?O.rr?O.rr?M3@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E^&O!oC1@0W!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB#CG=ihX:+;pAP$qe`PD/@Uf=O"_)i8e^a*b!<:RXhKrF8
+C2.3mHf!<'me["aeHOfV>%25UrbDK5!%EE~>
+!VZBdWWJIFk4eoYk1Z)or2TesBVhE!Tr"HZTr"HZTr"TZV4j`ZV4j`ZV4j`ZV4j`ZD#bPq])U?m
+E?"sqV4j`ZV4j`Zs8N(mV4j`Zs8N(mV4mqh!<<'!V>pPqV>pPqV>pPqs8N(mV>pPqV>pPqV>pPq
+V>pPqV4med)Z]p<!2]_q!<<'!Tr"I_rrE*!!2]_q!2ZBcU&G"3!266_V>pPqs8N(mV4mqh!<3'!
+!<<'!s8N(mV4mqh!<<'!V>pPqV>pPqV>pPqV>pPqV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4lK?^6POGWhHEtQ/^rco(MqRrW!)Xk1Z)or2Kmb
+inE8WqZ$cUg>\B[r2KmbinE8WqZ$cUg>\B[ql9\r!+CB~>
+s8NDnp?qYBp?o<Up@nUpp?''Vme6)Bmf3=dp&OO[p&OO[p&jaVp?qqR!:Kj[!:Kj[!:Kj[%.9nk
+(j!Cje\-#H!1a&^!:Kj["Rc<i!:Kj[0(/c>!:KRSs8N*!rrDcmrrDcmrrDcmrrE*!!:KR\rrDcm
+rrDcmrrDcmrrDcdqu7H4s8N)ms8N*!rrDK\pAb-ms8N)ms8N)up&OOZs"aZKp?qYSrrE*!!:KRS
+s8N*!!<3'!rrE*!!:KRSs8N*!rrDcmrrDcmrrDcmrrDcmrrE&l!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6Qas8VfCmd>Sume6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6'Xp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qX]me6)Is8E!*me5eVmdBf:p?o<emK!:a!<2Bk[+4U4
+p?qX]rpBddqZ-W`$FJ@Op?qYBpAb/_J,~>
+%/0+(@VT@e@VTB7hVS)/rn[oi>&%M]@VYrCi*$B1s37XPc2Z&_>6"U&!<-1#rr<&u>6"UL!<<'!
+>6"U&>6"U&>6"U&s8N(&>6"U&>6"U&>6"U&>6"U&>6"X%!<<'+!<<'!>6"U&s8N)u>6"U-!<<'!
+>6"U&r*'%!rEB7$!ruO)s8H4%rsAc+!<3'!rrE*!!<-1%rt>D4rr?7&rr?7&rr?7&rr?7&rrC)C
+"K_Wf>$?Dj@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@aC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe@clP(k4\NJ
+!!)0\h?m^qC1:peC1?&EebK1Tc/)o-C2.3m@Ue3=e`QT(!"S/Ac/)o-C1:peC1@5C.=_~>
+s7Qf"V5gAlV5f73injM3/DfCKKpes;Whl`qs.,jSTq.mJTq.mJTq.aJSY;UJSY;UJSY;UJSY;UJ
+SSe0&%r%`.Tq.mJTq.nWrrAa`U&G!B!25sWs8N*!rrAVirrAVirrAVirrE*!!25t`rrAVirrAVi
+rrAVirrAVis8E#uru;%=rrAVirrE*!!25sWs8N*!rrAVirrAU`SY;VQ!&:1<Tq25`!1j/iTq.nW
+rrE'!rrE*!!<<'!Tq.nWrrE*!!1j/i!1j/i!1j/i!1j/iIfQ%5SY;UJSY;UJSY;UJSY;UJSY;UJ
+SY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJcMtbDSZ8NdV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV15MAWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhh&BV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAGk2P7_o()b[%dMp1k(T5'V5gAlL#U\;q#CoUie<Al
+Whl_lL#U\;lLOlR%dMd!ie<AlV5gAlV>pC#J,~>
+s8Vrh!2TV^q>gN_!MnlUpAb.8me6)Bme6)Bme6)BmdBf:p?qYBp?qYBp?qYBp?qYBV"k!$SG)CE
+me6)Bme6\\!;>jSrVnDKp?qYSrrE*!!:Kme!:Kme!:Kme!<<'!p?qt\!:Kme!:Kme!:Kme!:Kme
+rW)uu*!$$=!:Kme!<<'!p?qYSrrE*!!:Kme!:KRKp?qkZEVAhomf3:emf3=\me6\\!<3'!!<<'!
+s8N)mme6\\!<<'!mf3:emf3:emf3:emf3:eme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6ASp=8;Vp7_0[V#Kc`pAb0l!!)`lmK'-Gr:U5gmcNs5
+!!DBOUt,D:"f1SKme6\Z!!W)ak3f%qqtC'i!2P,~>
+%Hd(^@Tm5E@Tlslk1/Vl!'ou&k06e->%1ZE>6"V3;Hct%;Hct%;Hct%>#JO%>#JO%>#JO%>#JO%
+>#JO%;IZa-s/]Br>#JO%>#JO%>#JQ#rr<&rs8N*!rs\s3s8N(&s8N(&s8N(&qu6Zs>5S='!*]F&
+!*]7!#QXo)!*]F&!*]:"rrE*!*<9:Crr?5#>#JO%>#JO%>#JQ(rr?5#s8Q8#s8N)urr`?%rr?7"
+s8N)rrsJg1s8N(&s8N(&s8RQK>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#N'6HW"<V@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5j>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE
+>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE
+>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE3*Kcp@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@TqXNe`Q;n!!)HTe`P+S>$>B=@Tlsle^aHq%b9E>;Hd75>%1[le^a*Ur;[>qe^`M[
+;HdO5@Tm7/p*kL~>
+s7-PkV4j`ZV4i=ok2,D$!&*csk14g?Tr"HZU&Y.hSY;UJSY;UJSY;UJTq.mJTq.mJTq.mJTq.mJ
+Tq.mJO[T-J$qQAOSY;UJSY;UJSY>o[!!)orrrE*!%03+%rrAbmrrAbmrrAbirrE+nqu6g"U&Y,m
+U&+cp!<<'!U&Y,mU&4li!<<'>!29Gm!25sWSY;UJSY;UJSY?)`!25t`s.Q"`rrE&u"9AK%!29;i
+rrDrr9E:ddrrAbmrrAbmrrAa`Tq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJ
+Tq.mJTq.mJTq.mJTq.mJgAeUDTqQt4Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZ
+Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZ
+Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"H,V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`6hWE\[md^>Xo'YAsep3COV4j`ZIH&u7q#CoYidHf[Tr"HZIH&u7lL+TN%dMd%idHf[
+V4j`ZV=sUkJ,~>
+s8NJpp?qYBp?o$Mp?))H!&+'6p?&1-me6)Bmf3=\me6)Bme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+p?qYBhJ2uh$u4>dme6)Bme6)Bme6MW!!)orrrE*!%06,%rrDcmrrDcmrrDcirrE,nqu6g"pAb-m
+pA4dp!<<'!pAb-mpA=mi!<<'>!;?Hm!;>jSme6)Bme6)Bme6\\!;>j\s7Ym\rrE&u"9AK%!;?<i
+rrDrr9E=edrrDcmrrDcmrrDc\p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBs8VfCmd>Sume6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6'mp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qXUme5f:pAY*ms7YmSk+pl%p?qYBV!dC-q#LH_%&DGAme6)BV!dC-p@eFb%ef&Qm\JD$
+p?qYBpAb/_J,~>
+s5j;jr`TS:>$=P"hUU0ErW!/jk2+sr5t_)Z"(L-eF8f&;9)_]g9)_]j8lAPZr_`_gr_`_gr_`_g
+r_`_gr_`kk0f`-(r_`_gr_`_gr_`bh;Z6Xp!!#pqs8N'19)nnk9)nnk9)nnk9)nnk9)JVi!(p/e
+rrrHqs8N'k;Z?[u!<<'!rr3-os8N'k;Z6Xq!!l3srr>[krr>[j;?0>g;?0>g;@H1trr>Yh;ZHbp
+s8N)urriE&rr>YhrVult!D68frrE*lrr36rs8N'ks8N'kr_`_gr_`_gr_`_gr_`_gr_`_gr_`_g
+r_`_gr_`_gr_`_gr_`_gr_`_gr)*Mer_`_gr_a!Gs&r;u>$>D7=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=pAG>9!$n"ebnhGk2+sr5tY<a@Tlr$k0;H=r9agPe]m5B8m5^'=p..R
+c.1tR!!Lisk!;W<=p/;<md;f[~>
+s6f`W"b",EhVRPs!!`#Zio[shNVoJ.lMn/\R@Tb:R@Tb:R@Tb6SXH%:SXH%:SXH%:SXH%:SXH%:
+SXF2+SXH%:SXH%:SXH%:SXH&Is8DuuSc/Tg!"bRurrAJerrAJerrAJerrAJarrN1gSc&Kl!1Ele
+!1BDWrrW9$rrE&u"e#Dj!1BDVs8N'ARK*9eRK*9eR@Tb:R@Tb:R@Tb:RK*9eR@TcGs.02i!<3!%
+!<<'!R@X<Vrr<(fSc&Kg!1Eid7[a;V!1Ele!1BCGSXH%:SXH%:SXH%:SXH%:SXH%:SXH%:SXH%:
+SXH%:SXH%:SXH%:SXH%:SXH%:SXH%:SXH&.s.PF?JYAd2#(=5FhVRPcrpg6Xio[shNVoI\D<BR/
+lL+*2mdBAsg?*73r1O71k1\\WqZ$cUg?*73qk4)bnmR%~>
+s8W)l!:Kj[!OUDVmJut[!!`JsmdAVihZ!3Rme6\\p?qABrpBd[rpBm^mdBfJmJut[mJut[mJut[
+mJut[mKE7OS>>lXmJut[mJut[mK3+Mmf!1b!!)Hcs8N'1mf3:emf3:emf3:emf3:emed"c!:K:Q
+rrrJks8N)emf*4g!<<'!rr3/is8N)emf!1c!!hrlrrDKerrE&d!;?E[!;?E["SV9`rrE&ds8N2h
+s8N)urriE&rrDKTrVults6fgb!<DQers.ulrrDKerrE&d!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!qu'UrpBd[rpC$bs8VN;k4\6Bp&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&sgWp9`BLmf2tfs7ZKdmdAVihY-C:p(*DUk3hsCpAajdp?q)2Ph#a+
+"n%WCk3hs?!!M`PmZc9$p''mXpAb/gJ,~>
+s5"&[>#JO%>#It-k5O4,mJutKmcNYH0iCnQ;Hcu*s/\gj8lA8Z8lA8Z8lAPZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'jc!!>hk8lGTf&kZ%o!!#nh!!#nh!!#nh!!*'!rW)uu
+!ru4k;Z$M!;G$oh;G'jd!!?+!!)!4j"\Jap;G'jc!$Y$58cSih8cSih8lA8Z8lA8Z8lA8Z8cSih
+8lA7]!)`ds9)\eo8cSih8lGTf"%lH`;Z$Lq;G-og6qRFZ;G$oh;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;H!Pp8kOS:;Hct%;Hct%;Hct%;Hct%
+;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%
+;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct.>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>"WPlrn\:U!!)HTk2pD5;Gp[r>#IB;hUVE%s5")C
+8lAPj;Hc*;hUVT*s6fjds5")C8lAhj>#JPdjsbf~>
+s6BHOs+q3Iinihc!;?!Ok2qY7NVo=Kf)O%>RJd-aRJd-bRK!9eRK!9eRK!9eRK!9es8E#urr<&u
+RJ['bRK!9dRJm0gR/d5TrW!"f!!*"dr;chbrrE(errDYYrrE"crr<.h!!&Gd!!8Pg!</Db!<&>`
+!<8Jd!!\hk!1B5T!6CQ2ScA_<NIdXnSc=NUk2P7[mJm7XmcNYkAW?VY"(gKOhY@0OiW3VIr1*q$
+io8ho!!2NYrW)uX!G.,bScA*X@=S~>
+s8NDnp?qYBp?pJ4pAXIirrE)mp?qXUPhtj%me6)Js"s0;me6)Bme6)Bme6ABp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYQ!!DZ_me6SZ'(5J]!!)`\!!)`\!!)`\!!*'!rW)uu
+!s&&_pA=mpp?hn\p?qYR!!Dop!:Kgd"mu?jp?qYQ!$^k)mJm7\mJm7\me6)Bme6)Bme6)BmJm7\
+me6&K!;6Bmmf!1imJm7\me6SZ"7GmNpA=mkp?qn[7d^6Vp?hn\p?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qt\`RXDEJ+i=(me6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmU>hWp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp=68<rpC<s!!)`dme3`HhX:+*p?n1EmeHk_mK]!,
+mdBf:p6>RErVuums8E#umL#3/me6)Bme6\\S:C~>
+!T)B&;@Y^Ok2+tWmdBf2k05>89)MQiHiN5#62jIV62jIY5tXa8r^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m2W9)APi!(ojLr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m5X8jWGK!($TV"[S(H]fA]9;P-hs3L&[_hW=e<p?(M^.61#u
+;?/0FhY@-RhW?7Qr)*MDrndYTrpC!a!!(m<.7*i/!p8>gJ,~>
+!UAhCSITM:k2PC_mdfr:lIK*TOo1bL[f>c`Q'mo*Q'mo*Q'mo&R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*RJQr5!0rt;R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+-^g6fQ'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'moOs4VaXR=Up%SITM:k2PC_!!)TXlIK*T
+Oo1aP<T`<#q#LHW!EG!SSHW$Uio0q<rpC!]!!)0D<JgUD!q,>^J,~>
+s8NE!me6)Bme6@U`Vo6)p(.2sp?%:7hY-C2me6ASs7ZH[!;?E[!;?<X!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!qu'MqYpTsme6YJ
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;??Y!;?E["SV9Ws8RSUhX:+*p?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qWcme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BXMt/+rr<K-p@dX,XPW[=p?qX,rpKR^s6^,Ec1^l!
+p?mS4mf*8"pAajd!!)HTK?a,Xp?qYBs8SmF~>
+FNr?.;G'hZ;G'PI0pLhWk2uC2mZ]FK3D)nA8lA8Zec1P"5tXF85tXF85tXa88jQ'88jQ'88jQ'8
+8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88c\kj
+rW%F?5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXFm8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'89'6.g5tY$I;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8g.));G'hZ;G'50Pigibk4\N:PVF:@8kMuR;G&(g
+k2,7_rU(6jmcNXS5tXaI8l?egk2,7_rU(0hmcNXS5tY$I;G'j;hC3s~>
+!TN8;R1=pVWoiI/lLsr>Wa/GHOo(OJk5W0!PlLg`s8E"LQ/Ru3RI:*TI>rfGT:$1C?)m&LlK\*:
+m]'PhH'/#m%nu!Fk3D7"mdfrBmcrq.L&@>L9]G3slK[g*o()MBlK1coqjIKH!+CB~>
+s8W)d!;?BZ%b6KVp?qYJs8Vf3MhA_*rpEn^me6\\p@dqJme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qVSrr;rt
+J+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)BmO7esp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYSs7XFgmdBfJmJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mL[p,`V/`npAb0d`J]A^k3hsBmK8+0p?qnQ
+rr<#l!q(]crU'g^KC8I$rV$6js7QN^K?aD`"nqBPs8SU>~>
+s3:=2$ooG.PeH4uUfnTP0gYY.<g<XX;F*</3C,Yk3C,Yc5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4krW%F.5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4Z
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C0J@ZnXR56%MY#8dm^&;O"lW`M?ZS(bn>R
+8c]LcrndV9s6^$`md:WPr(6u$k5O69k5XiPp?q>[62O7Ue]fh!~>
+,3%IIQ'mo*Q'n&*I8G'_b3%-XI7-b?KpA'kR?a2*^An&#Y*&\`JW\iPJ'.fBD1Rh7R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R=:EhQ'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mnc:j&VWk0gP`6qh0GQ'mo*Q'k&&
+irA0>l4ECSp?qK>JXMpkR?^2&io]D%l4<=Rp?qK>JXMdkQ'mp"iaI?~>
+s8O27me6)Bme6ABc&8+2hY-*VS9'=QhX:+*p?qYBpAb/pmf!3;mbdG^pAaifc0"Hfme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BI.$^rp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?p1`SAj@Yk09E;K:Lfdp?qYBp2g3#
+!VYs[p'Uins)ZHYp?qYBF8bM-p?qnQ%KH/%F3XFHp?qYBs8SmF~>
+s2>")9)_*V9)LsU+;"MX#S7h%.60[d5t_,B"\M)"s5lrQ5l`qE5m',55rnp1!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!]`P,r]piN6&YdC5rh4s9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)V$V+;"MX"qVV#.60[dr]pTX5p5e*!"f,q
+"%kjF+S5pA&4&TSr]pWY`Q]i^~>
+%bfd%Q'%>oQ'%2oNIb5#r]CcX6rdfLNKoWkOd2&oQ/;Q/R=UKYOTN,os*p/RM34'cQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'#gHOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd1oW=[`6O$p[3\AV#i+Od2&oO^7TA
+#=O-*Od2&o?1^5d7"LJcOd2&ohVqso~>
+s8Vi]!nEffrc86XF,Qj=k54QIp?qq[!Uf[\mJut[mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;??Y!;?E[s7ZKm"R`t[me25"T'c[1S9t6V"_r+:Us8'!mJs'T
+ErgX4r9aQ\oQ(%[c26r/rrAR>~>
+!QDbG5liu#r$_Y$3VPfK9%Et(>!Y/73C,Yk3B;RT3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,ZF5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh6,s8Q7W3B;XVRm@'81&NI$0ff"p!BDV&+9<oOq`t6C
+.J=kb.678ks2=seJ,~>
+s4RpIOd2&oOd22oQ&UK?C&VBMBm#,hQ'%>oQ'%>oOd5)/m\,2kNf=@-b5_L8D1RP+OaiXYQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'#[DOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd1o[F_Uh\3,*MhNKoWkOd2&o
+Q%<XL=]JU)=]JU)=]K0eQ'IJsOd1K3<EW=)<EW=)<EW=9JX)@_Od2'cg0oL~>
+s8O&3me6)Bme6ABp?peNXIPNFXM*KYp?qYBp?qYRmf*7dmK_nBk3hC"k2q0]k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hAQmcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs2s8Veoe`Q;fJ+i=(me6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+mWJ6kp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?peNXIPNFXM*KYp?qYBp?qYJ
+/Cgh[P`(caP`(caP`)Wnp@dqJme524Mj0-aMj0-aMj0.$eb8G)me6)Ks.k/~>
+*ONL?5rh4k5rgqk3C,Yc0f^sK0f_6[3C,Yk3C,\)5n$ZAs8TH03C,Yk3C,r\3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,YkE&g3E
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5s^.cs8Q7O3B@()IlTeT5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+6$51R3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yc0f^sK0f_6[3C,Yk3C,Yc
+/3u!N0f^sK0f^sK0f^sS3B9Ac5rh4c3AENK3AENK3AENK5rh4k5rh6E]d\I~>
+s4/-KOc>K_Oc>?_NKK3[JUr6#JW5YONKK3_NKK5"OTh04s8UN@JW5hP#a)R`s8Sd,I>.Z_IuTSM
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_O`QMENKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3[JUr6#JW5YONKK3_
+NKO4"%"WhPI<g6dI<g6dI=_BW)j-,BNK&L;H$ssdH$ssdH$t7'NKK3_NKMfG@=S~>
+!VZQdmK)J,rm_&+k4n?EpAXLYrrDcljob&6k3i62!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK#4CXAk2u+*rr3)oXNfUQm[<JDk2-*f!T)u4mJtf2blH;imJtf2blH;j
+mf3:eS:C~>
+s0O:B3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh4k5rh4kXS2\om]<LBMh?Y3Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?B8_D#
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8Yu$`W#lAZoKQi0f_7D5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+ImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3@$mN5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k['VQ<~>
+*S/Z$NKK3_NKK3_NKK3_Oc>K_Oc>K_Oc>K_Oc>M%N<b<cqZ$TdcH_!PR(<XAdbaj#s43$@H%GpR
+J!#_QNKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NIR(MOc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc:QINKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK4OdU@Y~>
+s8W)d!9X:K!9X:K"6T%>k5OcKk5OcKk5OcQk3hC"k3hC0rrMinJbGH(r;R,thQ4]Hk2u*omcON:
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K"m57@s8SmF~>
+s/Z5]62ikE62ikE62NYB62ikE62ikE62ikM5rh4k5ri,MhLY]hrsHGS0ek[K5rh4k62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikH6*..:J,~>
+s3;R?NJWXONJWXONJWXOM2d@OM2d@OM2d@OM2dAiN<>$*cK]u\OoG[;V.FLlJVf6_NIQeEM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d"ANJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWW=M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OcI--O~>
+!VZQRjoFiKjoOoDJcCf2"R`@uc.2dT!:GF#J`bqR!quYaJ,~>
+*NZ&&3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh713<2AD3<M!.F*iJ.R%+A5C.^300erVe!($TE
+ImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3Ia=T5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rg,T3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,[,Ua^f~>
+.F-(qM2d@OM2d@OM2d@ONJWXONJWXONJWXONJWXONJWXONJWLCQ*.Fl`dbkF_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T$Q3`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`jVn4EG9E8JVAr;IuT;EM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM1:MA
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJT!AM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2dA;b$ff~>
+!WVlTjoF9;jp0c*hVQfFmd>Z"R.gRJ$Kf%']uAOPk2,7WJ`_OGhrY"?p8!3~>
+-Cgkd3AENK3AENK3AENK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKpb;atr\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%pG%.X0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^t<3AENK3AENK3AENK3AENK3AENK
+3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK
+3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK.60+C0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKS>7Ta~>
+.`TVVI<g6dI<g6dI<g6dH$ssdH$ssdH$ssdH$ssdH$ssdH$ss`F`h\Drb[.!D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j'Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$D/jQ@H%16fI<g6dI<g6dI<g6d
+I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6d
+I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g<jH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$sreI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g7\b$ff~>
+*VTNPc,IrHc,IrHc,IrH`QcBH`QcBH`QcBH`QcBublu)2`PoO(rj70V[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gWFXL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XSoO+^&Q(Jc%!^W`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`Q`nOc,IrHc,IrH
+c,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrH
+c,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IpO
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBHpA^Y5~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@p?mr=!<7W<JaS*W_X7L\Umrla~>
+!liB.p?mr@!<7W<JaS*W_X7MOb/Rk?~>
+!quZ5p?%B5!<7W4J`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\O59m:JaS*WJaUDC"+A23@=S~>
+!rqu=p>u?QO)k=$J`_OGJ`ai3"3pQ>S:C~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\O59m:JaS*WJaUDC"*r&/@=S~>
+!quZ5p>u?QO)k=$J`_OGJ`ai3"3(<6Ujr~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\O59m:JaS*WJaUDC"+A23@=S~>
+!rqu=p>u?QO)k=$J`_OGJ`ai3"3pQ>S:C~>
+!h?&@p?hoYNrR/frr@W<JaS*WrpBkCUmrla~>
+!liB.p?ho\O59m:a6rs-JaS*WJaWO*"*r&/@=S~>
+!quZ5p>u?QO)k=$a6*C%J`_OGJ`cso"3(<6Ujr~>
+!i2>Hp?hoYNrSb>q>f:<rrDo`quH?Vrr@W<JaSup"$)mI.=_~>
+!m8N2p?ho\O59m:o^;PUg[>(AqX47]oBuVYJaS*WRdL9+`l__?~>
+!rqu=p>u?QO)k=$o]GuMgZJM9qW@\UoB-&QJ`_OGRcX^spA^Y5~>
+!h?&@p?hoYdf0U'`Pp*P^!5F-`rG`"rW)ob!!(dArrDrarrE&drrDi^rr@W<JaSil"#6UA.=_~>
+!liB.p?ho\dbY8P^:qn<]#)VDa5-grp$VeZrU'Xcg[>(AqsOIarpKddq!S.^JaS*WQL4j#b/Rk?~>
+!quZ5p>u?QdrPhBXMr`HhTa$8HcL1-s7POR!<)$[!8HZ9!;kpY!<2-\!;P^V!.j9`k*G-3`W,Y-
+J,~>
+!i2>Hp?hoYe,KLC^#&_f"8:9PhT,Zimf*:]mem.bmf*7gmJm7cmem.bmem+cmem.bmf*:bmf*:b
+mf*7emed%bmem+emJm7dmf!4cmf*7gmJm7cmem-:mXaf1mK5J>Ua^f~>
+!m8N2p?ho\e(t/[]%6i["7jmKb/iE>s7Ym\!;Gp[!<2Ed!!;Qg!<)?a!<2Eb!!)Hc!<2Ed!;u9b
+!;u9b!!)Hb!!)Hc!!;Qg!<2Ec!<2Ed!!;Qg!<)?a!.jQhm]c*]IE'E<J,~>
+!rqu=p>u?QdrPS;`TI.!"8:lrSB,aOs7YUT!;GXS!<2-\!!;9_!<)'Y!<2-Z!!)0[!<2-\!;u!Z
+!;u!Z!!)0Z!!)0[!!;9_!<2-[!<2-\!!;9_!<)'Y!.j9`k-3tMc1_1-J,~>
+!h?&@p?hoYdf0CB^#o7m!qsU`aT(u%rrDi^rrE)errE)erW!Gr!!)HT!!)HT!!)HT!!*#d#QX;\
+!!)HT!!)rbrrDubrr<&erW!T!!!)Ee!:K7T!:K7T!:BgemdC&S#4;Hkmd:&TJaS*WXmQ9GUmrla~>
+!liB.p?ho\dbY&V[c[Mf!qO4Fakd$tp?qq\q!S.^s6fmes6fjd%dj;smd:&Tmd:&Tmd:&TrpC$l
+md:&Tmd:&Tr9jRbr9jRb!:Kgd'(,`"mJm7TmJm7TmJm7T!!)HTrW!/j!!)HT!!%T<JaTZ."*r&/
+@=S~>
+!quZ5p>u?QdW5JB`U<X'!R7F^Erc76k5PGVk5PG]k5PG]k5G>jjo>DDjo>DDjo>DDjo>D\jp1tL
+jo>DDjo>DZk5PGZk5PD]k5G>njo>DD!!)0D!!)0D!!)-]!9WGC!!_Qc!9WDD!.j9`k,mbJ`W,Y-
+J,~>
+!i2>Hp?hoYdJj:A[-%8c!PR%*s7Ym\!<2Eb!<;Ke!<;Ke!<;Ke!<;Ke!<;Ke!<;Ke!<;Ke!;l3a
+!<;Ke!;u9b!;u9b!"ePu!:K7T!:Bgemd:&TmJm7dmf*7mmJm7TmJm7Tmf!3;mXaf/mK5J>Ua^f~>
+!m8N2p?ho\dG=rUY2]?Y!P6.jh>mTLmf*:dmem.cmf*:emf*:emf*:emf*:emf*:emf*:emf*:a
+mf*:emf*:bmf*:bmf*7umJm7TmJm7T!!)HT!!)Ee!<2Ed!!qum!:K7T!:K:S!.jQhm]Ps[IE'E<
+J,~>
+!rqu=p>u?Qd;oAA^$bdt!R7.WErc76k5PG\k5>;[k5PG]k5PG]k5PG]k5PG]k5PG]k5PG]k5PGY
+k5PG]k5PGZk5PGZk5PDmjo>DDjo>DD!!)0D!!)-]!<2-\!!q]e!9WDD!9WGC!.j9`k-!hKc1_1-
+J,~>
+!h?&@p?hoYd/O1@XQKE[!Nb_3s7Ym\!;u9b!<;Ka!<;Ke!<;Ke!<;Ka!<;Ke!<2Ea!<;Ke!;u9b
+!;u9b!"ePu!:K7T!:Bgemd:&TmJm7dmf*7kmJm7TmJm7dmem-:mXaf1mK52>S1/s~>
+!liB.p?ho\d,"iTWo![R!rAqFbME7!p?qq\r9jRbs6faas6fmes6fmes6faas6fmerpK[as6fme
+r9jRbr9jRb&FKMumd:&TmJm7TmJm7T!!*#drr<8k!!)HT!!*#dr;_E:JaTc1"*r&/@=S~>
+!quZ5p>u?QcuT8@^$bdt!PO-/Erc76k5PGZk5PG]k5,/Yk5PG]k5PG]k5,/Yk5PG\k555Zk5PGZ
+k5PGZk5PDmjo>DDjo>DD!!)0D!!)-]!<2-\!!_Qc!9WDD!<2-Z!.j9`k-3tM`W,Y-J,~>
+!i2>Hp?hoYci4(7Uu)%L!T(3+s7Ym\!;u9b!<;Ke!;l3a!<;Ke!<;Ke!;l3a!<;Ke!<;Ke!<;Ke
+!;u9b!;u9b!"ePu!:K7T!:Bgemd:&TmJm7dmf*7kmJm7TmJm7bmf!3;mXaf2mK5J>Ua^f~>
+!m8N2p?ho\ce\`OU"]GE!SX^"h>mTLmf*:bmf*:emf*:amf*:emf*:emf*:amf*:emf*:emf*:e
+mf*:bmf*:bmf*7umJm7TmJm7T!!)HT!!)Ee!<2Ed!!_ik!:K7T!;u9a!.jQhm]l0^IE'E<J,~>
+!rqu=p>u?QcZ9/?[-%;d!Tp3$Erc76k5PGZk5PG]k5PGYk5PG]k5PG]k5PGYk5PG]k5PG]k5PG]
+k5PGZk5PGZk5PDmjo>DDjo>DD!!)0D!!)-]!<2-\!!_Qc!9WDD!;u!Y!.j9`k-=%Nc1_1-J,~>
+!h?&@p?hoYf`)!&hYI0Qm[W_DrrVnip<3L/mf!4cmf*:emf!4amf*:emf*:emf!4amf*:emf*:e
+mf*:emf*:amf*:dmf*:emf*7emf!1kmJm7TmJm7TrW!Dq!!)HT!!)HT!!)HT!<2Ed!.jQhm]l0^
+0r1<gJ,~>
+!liB.p?ho\f\QYG`qeHmd[BD!rrVbbf$)tNs7PgZ!<2Ed!<;Kd!;u9b!<;Ke!<;Kd!;u9b!<;Ke
+!<;Ke!<;Ke!;l3a!<2Ed!<;Ke!!)Hd!!hol!:K7T!:Kgd%IO2rmd:&Tmd:&Tmd:)Smf*9<mXaf2
+mK7aW`aOA~>
+!quZ5p>u?QfQ7(Nq/ZUa[.aIu!qs<Sb]<dap#c5RroX4\s5s:\r9""Zs5s=]s5s:\r9""Zs5s=]
+s5s=]s5s=]qr[nYroX4\s5s=]!9X7\#Nc!dk2lXDk5G>ijo>DDjo>DDjo>DDjoGDCrr@W4J`a6"
+"3(<6Ujr~>
+!i2>Hp?hoYf`)#KSCRK9!kk,lr;Qf)hTPrjme["_mem.cmf*:emf*:cmem.cmf*:dmed(bmf*:`
+med(amed(amf*7gmJm7dmf!4cmf*:emf*:emed'9mXaf1mK5J>Ua^f~>
+!m8N2p?ho\f\ZY!!5eTh!j8*^rVlrqZGOiB!<;ZYqZ-T_r;clcrrE)errE#cr;clcrrE&dquHcb
+rrDo`quH`aquH`arr<,g!!*#drW)rcrrE)errE)equD<9JaTc1"+A23@=S~>
+!rqu=p>u?QfQ.+i[#=d%!gL(cr;Qf:Mp-5Bs7>CM!<)'Y!<;3]!<;3]!<)'Y!<;3]!<2-Y!<;3]
+!;bjU!<2-Y!<2-\!!;9_!<2-[!<2-\!<;3]!<;3Z!.j9`k-3tMc1_1-J,~>
+!h?&@p?hoYf`)&<m[Vi*rrTm0k5>5\p;P;"s0h@q!.jQhmZ6c<0r1<gJ,~>
+!liB.p?ho\f\Q^mk*a*ah?'jVir&WSp:e,^h>mSamf*9<mXaeemK7aW`aOA~>
+!quZ5p>u?QfQ..rm^.WEErqT>med"bc'6Fn!<9Lirr@W4J``$U"3(<6Ujr~>
+!i2>Hp?hoYf`))Es5oQrrr3A5V!e9Vs7ZKdp9_f^s0h@q!.jQhmZ6c<3LlloJ,~>
+!m8N2p?ho\f\Qb%p>V4Krn[^VSa-+G!qNe.bh`@"[dO.qJaS*WO7!*u`l__?~>
+!rqu=p>u?QfQ.2&s5pD8rc8I3[-mtfs7ZKdp;Ms6Erc6Kk5PF4k(2ZUjo`m%s."T~>
+!h?&@p?hoYf`)8Bp@d@-ec3"Hk5+cQm^0sVs+0ThmXafCmK52>S1/s~>
+!liB.p?ho\f\Qq"o((Xs^>>lXk5+WMlE[_>h>mS,mXaeWm_\AoH-4-8J,~>
+!quZ5p>u?QfQ._-pAa9VK6)sXmf3"\pAajdp;Ms6Erc5kk(2ZGk/-6_`W,Y-J,~>
+!i2>Hp?hoYf`)V3mdBf!Mk$$gp?qYBp?qYBk*4`Gs+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\f\QUVrpBp?Kp@eWqX+INifV+%h>mS,mXaeWm_\AoIE'E<J,~>
+!rqu=p>u?QfQ.%_rq6KOUm.tCq=XmXXFn`<!<7W4J`_OG_WCsFpA^Y5~>
+!h?&@p?hoYf`(uB`W#9,eXYLkmK26lp<3JemXaeWm_\Ao0r1<gJ,~>
+!liB.p?ho\f\QXg`r>6)d[Ahal2oObg<ACRs+0ThmXafCmK7aW`aOA~>
+!quZ5p>u?QfQ.[ieb8G)hR)G=me6)Bme6)Bk+'V9!<7W4J`_OG_WCs>s7W7=~>
+!i2>Hp?hoYf`),oUu(7rmf)>Kmf)>QmcNZgk+&Nrs+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\f\R:ES_iMgk2PO_k2PO_k2POWhOU4]h>mS,mXaeWm_\AoIE'E<J,~>
+!rqu=p>u?QfQ.+H[-%AU!9X(E"6T$YK?SB:s+0<`k(2[3jo`m%s."T~>
+!h?&@p?hoYf`)$HF2dh7#M$N$hPB#bp<N\hmXaeWm_\Ao0r1<gJ,~>
+!liB.p?ho\f\Q_aFhZ`-iX+K$cF1=<R?a&Sce\[%JaS*WJaUDC"*r&/@=S~>
+!quZ5p>u?Qf5h(Qc0"HVrpBdKrpC*TmbYq-k,^Ql>0h6is+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoYfDbokC<cM0$-g/s`Qd8rp=8l_s+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\fA7:KD8t;dg>:Q?g>:Q?cG%$4_P*gOOi%"P!92Ve!<7W<JaS*W_X7MS`l__?~>
+!rqu=p>u?Qf5h"?Mq.Ra$/WqOe]gu@3@S//Er^R=Erc5kk(2ZGk/-6_c1_1-J,~>
+!h?&@p?hoYf)GiJF0s3gh?)6Pc2Q5shY-C2eb7AiJaS*WJaUDC"#6UA.=_~>
+!liB.p?ho\f%q1)D6D1<f%S^/f%SQl`m2_pTuO+\NPa*"!<7W<JaS*W_X7MOb/Rk?~>
+!quZ5p>u?QeoLqGMoFQLjpU%re_\PK.5;r*.9b,?!<7W4J`_OG_WCs>s7W7=~>
+!i2>Hp?hoYec-#j>)T2i`QcB8^"(C+eHYa0p?qY!ma;(.mX\8e;Lq`u;YKM\3LlloJ,~>
+!m8N2p?ho\e_V(A?&>Dh_T'I$^=(<Td[?N?Ko)tTM8%Ep!<;c\JQ78$JQ:?&p?i$2`l__?~>
+!rqu=p>u?QeT2%DK;?3*e^_p`c2QQ+eP[hF#RD8%.8nT8!<;cTJPq%sJPt,up>uJ%pA^Y5~>
+!h?&@p?hoYeGg'IS6BZKHZNY"Ut+>Heb8G1s8Vcn`U;1Sp?mM3JcC<$f`1[5"#6UA.=_~>
+!liB.p?ho\eD:tdM-4D4H#7+qU!hMWQ+i6GR?b(tKtc$m!<;c\JcC<$JcFC&p?i$.b/Rk?~>
+!quZ5p>u?QdrPS;K7j/fs+:cfk2&ub.1d$r&0N\V>17Nms7YT+s+13$s4IAFjo`U&p8!3~>
+!i2>Hp?hoYdJjU)[&gskhI<"oc1^T'rr_u_`U;4TJaS*WJaUDC"$)mI.=_~>
+!m8N2p?ho\dG>SOTp_pp`a,!lOfjtGTr"HRZG(n(eD:3*JaS*WJaUDC"+A23@=S~>
+!rqu=p>u?QbB"/?X@aoa&/Yrq&/Z6=.8nZ:!<7W4J`_OG_WCsFpA^Y5~>
+!h?&@p?hoYbPq_%XNgJ4qYpZkm_/&<s+0ThmXafCmK52>S1/s~>
+!liB.p?ho\bMEcDFcE]#Y-,(5ZEC49\p_0?h>mS,mXaeWm_\AoH-4-8J,~>
+!quZ5p>u?QbB"2/3@Q'f+;c4<+;bq<0e$;VErc5kk(2ZGk/-6_`W,Y-J,~>
+!i2>Hp?hoYbPqY;[-%,_"8;/rk10K_mXaeWm_\Ao3LlloJ,~>
+!m8N2p?ho\bME<GH*6qR"L>VEH+MS`!<7W<JaS*W_X7MS`l__?~>
+!rqu=p>u?QbB!_o.4P!6!uNI9;V#mhs+0<`k(2[3jo`m%s."T~>
+!h?&@p?hoYb5VP*[-mYf!q*GXf)L<hJaS*W_X7L\Umrla~>
+!liB.p?ho\b2*32FftV]s2+fM"2_3`[b'@9s+0ThmXafCmK7aW`aOA~>
+!quZ5p>u?Qb&[PdpF-7g.3L&g>1[fqs+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoYao;G)XQK6V!p6TXfDgEiJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\akd-.EM^hWc2c#a\cS^Jb1PPNs+0ThmXafCmK7mWb$ff~>
+!rqu=p>u?Qa`@G[r[@q(.5<:K+TEkj@b>`%s+0<`k(2[3jo`m%s."T~>
+!h?&@p?hoYaSu>(XQK6V!R8U8s+0ThmXafCmK52>S1/s~>
+!liB.p?ho\aPIH9D5#8/g;:/$R?`o?[Z-F%h>mS,mXaeWm_\AoH-4-8J,~>
+!quZ5p>u?QaE%>br[A480e!q^&.f*i+=TV/Erc5kk(2ZGk/-6_`W,Y-J,~>
+!i2>Hp?hoYa8Z5'UuqFO!Ucc8s-rHVp&`Kc>+7e\;M2s^p4;Y!mK5J>Ua^f~>
+!m8N2p?ho\a5.<3BpmE3ZEC3mSY;1OWbL,B!<8PV"S2!#I8ub%"&OE_nq$4qmK7mWb$ff~>
+!rqu=p>u?Qa)_A].3L'"rYPhF&.f*a(b+*Y!<8PNs6]s-HW'f.!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E#!"tIHbJk8J``?^"3pQ>S:C~>
+!h?&@p?hoY`r?+sUuqFO!2S6HRdP'`>.sY0me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)BmbY<SSG%O%R-k&2Umrla~>
+!liB.p?ho\`nh01AX1iHWksITToH(XA_>i>s-i@nQ!(]ds6B%;mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcrB+=dAQ/m[3DEH-4-8J,~>
+!quZ5p>u?Q`cDSe.3L>^(b#Fr&-s*i.G/\As-i(fPZ"mNs5rb3mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcN'$>*SH+k*Y95`W,Y-J,~>
+!i2>Hp?hoY`W$"rSDO&@!1_[@S*g@&@cj-Z"nqBXhI=HTm[3DE3LlloJ,~>
+!m8N2p?ho\`SM$/@?IC[cBX*KQ)1<cf\QW.S*gBq@H-jIrrqiUlIo[\JaSon"+A23@=S~>
+!rqu=p>u?Q`H)Gc.3K0=.0onb#S7OrfQ.&mS)sgl>2J\:rrqiQk1*qSJ``?^"3pQ>S:C~>
+!h?&@p?hoY`;]nqPhu9:!S+!ts7Yj]p6;LZ",";Tp6u!amcNrNK7WHXmK52>S1/s~>
+!liB.p?ho\`81m-?&>,Tg:FGXTnR@9h>mTLmK)m<W*'4R[d*:Mrrr8aip*t'JaSon"*r&/@=S~>
+!quZ5p>u?Q`,c;a.2WU50d%;E&0N^[Erc76k$IJ6>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>'mX=m[O4[p?(5o[!RAdR-"Lis7W7=~>
+!i2>Hp?hoY_uBegMr+C3!q)<'fDkR4?BeXUmb[*_k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W@cm+H
+RK!BOmcI](m[3DE3LlloJ,~>
+!m8N2p?ho\_qka'=b2j+Q'n&&?*;i:!<;c\?B&+Ek1\\GhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+?/Fl/Rf<Naio]*#JaSon"+A23@=S~>
+!rqu=p>u?Q_fH/_+;b@q#S77Q+B$j5!<;cT"bU"8k1/>feH"J*eH"J*eH"J*eH"J*eH"J*eH"J*
+eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eH"J*eHOg[
+>2JDuRf<NahWEZuJ``?^"3pQ>S:C~>
+!h?&@p?hoY_Z'nlMnSias36eAf)PI3"'X73k,RhO>41P8RK!BGk3cE(m[3DE0r1<gJ,~>
+!liB.p?ho\_VPR$<H4"`O`af`fA6N-p?i#cdam9Tjo\WGhVst'"5;bs=b6".mK7aW`aOA~>
+!quZ5p>u?Q_K,u\.3Jm-#T+[Mf5grlp?#[bc.1A,hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhW@_u
+hVO\#"4c8b>(Ph'jo`U&p8!3~>
+!i2>Hp?hoY_>a`-XG_^hPh"=ap?l6je_]0Vme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme1,Xk2r*3
+"6SJ.>(Q+/mK5J>Ua^f~>
+!m8N2p?ho\_;5C9I8s*D@B.o8!<;c\?<PS%f'_hklL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*?0:"t
+Rf<NehV.6tJaSon"+A23@=S~>
+!rqu=p>u?Q_/fWd3W1B,;V#mhs7YS]>0Y=BmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNq@k2+XW
+rri&Pe`L%dk*Y95c1_1-J,~>
+!h?&@p?hoYNrSh@"'X7*hQ#uG>418(RK*<D!TmjBm[3DE0r1<gJ,~>
+!liB.p?ho\O59m:p?i#_da$FDl3(DTf%Ttirri2Lf&C+hm[3DEH-4-8J,~>
+!quZ5p>u?QO)k=$p>uHTc,J55joelMe^aA_rri&Ge_XJ\k*Y95`W,Y-J,~>
+!i2>Hp?hoYNrSh@#$TR-hX9h*rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBp_C?FC0r;ZQmgAh'Nj8T)Z
+nc&^Jea@1'm[3DE3LlloJ,~>
+!m8N2p?ho\O59m:p?i#ccI1:Dl3(\Xf%0]rs7lZKs82lWrr<&irri&Hdc+hhm[3DEIE'E<J,~>
+!rqu=p>u?QO)k=$p>uH\`QcZ-jofGUe^aBls7lZKs82lWrr<&irri&Gc/)o\k*Y95c1_1-J,~>
+!h?&@p?hoYNrSh@"Bs@+hWFh*!TrhI!!)0\mJuDKmJuDKmJuDK!!)0\mJuDKmJuDKmJuDKmJuDK
+mJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmK_nBmV:n7hY-gG!!(XN!!(mU!!)Qh
+s4%/4C4Yf?mK52>S1/s~>
+!liB.p?ho\O59m:p?i#_cHb#<k5,/Nk5GA#jofDTcI2:[rr<&Nrr<&Urr<&irri&Ddb\\hm[3DE
+H-4-8J,~>
+!quZ5p>u?QO)k=$p>uZZc,Irak2,7Wk5,,ehWE\WhWE\WhWE\WhYmL>hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE[(hTa=5rr2ulrr2rurr2ul
+rr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr3,ps8N)mrr2ulrr2ulrr2ulrr2ulrr2ul
+rr2ulrr2ulrr3,ps8N)mrr2ulrr2ulrr35ss8Vf;c.-Q[k*Y95`W,Y-J,~>
+!i2>Hp?hoYNrSh@!*]BPqsFFarU0[cp$Me[`9m_Kk1/#Xrr<&frr<&qrr<&irr<&Urr<&irri&P
+e`Lq(m[3DE3LlloJ,~>
+!m8N2p?ho\O59m:p?i#ccHal8jo>D[k5PGSjo>D"k&57rdaIjhs8)cls7u`ls8)cls8)cls8)cl
+s8)clrrE)qs8)clrrE)qs8)cls8)cls8)clrrE)qs8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)clrrE)qs8)cls8)cls8)cls74U`hJIi3R-k')`l__?~>
+!rqu=p>u?QO)k=$p?#ad`QcZihWE\Wh>lEphW=e<hWE\WhWE\WhWE\W!9W/#hWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWAn0c->tUC&do,pAagd
+pAajdpAajdpAajdpAajdpAY-mpAajdpAY-mpAajdpAajdpAajdpAY-mpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAY-mpAajdpAajdpAajdpAaR2c/*2dk*Y95c1_1-J,~>
+!h?&@p?hoYNrSh@"^9I$e`Q<!jp:ATk2u*ojoFiKjoFiKjoFiKjo>D\joFiKjoFiKjoFiKjoFiK
+joFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjp(89F6;$'pA4dh!;lfq!<2uu
+!<3#s!;ulr!<<)t!;ZZp!;c]t!<3$!rVuisrVuisrVufr!ri9#rW)Zl"SUBrhK+89R-k&2Umrla~>
+!liB.p?ho\O59m:p?i#_cH=T4iW&uViW&uOiW&tsiY$7fcI2.WpA4LZpA+dcpA4LZpAP$rpA4I_
+pA4L]!!N/lqY'db!!2rir;[]2pA4LZpA4I_!;cEcpA4LZ!;ZZqpA4LZrW!&spA4L^!!DrkpA4^f
+!qlWfrW!K&qY'dZqY'dZqYKX*cJ!Dlm[3DEH-4-8J,~>
+!quZ5p>u?QO)k=$p>uHT`Pp+!h>dQRh>dQKh>dPoh?7TD`QdQAp&G*ipAP'kp&G*lpAG!hpAP'l
+pAG!epAY-hp&b<g!!)ukrW)ojrW)ojr;Zom!;?Blp@\XWc-=d[J``?^"3(<6Ujr~>
+!i2>Hp?hoYNrSh@"'Wt"ebeJ/!;ts`!9O:D!9WGC!<;3\!<;3\!<2*`!9O:Dk5GA[joGJErW)r[
+r;cl[rW)r[r;c?L"G>jeeb8k>!!)rs%06G.!!*'!!!*$!s8N)qrs/W)rr<'!rr<&ps8E#rs8N'5
+rr<'!rrE*!!!*'!!<<'!!<<'!!<)rt!<<'!!;?Eqp=7^UH\(UPmK5J>Ua^f~>
+!m8N2p?ho\O59m:p?i]!b0&#hhW!DOh>lElhW!Alh>lC4hW"M7!TMu8!!1s9rW!2_hVnOp!92l7
+!!M0<h>lF3!!;$:hYdETinjY7!oDqnr;[SlhW!DOhW!DOhW!DOhW!DOH.pQhmeZVW!;uO"!;?*d
+!;?*d!;6Edp&Os_#QXSl!!)`d!!)igrW)lirr<c,!!)`d!;?*d!;?*dp@\Idp@\IdrV$6ks7QEm
+p\"dem`s,7H%GCNmK7mWb$ff~>
+!rqu=p>u?QO)k=$p>uH\`Pp+!h>dQRh?Eu:!8[_4hYmNThYmNThYmNSh?3i8!8cT3!<1gU!8d\T
+rndSRs5*_TrndSRnD4:pe]lA,qXsmhr:UR"p@\Idp@\Idp&Og[!;cBp!;?*d!;?*d!;Z?f!;uQj
+!#5,,!;?*dp@\Idp@\L[p&G*dp&G*kpAY-mp&G*dp&sg.`SPZek*Y95c1_1-J,~>
+!h?&@p?hoYbl@\C`W,Z"?s:h"e_]HFk2,5#k2,7W!!)-]!8ci<k2$(<k2$*pjoFQ#!!)0<!!)0<
+!8ci<!8ci<!8ci<k2$(<k2,7W!8ci<!8ci<k2,7Wk2,7Wk2,7Wk2,7Wk2,7WHfiT'mf31X!!)uk
+rrE&l!!*#lrW)ul!!)lh!s&&g!<)Tk!;H3d!<2Zl!<2Zo!;6Bmrq6Eop&G*lp&b<gp&P$a!!*#l
+!!)]c"3oBQH\(UPmK52>S1/s~>
+!liB.p?ho\bhi@"`ng^qp?m$&b/V`\hV-i?h>lEdhV%r0h>dQ0h>lEd!!(m0!8?90hV%r0hV%r0
+hV%t`h>dQ0h>dQ0h>lEd!!(m0hV%t`h>dQ0h>lEdhV-i?hV-i?hV-i?hV-i?hV*D3b0K;Gmdff:
+md^AKmdfcG!:oRK!:oRKrW!r/mJu\Gmdff:mJu\G!:oRKmJu\Gmdff:mdff:rW"_Emd^AKmd^AK
+!!)HXmJuYT!:oRK!:oOXmdff:mJu\GmJu\Gmdff:mdff:o'4NGg3J8;R-k'%b/Rk?~>
+!quZ5p>u?Qb]Eda`cD.[p?#j_`Pp*PhUUK5h>lE_hUMT+h>dQ+h>lE_!!(m+!7fp+hUMT+hUMT+
+hUMVVh>dQ+h>dQ+h>lE_!!(m+hUMVVh>dQ+h>lE_hUUK5hUUK5hUUK5hUUK5hUQu'`QdQ=mdB6:
+mJm7dmKr"U!:K";!:K";rW)ud!<D9]mL87GmJuD;!:K";mJuDKmJuDKmK)J<rW)rc!!*#d*!#C,
+!9W_;!9O7]mcNp;mcFN;mcNs*!9W_;!9X:K!9X:K#NkIBk/GTqH\(=Hjo`U&p8!3~>
+!i2>Hp?hoYq>^9kg].9RqZ$HnoDegjiW&W>$!PU(c0!mFhWE\l!)D\5!8ci<!8ckp!8ci<jo>D<
+k2$*pjoFQ#!!)0<joFQ#!8ckp!8ci<k2,7W!!)0<joFQ#!!)0<k2,7Wk2,7Wk2,7Wk2,7Wk)8*H
+ebSn=!<)Wg!<2]l!<2Zn!;?-c!<;`p!;?*drUp9mp@eIcqY'phs7QEmrq6?mpA4gipA4jip&G*j
+p&G*lp&G*ep'(Kae^`f/JaSon"$)mI.=_~>
+!m8N2p?ho\q;1rJgYVr1qVM,MoA9KIina\8p?i#cb0&$,gA:mMg&qE0g&M-Pg'.Q2g&Th,!<1[W
+!8?-,g=cN,rn7GSg=cQ+g&h?/g&V**rrE&P"9@00!!)H@"bk[UcKautmJm7cme["`mf*:dmK*CV
+mf!4dmK3IWmK!4R!W_ZVrW)f_rrE)e!!*#d!<DQb!!)Ha!<;He!;u6b!<2Bd!;Gmbo'4NCg3J8;
+R-k')`l__?~>
+!rqu=p>u?Qq/cB4gN3ApqK)Q7o5jp3ic>,"p>u?Yrl"lorm_&+eb]=XhUMVVh>dQ+hUMVVh>l(+
+!<1Lo!7fU"hUMT+hUU-VhUMVVhUMVVh>l*VhUMT+hUU-VhUMT+hYu%*hYu%*hYu%*hYu%4hUU//
+e]lA$mdB6:mKM_QmdB6*qZ$c]md:&TrpBgfmdC&Ss6^!imd:);rpBgfmdC&Ss6]mLrpC-U!!)HL
+!:K:;!:K^a!:K^a"Qo+PmcON:!!*#d!!*#d!9X:K!9X:K"QmtJeT6<(R-"LqpA^Y5~>
+!h?&@p?hoYqZ$NprVlitg].9Rqu?Zrrr;uuq#C?oh>d3:#$TR%e_]05rn[VTrn[Y*rn[\VhVS,0
+s5!bVeb]=LhUMV_hYR<Qh>dQTh?3i8h>l+*hYR<Qh>l+*!!(RKh>l+*h>l+*h>l+*hAXpshTaU=
+p?qYBp?qVSp?qYB!!)`\p?qYBpAP%ip?hqKp?qYBp?hqKp&OgSp?hqKp?qYBp?qYBp?qYB!:KO\
+p?qVSp&G*\p?qYB!!)`\p?qYB!:KRKp?hqKp?hqKp?qYBp?qYBp?q@ne_YY(m[3DE0r1<gJ,~>
+!liB.p?ho\qVM2OrS@MSgYVr1qqh>QrndYTptl#NhVJ84p?i#_b/Va(ec5^HecGj&f)#IIec>d%
+qZ-ZI!W^g&qZ-ZI!!*#L!s$p'!<(LG!<1RK!:\PCL"a\pk3i-3!!)u_rrDo\rW)u`!!)l\!s%WO
+!<)0_!;,OY!:&hLrosRcl2Uh^lMgk]l2Uh^l2Uh`l2UhYl36V@b0&F`JaSon"*r&/@=S~>
+!quZ5p>u?QqK)W9rGqr=gN3ApqfDc;rcA)>piHH8hK&\sp?!&e`P'78e]lXheH".Ee]lXheH".E
+qZ$`KblH#c!!Lis!6s'k!"I3'!7f?E!7f<oc.1(hqZ$]Be]n'n(<tCSe]lXhe]lXhe]lXhe]i`s
+`Qd9-qrRkYrT=+[qW@bWs5j:]qW7k[k2l[Bjo>DRjoYVGjoGDC!s%H`!;u!Z!;kmY!;tsZ!<2*\
+!;5IV`Qcq[J``?^"3(<6Ujr~>
+!i2>Hp?hoYqu?Zrp](0lrr;uu!ri6#rVufrrr;os!<;utrr;uur;Zcsr;Zcs!<;rs!<;ut!ri6#
+rr;rtrr;uu!ri6#rVufrp]'sT@9Uq+c/."-e_\gVe_\j5e_\gVe_U9+e_\j5e_U;_!!(R+e_\j5
+!8c6+!8c8_e_\gVe_\gVe_U;_e_\gV!8c8_e_\j5e_U9+e_\j5e_\j5e_\j5e_\j5Mr*"/me6AR
+mKE7O!:KR[mJm7dmL8gWmJutK!:KO\mdBfJmL8dhmd:&Tmd:&TmdBfJmM,?pmdBf:!!)`\!:KO\
+!:KO\mdBfJmJm7dmKE7OmJm7dmKiLdmdBcKmdBfJmJut[mKN=Pe]m6'JaSon"$)mI.=_~>
+!m8N2p?ho\qqh>QpYPiKrndYT!o<nWrSIJQrndSR!8dYSrndYTr8.GRr8.GR!8dVR!8dYS!o<nW
+rndVSrndYT!o<nWrSIJQptc#Np?ho`rlSNtdaljtdK%_HdaljtdK%_H!!(Hudaljt!7h,Mdaljt
+daeELdJs9udaljtdK%_HdK%_H!7oTLdJs9udaljtdaljt!!(Hudaljtdaljtdaljtdaj-+cH>;7
+l=f>Fk3D(/k3D*ojoFQ/k3D*o!:&\Hk3;s3k3D*ok3;s3jo>DHjo>DHk3D*ok3;s3k3D(/!:&\H
+k3;pHk3;s3k3D*ojoFQ/k3D*o!!)0Hk3;s3k3;s3k3D*ok3D*ok3hBWb2.Dpm[3DEIE'E<J,~>
+!rqu=p>u?QqfDc;pN-95rcA)>!cn>ArH%o;rcA#<!-A)=rcA)>r,_l<r,_l<!-A&<!-A)=!cn>A
+rcA&=rcA)>!cn>ArH%o;pi?H8p>u?Yrl&'kc.1(hblH#=c.1(hblH#=!!(9oc.1(h!7_&Lc.1(h
+c.)gEbl@aoc.1(hblH#=blH#=!7f?Ebl@aoc.1(hc.1(h!!(9oc.1(hc.1(hc.1(hc..Hsc,KM@
+!!)rZ!!)oY"p!fJ!9WDDqW8%`k2lXDk2lXDqW7bXrT=+[s5jOdk2lXDk2l[@jo>DYk5PG[jo>D\
+jo>DUjot28c,JO\J``?^"3pQ>S:C~>
+!h?&@p?hoYqu?Zrq#C?os8W*!s8W&u%fZM/s8N'!s8N'!s8N'!rr36(s8N'!s8N'!r;Zcsr;Zcs
+!<<#u')qq3rr<'!rr<'!rr<'!!!*'!rW!0&!!*'!!!)Zkp?lEoc-=ehhUUK5h>lE_hUUK5h>lE_
+h>lE_hUUK5!7fp+hUUK5hUMVVhUMVVhUUK5h>lE_h>lE_!!(m+hUMVVhUUK5hUUK5h>lE_hUUK5
+hUUK5hUUK5hUR8@c.27UmdB6:mJm7dmK2P=mem+lmJm7TmJm7T!!*#d#3P@A!!)HTr;Zldk5OcM
+k3h[7!<2Eb!!)0\mem+ek3h[9!!;TNmem+imJuD;mJuDKmJuDKmJuDKmK:_ahLgCIR-k&2Umrla~>
+!liB.p?ho\qqh>Qptl#Ns5*bUs5*_T%c.0chVJ54hVJ54hVJ54rn[n\hVJ54hVJ54r8.GRr8.GR
+!8d\T'&ETgh>dQ4h>dQ4h>dQ4!!(m4rW!/Z!!(m4!!)]K!<;c\?rb@hb0nkhf$`+Lf$`-tf$`+L
+f$`+Lf$`-tf$XQHec=:Lf$`-t!7KHH!7KHHf$`+Lf$`+Lf$XNuf$`-t!7KHHf$`-tf$`+Lf$`-t
+f$`-tf$`-tf$`-tL"a\pk3i-/!!)oYr;[/d!!)0D!!)-]!;kpY!<;3[!;YdS!<2-Z!<)'Y!<2-Z
+!<2-Z!!23^roO1\pZ;YEk0D9+I=^gRmK7aW`aOA~>
+!quZ5p>u?QqfDc;piHH8s)\2?s)\/>%W_UMF)q<]F)q<]F)q<]rc8>FF)q<]F)q<]r,_l<r,_l<
+!-A,>&p"$QErZ2]ErZ2]ErZ2]!!%(]rW!.D!!%(]!!)\5!<;cT"&d+O`V[m[!;aq?!<14C!;k"C
+!6ragqoo*@rlkECqoo*@rlkQGc-64grQP<BpWW[<n]_]!e]#eimb[*_k2,5#k2,7Wk2-%:'BT8p
+hW=e<h>dQ<hWE\Wh>dQ<hYdEZk2,7Wk2,7WqZ$][hWFb:"5`1sk5>8]hWE\n!!;<>k5>8ih>lEp
+h>lEphWE\WhWE\ojo`TIeU)l0R-"Lis7W7=~>
+!i2>Hp?hoYqu?Zrrr;oss8W*!s8W*!s8W*!s8W*!s8W*!s8W*!s8W*!qu?Zrs8W*!r;Zcsr;Zcs
+&H;_1s8N'!rr<'!rr<'!!!*#urr<?)!!*'!!!*'!rW)Wkp?hoarll)4e_\j5eH".Ve_\j5eH".V
+e_^6)"kDH0hUUK]!!_!1!8c8_eboIShUMVVhUMVVhUVQ)!T)B*!!1s,r;[Vie_\j5e_\j5e_\j5
+e_\j5Mr*"7p@cPp!!([>"nq*/e`ML8m[3DE3LlloJ,~>
+!m8N2p?ho\qqh>QrndSRs5*bUs5*bUs5*bUs5*bUs5*bUs5*bUs5*bUqqh>Qs5*bUr8.GRr8.GR
+&DdBehVJ54h>dQ4h>dQ4!!*#Trr<>]!!(m4!!(m4rW)ZK!<;c\!*T<DqpGHEqU,?DrR1WEs3^lI
+rmL`Fs3^lIrR1WEs3^lIrmCcHrmL`Fs3giGs3giGnBqJsg<S"/m`4Gi!8-E;lJg+3hLU7GR-k')
+`l__?~>
+!rqu=p>u?QqfDc;rcA#<s)\2?s)\2?s)\2?s)\2?s)\2?s)\2?s)\2?qfDc;s)\2?r,_l<r,_l<
+&9@gOF)q<]ErZ2]ErZ2]!!*">rr<=G!!%(]!!%(]rW)Y5!<;cT!*]B@qoo*@qTT!?rQY9@s31ND
+rltBAs31NDrQY9@s31NDrlkECrltBAs3:KBs3:KBnBGm(e]lA$mcNBghWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEYphWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\>`SPrmk*Y95c1_1-J,~>
+!h?&@p?hoYqu?Zrr;Zcss8Vrrs8W*!s8W*!s8Vrrs8W*!rr;lrs8W*!r;Zcsr;Zcs&H;_1s8N'!
+rr<'!rr<'!!!*#urr<9'!!*'!!!*#ur;cTlp?hoarlqIn#`IQaeaE.nmcO<F=755=k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"!:K";k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k5OcNc.1[/JaSon"#6UA.=_~>
+!liB.p?ho\qqh>Qr8.GRs5*VQs5*bUs5*bUs5*VQs5*bUrndPQs5*bUr8.GRr8.GR&DdBehVJ54
+h>dQ4h>dQ4!!*#Trr<8[!!(m4!!*#Tr;cWL!<;c\@o^[kb0JG\da$:dda$:dda$:dda$:dda$:d
+da$:dda$:dda$:dda$:dda$:dda$:dda$:dda$:dda$:dda$:dda$:dda$:dda$:dda$:dda$:d
+da$:dM;$+tk3h6kiqWRUk2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PM'k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_roO=*cJ!u'm[3DEH-4-8
+J,~>
+!quZ5p>u?QqfDc;r,_l<s)\&;s)\2?s)\2?s)\&;s)\2?rc@u;s)\2?r,_l<r,_l<&9@gOF)q<]
+ErZ2]ErZ2]!!*">rr<7E!!%(]!!*">r;cV6!<;cT##`FR`QcZHrlkG^rlkG^rlkG^rlkG^rlkG^
+rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^rlkG^
+rlkYdK@RrchX:C"q#CEWrn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[e?
+hVJ7prn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[kAhVQ5reUrG8R-"Lis7W7=~>
+!i2>Hp?hoYqu?Zrr;Zcss8W*!qu?Zrs8W*!s8W*!qu?Zrs8W*!s8W*!s8W*!r;Zcsr;Zcs&H;_1
+s8N'!rr<'!rr<'!!!*#urr<9'!!*'!!!)rsrW)`np?i2ic.1(qe_\j5q#F.>hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hONHQc2?u0k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcQk4\5nc/sq8m[3DE3Lllo
+J,~>
+!m8N2p?ho\qqh>Qr8.GRs5*bUqqh>Qs5*bUs5*bUqqh>Qs5*bUs5*bUs5*bUr8.GRr8.GR&DdBe
+hVJ54h>dQ4h>dQ4!!*#Trr<8[!!(m4!!)rRrW)cN!<;c\!*T<D"P2#Pdan3oJ'uorf$`-tf$`-t
+f$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-t
+f$`-3g<Rk'lK7*gio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_i]6/\
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2P[gcH=jtJaSon
+"+A23@=S~>
+!rqu=p>u?QqfDc;r,_l<s)\2?qfDc;s)\2?s)\2?qfDc;s)\2?s)\2?s)\2?r,_l<r,_l<&9@gO
+F)q<]ErZ2]ErZ2]!!*">rr<7E!!%(]!!)q<rW)b8!<;cT!*]B@s31Vqc-?%a!R90oblH;nblH;n
+blH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;nblH;n
+bllR]e]l)4k%NW6hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\>`SQN(k*Y95
+c1_1-J,~>
+!h?&@p?hoYqZ$Nprr;uus8W&ur;Zcss8W*!s8W&ur;Zcss8W*!s8W*!s8W*!qu?Zrrr;uus8W*!
+!<<#u#QFc(s8N'!s8E!-rr<'!rr<'!rr<'!rrE&urrDiop?i&ec-=ehJ)8`4e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\iHk0;H=mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mQTe$k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k5OcN
+c.1[8JaSon"#6UA.=_~>
+!liB.p?ho\qVM2OrndYTs5*_Tr8.GRs5*bUs5*_Tr8.GRs5*bUs5*bUs5*bUqqh>QrndYTs5*bU
+!8d\T#MoF\hVJ54hYmKah>dQ4h>dQ4h>dQ4h>mQ3rrDlO!<;c\IoXY2cI1:lf$`-tf$`-tf$`-t
+f$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-tf$`-t
+f$`-tf$`-tf$`-tQ/9[/ip,Ocio]7_io]7_io]7_io]7_io]7_io]7_io]7_i_&@mk2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2POg
+lH7E+Ob)qfmK7aW`aOA~>
+!quZ5p>u?QqK)W9rcA)>s)\/>r,_l<s)\2?s)\/>r,_l<s)\2?s)\2?s)\2?qfDc;rcA)>s)\2?
+!-A,>#BKkFF)q<]F8c.KErZ2]ErZ2]ErZ2]Erc2\rrDk9!<;cT!`I"VWQb[4hSmark2,8"h>l^;
+h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;
+h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h>l^;h?`9#hWEt>c..`'k*Y95`W,Y-J,~>
+!i2>Hp?hoYq#C3krVufrs8W*!s8W*!rVufrs8W*!rr;lrs8W*!qZ$Hnrr;lrrr;uu!ri6#rr;rt
+rr;uus8W*!s8Vusp]'sT"'Wt"eZ.I.Uup4XS*gIRma]kMS:U*qmK5J>Ua^f~>
+!m8N2p?ho\ptklJrSIJQs5*bUs5*bUrSIJQs5*bUrndPQs5*bUqVM,MrndPQrndYT!o<nWrndVS
+rndYTs5*bUs5*YRptc#Np?i#cb0&#0ecVW&da"?E"n([$cJFh;m[3DEIE'E<J,~>
+!rqu=p>u?QpiH<4rH%o;s)\2?s)\2?rH%o;s)\2?rc@u;s)\2?qK)Q7rc@u;rcA)>!cn>ArcA&=
+rcA)>s)\2?s)\)<pi?H8p>u?Yrl&'kc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc./?7c-?7M!8d_;
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;#i=_+mcMd=hNWTRR-"LqpA^Y5~>
+!h?&@p?hoY]Dqm2f)PI3"'X7"eZ.I/XQJ'`k+(l>pA`YDhP>_jR-k&2Umrla~>
+!liB.p?ho\]AEPffA6N-p?l6eb0&#\g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/
+g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=G!/g=E+[daDpjlK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolLOMkcJG+Cm[3DEH-4-8J,~>
+!quZ5p>u?Q]6!uPf5grlp?#^[`Pp*He]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]joHc->+8k5XiO
+`Qcr'J``?^"3(<6Ujr~>
+!i2>Hp?hoY]Dqm2f)PI3#$T:%e_]0Frn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;
+rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn[Y;rn_VV[-$5qmdBf:p?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qt\e^a)hJaSon"$)mI.=_~>
+!m8N2p?ho\]AEPffA6N-p?i#cb0J;4g'"_@g=#,Rl37%XdaI-OJaSon"+A23@=S~>
+!rqu=p>u?Q]6!uPf5grlp>uH\`QcZ-eHW,3e]m7=mf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>K
+mf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>K
+mf)>Kmf)>Kmf)AKpA`A<hP>_bR-"LqpA^Y5~>
+!h?&@p?hoYNrSh@"+/;;ec+D*k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;
+k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3?^#n2.k+(l>rr^g.k-T^-
+R-k&2Umrla~>
+!liB.p?ho\O59m:p?i$2b0&#0g'+qEg=G9KS`U+LqU3sSY(?#.mK7aW`aOA~>
+!quZ5p>u?QO)k=$p>uHu`Pp*%eShhOe^`O=hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WpA`CfhQ2:jR-"Lis7W7=~>
+!i2>Hp?hoYNrSh@?G4V6c0!mFhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Wc/.mFrT4+JroO4KroO4K
+roO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4K
+roO4KroO4KroO4KroO4KroO4KroO4KroOIRk5YJDk3fp6m[3DE3LlloJ,~>
+!m8N2p?ho\O59m:p?i$kb0J;4g&o@KinFCkB\qb*ini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oo(LqoijOF+R-k')`l__?~>
+!rqu=p>u?QO)k=$p>u@^rl(nf"3&gIeXPD!me5MfhR%jrR-"LqpA^Y5~>
+!h?&@p?hoYNrSh@VZ1SbhWEtWk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7gk2+(.s.oYp;YKM\0r1<gJ,~>
+!liB.p?ho\O59m:p?ngXDpm@rhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?ip,O[_L_`_rr?'mmK7aW`aOA~>
+!quZ5p>u?QO)k=$p?&7PDp?hhhUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hWE\F]n-3Zrr>sjjo`U&p8!3~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\O59m:p?hq\JaS*WJaV7[!*/a\"+A23@=S~>
+!rqu=p>u?QO)k=$p>uATJ`_OGJ`b\K!)iOQ"3pQ>S:C~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYd/O+.rl##R`P'7(rP\fEhTl/pmK!9<mXaeWmb7(/;YKM\0r1<gJ,~>
+!liB.p?ho\d/O4-_S3b`\d,s\^:M%mZJ*V(p?hq\JaS*WJaV7[!*/a\"*r&/@=S~>
+!quZ5p>u?Qd/O+.rl##R`P'7(rP\fEhTl/pjoGF4k(2ZGk1\qt;YK5T`W,Y-J,~>
+!i2>Hp?hoYdJj:)XS2Sl#kn;ls7ZKdXR=F7p?hq\JaS*WJaV7[!)iOY"$)mI.=_~>
+!m8N2p?ho\dJj:-Wq-/cqXt$fm],Qus7Yj\s+0ThmXaf[mJp8\mK7mWb$ff~>
+!rqu=p>u?QdJj:)XS2Sl#kn;ls7ZKdXR=F7p>uATJ`_OGJ`b\K!)iOQ"3pQ>S:C~>
+!h?&@p?hoYdJj9]XR?&\q<e:6[*SdGmK!9<mXaeWmb7(/;YKM\0r1<gJ,~>
+!liB.p?ho\dJjKdY3PTOo()5:r9=@Gf!`p)p?hq\JaS*WJaV7[!*/a\"*r&/@=S~>
+!quZ5p>u?QdJj9]XR?&\q<e:6[*SdGjoGF4k(2ZGk1\qt;YK5T`W,Y-J,~>
+!i2>Hp?hoYdJj9][-mqe$L[WUmcNs"mcNB5ci<_,!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\dJj9ZY3Q#Ws6fpPs5jIDk2Ostci<_,!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QdJj9][-mqe$L[WUmcNs"mcNB5ci<_$!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYdJj<^XR>NUpAaRZjoaK&e[3[&p?hq\JaS*WJaV7[!)iOY"#6UA.=_~>
+!liB.p?ho\dJjchWp]0?o'Yf.k2tOWg>^\hci<_,!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QdJj<^XR>NUpAaRZjoaK&e[3[&p>uATJ`_OGJ`b\K!)iOQ"3(<6Ujr~>
+!i2>Hp?hoYdJjck[-mYMk3hs2mcNZghWE\%ci<_,!<;ZYqZ+t1!!)oarW(L:!!)rb!!%T<JaV@^
+!)iOY"$)mI.=_~>
+!m8N2p?ho\dJjchY3tl?hWjOolK7*_g>^hlci<_,!<;ZYqZ+t1!!)oarW(L:!!)rb!!%T<JaV@^
+!*/a\"+A23@=S~>
+!rqu=p>u?QdJjck[-mYMk3hs2mcNZghWE\%ci<_$!<;ZQqZ+t)!!)oYrW(L2!!)rZ!!%T4J`beN
+!)iOQ"3pQ>S:C~>
+!h?&@p?hoYdJjck[.a449%E@tk3hBoe`P_qci<_,!<;]ZrrE#c!!(@5!!)oa!!(L9!!%T<JaV.X
+!)iOY"#6UA.=_~>
+!liB.p?ho\dJjchY4D;'7+UYgk2t[[f&GDhci<_,!<;]ZrrE#c!!(@5!!)oa!!(L9!!%T<JaV.X
+!*/a\"*r&/@=S~>
+!quZ5p>u?QdJjck[.a449%E@tk3hBoe`P_qci<_$!<;]RrrE#[!!(@-!!)oY!!(L1!!%T4J`bSH
+!)iOQ"3(<6Ujr~>
+!i2>Hp?hoYdJs6[%efq0C>S[HmcNZghWEt-ci<_,!<;`[rrC1/!!)oa!!(L9!!)3M!!)TX!!%T<
+K'iV:p?i#CS>7Ta~>
+!m8N2p?ho\dJs6X%eBY.A_QS7k2PCSf&G\pci<_,!<;`[rrC1/!!)oa!!(L9!!)3M!!)TX!!%T<
+K'iV=p?i$2`l__?~>
+!rqu=p>u?QdJs6[%efq0C>S[HmcNZghWEt-ci<_$!<;`SrrC1'!!)oY!!(L1!!)3E!!)TP!!%T4
+K'!&2p>uJ%pA^Y5~>
+!h?&@p?hoYdJs6["8;cgk5OfIjoaK.k-WJ7p?hq\p$Me[p[7t[rpBdemf!1dmf!4dmK!=UrVurd
+rW)udr;cib!<DQe!<2Eb!;u9a!<;Kc!<2Bf!:Bjbmem.bmK3IW!!)ucrW)rcr;cib$39M^!:K7T
+md:)CrW)rcr;cc`rW)udrW)rc!!*#dr;Zicr;cib!!%T<N:$[Dp?i#;Umrla~>
+!liB.p?ho\dJjch^@qEok3hO"k2t[[g?R\'ci<_,!<;`[!!)c]r;cib!<DQe!!)Hd!<;Hf!:Kgd
+!:Kgds6fgcrpBdemf!4cmem.`mf!4dmem.bmK*CV!;u9`!<2Bg!:BgerU0XbrpK^brpC*nmd:)C
+mJu\C!:KgdrpK^br9jOas6fjdrpBadrpK^b!:KdcrpBadJaSKb!*/a\"*r&/@=S~>
+!quZ5p>u?QdJs6["8;cgk5OfIjoaK.k-WJ7p>uATp#Z5SpZDDSroO4]k5G>\k5GA\joGJErVur\
+rW)u\r;ciZ!<D9]!<2-Z!;u!Y!<;3[!<2*^!9O:Zk5>;ZjoYVG!!)u[rW)r[r;ciZ$395N!9WDD
+k2l[+rW)r[r;ccXrW)u\rW)r[!!*#\r;Zi[r;ciZ!!%T4N91+<p>uIrs7W7=~>
+!i2>Hp?hoYdJj6\c2%ADpAaj[s6d8?s7Yj\s7Pd[!;Q!^!<;Ke!<;Ke!<;Ke!<;Hp!:K7T!:K7T
+!:K7TqsFpomd:&Tmd:)CmJm7TmK!.P$io_`!!)HT!!)HT!!)oa!!)oarr<An!!)HT!:K7T!;l1#
+!:K7TmJm7TmJu\C!!)HT!:K7T!:K7TqsG*tmd:)CmJm7TmJm7T!:K7Tmd:(+mY1'/;YKM\3Lllo
+J,~>
+!m8N2p?ho\dJj9^b4bi7s8)]fs7-6bk-E>5p?hq\p$Me[q!S.^s6fmes6fmes6fmes6^6pmd:&T
+md:&Tmd:)PmLB6bmJm7TmJu\C!!)HT!;l0m!:K7T!:K7T!:K7T!;l0a!;l3a!"&&n!:K7Tmd:&T
+qsG7#md:)C!!)HT!:K7T!:K7Tmd:&Tmd:)PmLoTgmJu\C!!)HT!!)Eemd:)CmJqh+L$eq@p?i$2
+`l__?~>
+!rqu=p>u?QdJj6\c2%ADpAaj[s6d8?s7YRTs7PLS!;P^V!<;3]!<;3]!<;3]!<;0h!9WDD!9WDD
+!9WDDqrS@gk2lXDk2l[+jo>DDjoG;@$ioGP!!)0D!!)0D!!)oY!!)oYrr<Af!!)0D!9WDD!;kmp
+!9WDDjo>DDjoFQ+!!)0D!9WDD!9WDDqrSOlk2l[+jo>DDjo>DD!9WDDk2lYpk(Vpt;YK5Tc1_1-
+J,~>
+!h?&@p?hoYdJj9ec0##nrV$0h!Tpc8s7Yj\s7Pd[!;Ps^!<)<f!:K7TrpBadrpBjgmd:)SmJm7d
+mJm7amK3IWmK!7S!s%cW!<2Bd!;l0d!:K7TrU'afmd:)Omf*:bmJm7dmK3IW!!*#d!!)oa"T[uY
+!:BjdmK3IWmK!7S!s%cW!<2Bd!;l0d!:BgerpBadrpKacs6^!imd:&TJaS9\!)iOY"#6UA.=_~>
+!liB.p?ho\dJjBacJIjSmf)bYpA4XbrrM8jci<_,!<;`[!!)f^!!)uc!s%cW!<2Bd!<2Bg!:K7T
+rpBadrpBadqsFOdmd:)SmK3IWmK!7S!!)oa!s%cW!<)<f!:K7TqX4@`r9aObrpBjgmJm7dmJm7a
+mKEUYmJuYTrpBjgmd:)SmK3IWmK!7S!!)oa!s%`h!<2Bd!<2Ec!<;Hi!:K7T!.jQmmJp8\mK7aW
+`aOA~>
+!quZ5p>u?QdJj9ec0##nrV$0h!Tpc8s7YRTs7PLS!;P[V!<)$^!9WDDroO1\roO:_k2l[Cjo>D\
+jo>DYjoYVGjoGDC!s%KG!<2*\!;km\!9WDDrT41^k2l[?k5PGZjo>D\joYVG!!*#\!!)oY"T[]I
+!9O:\joYVGjoGDC!s%KG!<2*\!;km\!9O7]roO1\roX1[s5jFak2lXDJ`_^L!)iOQ"3(<6Ujr~>
+!i2>Hp?hoYf)Ga<roP$R[)L#/c.1)$pAaRCk3hZfSDNDjhWEtNs7Yj\s7Pd[!;Ps^!<)<f!:K7T
+rpBadrpBjgmd:)SmJm7dmJm7dmem.cmJm7dmK3IWmK!7S!!)oa!s%cW!<)<f!:K7Tq<n4^rpBad
+rpBdeme["`mem.cmf*:cmK3IWmK!7S!s%cW!<2Bd!;l0b!:K^arpKddrpBadrpKacJaS?^!)iOY
+"$)mI.=_~>
+!m8N2p?ho\fDc]alJgschQF`8b0&#Tipug.io9+_d[AhKrSH*)p?hq\p$Me[q!J+^rU'afmd:)S
+mJm7dmK3IWmK!7S!!*#d!!*#dr;clc!!*#d!s%cW!<2Bd!;l0d!:K7TrU'afmd:)Nmf!4cmJm7d
+mK!=UqZ-W`r;clcrrE#c!s%cW!<2Bg!:K7TrpBadqsFIbme["`mf*:dmJm7dmf!3;mYL92<VGh_
+IE'E<J,~>
+!rqu=p>u?Qf)Ga<roP$R[)L#/c.1)$pAaRCk3hZfSDNDjhWEtNs7YRTs7PLS!;P[V!<)$^!9WDD
+roO1\roO:_k2l[Cjo>D\jo>D\k5>;[jo>D\joYVGjoGDC!!)oY!s%KG!<)$^!9WDDq<%YVroO1\
+roO4]k5,/Xk5>;[k5PG[joYVGjoGDC!s%KG!<2*\!;kmZ!9X.YroX4\roO1\roX1[J`_dN!)iOQ
+"3pQ>S:C~>
+!h?&@p?hoYf`)!GXS_,fhWE\WhVPs6hTb3NqrS%<k2+Xaf)PI3!<;`[rrDl_!!)uc!s%cW!<2Bd
+!<2Bg!:K7TrpBadrpBjgmd:)SmK3IWmK!7S!s%cW!<2Bd!;l0d!:K7TrU'afmd:)Lmf*:emJm7d
+mK3IW!!)oa!!*#d"T[uY!:BjdmK3IWmK!7S!s%cW!<2Bd!;l0d!:BgeqX4=_s6]jer9jRbJaSB_
+!)iOY"#6UA.=_~>
+!liB.p?ho\f`)$DY3,ZA&`2O(iniP+k1[u?k2PCWio]8"h>u3$f)PI3!<;`[rrDl_!!)uc!s%cW
+!<2Bd!<2Bg!:K7TrpBadrpBjgmd:)SmK3IWmK!7S!s%cW!<2Bd!;l0d!:K7TrU'afmd:)Lmf*:e
+mJm7dmK3IW!!)oa!!*#d"T[uY!:BjdmK3IWmK!7S!s%cW!<2Bd!;l0d!:BgeqX4=_s6]jer9jRb
+JaSB_!*/a\"*r&/@=S~>
+!quZ5p>u?Qf`)!GXS_,fhWE\WhVPs6hTb3NqrS%<k2+Xaf)PI+!<;`SrrDlW!!)u[!s%KG!<2*\
+!<2*_!9WDDroO1\roO:_k2l[CjoYVGjoGDC!s%KG!<2*\!;km\!9WDDrT41^k2l[<k5PG]jo>D\
+joYVG!!)oY!!*#\"T[]I!9O:\joYVGjoGDC!s%KG!<2*\!;km\!9O7]qW@bWs5j:]r9""ZJ`_gO
+!)iOQ"3(<6Ujr~>
+!i2>Hp?hoYf`(uZ^&7m2pAb-c"on;YXIRQ7rsJK"k1/o"pAaR;^"<;XmK!:Zmf*:cmL'$_mJm7T
+mJm7TmK!7S!!*#d!s%cW!<2Bd!<2Bg!:K7TrpBjgmd:)SmKWa[mJu\C!!)oa$NTV_!!)HT!!)HT
+!;>gf!:K7Tmd:&Tmd:)PmJm7dmL0*`mJu\C!:K7Tmd:)SmKWa[mJu\C!!)oa!s%cW!;l0g!:K7T
+md:)PmJm6<mYU?3;YKM\3LlloJ,~>
+!m8N2p?ho\f`))[](Z!srUq#tp@@qJii\Qhs8)Tcp?'fkp@@qBf"Tc9p?hq\o^;_ZrU($nmd:&T
+md:&Tmd:)SmJm7dmK3IWmK!7S!!*#d!s%cW!<2Bg!:K7TrpC!kmd:)CmJm7amL'$_mJm7TmJm7T
+mJutK$39M^!:K7T!:K7TqsFFarpC0pmd:)CmJu\C!:K7TrpC!kmd:)CmJm7amK3IWmK!.P"p")Z
+!:K7TqsFFaJaSB_!*/a\"+A23@=S~>
+!rqu=p>u?Qf`(uZ^&7m2pAb-c"on;YXIRQ7rsJK"k1/o"pAaR;^"<;XjoGGRk5PG[jpM1Ojo>DD
+jo>DDjoGDC!!*#\!s%KG!<2*\!<2*_!9WDDroO:_k2l[Cjp(nKjoFQ+!!)oY$NT>O!!)0D!!)0D
+!;>O^!9WDDk2lXDk2l[@jo>D\jpV7PjoFQ+!9WDDk2l[Cjp(nKjoFQ+!!)oY!s%KG!;km_!9WDD
+k2l[@jo>C4k)&4#;YK5Tc1_1-J,~>
+!h?&@p?hoYf`(uB^&@['mK_nBk3hB=Mq.e""7F-uc2R/2joD4/s7Yj\s7>[V!<)?a!<2Bd!<2Bd
+!<2Bg!:K7TrpBadrpBgfmdBrP!U]semJm7dmf*7fmK!.P!!*#dr;cib!!)l`r;cibr;cfar;clc
+qZ$uk!:K7T!:BjTmK!7S!!*#drr<)f!;l3a!<;Kc!"/,o!:K7T!:Bgemem.bmJm6<mYpQ6;YKM\
+0r1<gJ,~>
+!liB.p?ho\f`(uC])D4"mf2PQk3Ds."0.@+pAXUhm_YC3mcrrok+UE,p?hq\oBuMVrU0UarpBad
+rpBadrpBjgmd:)SmJm7dmK*CVmeZtbmK!7S!!*#drr<)f!;l0a!<2Eb!<2Bd!;c-^!<2Eb!<)?a
+!<;Ka!"/,omd:&TmJu\C!<2Bd!<2Ed!!2KfqsOIas6fgc$LRlomd:&TmJm7Tr;cib!!%T<N:$[G
+p?i$.b/Rk?~>
+!quZ5p>u?Qf`(uB^&@['mK_nBk3hB=Mq.e""7F-uc2R/2joD4/s7YRTs7>CN!<)'Y!<2*\!<2*\
+!<2*_!9WDDroO1\roO7^k2uO@!TjC]jo>D\k5PD^joG;@!!*#\r;ciZ!!)lXr;ciZr;cfYr;cl[
+qZ$uc!9WDD!9O:DjoGDC!!*#\rr<)^!;kpY!<;3[!".ig!9WDD!9O7]k5>;Zjo>C4k)AF&;YK5T
+`W,Y-J,~>
+!i2>Hp?hoYf`)&D^%UmnpAaOrk3hBohX7b8c2[5*me4W,V!dC-hX72ks7Yj\s-i?U!8?l@!.jQh
+md'9@;YKM\3LlloJ,~>
+!m8N2p?ho\f`*%e[dr_SmdBB*k2t[_hWh8+cM$\smde5tV<[("hWgfds7Yj\s-i?U!8?l@!.jQh
+md'9@<VGh_IE'E<J,~>
+!rqu=p>u?Qf`)&D^%UmnpAaOrk3hBohX7b8c2[5*me4W,V!dC-hX72ks7YRTs-i'M!8?T8!.j9`
+k3M.0;YK5Tc1_1-J,~>
+!h?&@p?hoYf`)2H^%Um^p?qYQk5X9Mm^.nsp?qABhS%d1`TH%6m\JJ7p?hq\m-aZL\*a4rh<t4A
+JaS*WlL"XMp?i#;Umrla~>
+!liB.p?ho\f`*%a](5.So'Yr.k2P7Og?Pu'cLU8go%(P3Oi$,3g?PB`s7Yj\s6T1L!4V@r!8[)A
+!.jQhmcs3?<VGh_H-4-8J,~>
+!quZ5p>u?Qf`)2H^%Um^p?qYQk5X9Mm^.nsp?qABhS%d1`TH%6m\JJ7p>uATm,n*D\)mYjh<+Y9
+J`_OGlK/(Ep>uIrs7W7=~>
+!i2>Hp?hoYf`*%h^&RfohX8q^mcNB_eb6A7ec5(*p8$7=P^DQLhY*bss7Yj\s+0ThmXaf[mJp/Y
+mK5J>Ua^f~>
+!m8N2p?ho\f`*%e])(jWf':]Kk2P7Of']i+cMHhknt"A.Q$MBCf']6`s7Yj\s+0ThmXaf[mJp8\
+mK7mWb$ff~>
+!rqu=p>u?Qf`*%h^&RfohX8q^mcNB_eb6A7ec5(*p8$7=P^DQLhY*bss7YRTs+0<`k(2[KjoA<Q
+jo`m%s."T~>
+!h?&@p?hoYf`*%``W)`dC3,$amcNZ^eaC,8hZ*<CeWd0'P]PC*hX72ks7Yj\s+0ThmXaf[mJp/Y
+mK52>S1/s~>
+!liB.p?ho\f`*%a_YTgSBlS^\k2P7KddFE+f)"h&cBYR#NHN\#f']6`s7Yj\s+0ThmXaf[mJp8\
+mK7aW`aOA~>
+!quZ5p>u?Qf`*%``W)`dC3,$amcNZ^eaC,8hZ*<CeWd0'P]PC*hX72ks7YRTs+0<`k(2[KjoA<Q
+jo`U&p8!3~>
+!i2>Hp?hoYf`*%hc2WEKC4i>Ek3hBgec3=QhZ*<L^"&X"S@uo(hZ'D's7Yj\s+0ThmXaf[mJp/Y
+mK5J>Ua^f~>
+!m8N2p?ho\f`*%eb5-O7Bn;i3k2tOWf(QD?gAga?]$?RdQ+"QdhY*Yps7Yj\s+0ThmXaf[mJp8\
+mK7mWb$ff~>
+!rqu=p>u?Qf`*%hc2WEKC4i>Ek3hBgec3=QhZ*<L^"&X"S@uo(hZ'D's7YRTs+0<`k(2[KjoA<Q
+jo`m%s."T~>
+!h?&@p?hoYf`))Mec5@*r9jUI'AhmO]q"6bs7Z0:c-=5Xmb[+"Ut>Y?mK!9<mXaeWmb7(/;YKM\
+0r1<gJ,~>
+!liB.p?ho\f`*%ecN!ItlK[g&lK7*_hY+COhZ*<Cm`rht_U@T'k454ts7Yj\s+0ThmXaf[mJp8\
+mK7aW`aOA~>
+!quZ5p>u?Qf`))Mec5@*r9jUI'AhmO]q"6bs7Z0:c-=5Xmb[+"Ut>Y?joGF4k(2ZGk1\qt;YK5T
+`W,Y-J,~>
+!i2>Hp?hoYf`(uRebK.KpAajd]r^AkrrDclrrAkHs7Yj\s+0ThmXaf[mJp/YmK5J>Ua^f~>
+!m8N2p?ho\f`(uKf)5RHqYp0ns0AZ]s8)clrVm&tp@e@ZU"B><mK!9<mXaeWmb7(/<VGh_IE'E<
+J,~>
+!rqu=p>u?Qf`(uRebK.KpAajd]r^AkrrDclrrAkHs7YRTs+0<`k(2[KjoA<Qjo`m%s."T~>
+!h?&@p?hoYf`)/WhVRDWmdC&IrVm8=[+4$qk3h[2pAajbrrAkHs7Yj\s+0ThmXaf[mJp/YmK52>
+S1/s~>
+!liB.p?ho\f`*%if%T-Ck3DC&o(MqVs8TO1f%T-ClK[g*p@e@_s8&G@s7Yj\s+0ThmXaf[mJp8\
+mK7aW`aOA~>
+!quZ5p>u?Qf`)/WhVRDWmdC&IrVm8=[+4$qk3h[2pAajbrrAkHs7YRTs+0<`k(2[KjoA<Qjo`U&
+p8!3~>
+!i2>Hp?hoYf`(uRk5F`JpA4dj]uB.4mf3"WrrAkHs7Yj\s+0ThmXaf[mJp/YmK5J>Ua^f~>
+!m8N2p?ho\f`(rOroOCLmdfrFqY^@#]"[%`k3h[.pA4X`rrAbEs7Yj\s+0ThmXaf[mJp8\mK7mW
+b$ff~>
+!rqu=p>u?Qf`(uRk5F`JpA4dj]uB.4mf3"WrrAkHs7YRTs+0<`k(2[KjoA<Qjo`m%s."T~>
+!h?&@p?hoYf`*%hc,IrHc-=e`e^`O,hVOd(c,IrHc-=e`e^`O,hUSFRs7Yj\s+0ThmXag)mf3"J
+s8VfdmJp/YmK52>S1/s~>
+!liB.p?ho\f`(uKb5TE\b5]cedf7nug(9[P`koa8b0&#TdaH^tg<u\Hs7Yj\s+0ThmXag)mK<%J
+qYKd_s7ucio(DDN<VGh_H-4-8J,~>
+!quZ5p>u?Qf`*%hc,IrHc-=e`e^`O,hVOd(c,IrHc-=e`e^`O,hUSFRs7YRTs+0<`k(2[nk5XlL
+p(%,rs7ZKds7ZKds7ZKds8M`lme5cC;YK5T`W,Y-J,~>
+!i2>Hp?hoYf`(s6o;qu!o;hrBfDkR4!<;c\JPq%sO&>u?qX+CapAY(%k3hC"k3hC"k3hC"k3hC2
+p@dnS;YKM\3LlloJ,~>
+!m8N2p?ho\f`)!3Y4Sao[e$L!f%9rqmK!:\mX\Ah<KC,[k5+NGndbNrqVpYsk2PO_k2PO_k5O?A
+mdfrBmJp8\mK7mWb$ff~>
+!rqu=p>u?Qf`(s6o;qu!o;hrBfDkR,!<;cTJPq%sO&Gf9s6fm[s5!b+r8%G(rn[h/hUUcVme5cC
+;YK5Tc1_1-J,~>
+!h?&@p?hoYNrSh@!<;c\!)eCJJcCi3!9X1H"8:mFp@J=_k4J'A;YKM\0r1<gJ,~>
+!liB.p?ho\NrSh@!<;c\!*+UMJcCi3!9X1H(\6SJlMpn\pA4LZpA4LZpA4LBhVQuGlLsWG<VGh_
+H-4-8J,~>
+!quZ5p>u?QNrSh8!<;cT!)eCJJcCi3qW8%NhVRDps7Ym[p&a[Umf)n\mb[rn!8dD2!)iOQ"3(<6
+Ujr~>
+!i2>Hp?hoYNrSh@!<;c\!)eCJJcCi3!9X1HroO4KoD\garT4+:p?hoYp?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<;c\!*+UMJcCi3!9X1H$/XCqk4\iTqZ$Ekrrr9!qZ$T`r7^l4!*/a\"+A23
+@=S~>
+!rqu=p>u?QNrSh8!<;cT!)eCJJcCi3qW@h.s5!hNs8W)l!rquorq6Enp?qk/p>u?Qp>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<;c\!)eCJ`W#o<JcF!p!9X1H"P)Ykk4\EH"RagshUV>f!)iOY"#6UA.=_~>
+!liB.p?ho\NrSh@!<;c\!*+UM`W#o<JcF!p!9X1H"O>`ThX^=="nps(g=jjGmJp8\mK7aW`aOA~>
+!quZ5p>u?QNrSh8!<;cT!)eCJ`W#o<JcF!pqW8U5e]lY4s7ZKds7ZKds7ZKds6ea_e]l),joA<Q
+jo`U&p8!3~>
+!i2>Hp?hoYNrSh@!<;c\!)eCJ`W#o<JcF!p!9X1H"3oubhYI0Rp8io?rr3,hhVRD>p?hoYp?i#C
+S>7Ta~>
+!m8N2p?ho\NrSh@!<;c\!*+UM`W#o<JcF!p!9X1H"if9If(/\7rsSP+M=U]HqWcY[g;<RO!*/a\
+"+A23@=S~>
+!rqu=p>u?QNrSh8!<;cT!)eCJ`W#o<JcF!pqW8U-e]lA,pAajdpAajdhTbcop@dXnc.0N$joA<Q
+jo`m%s."T~>
+!h?&@p?hoYNrSh@!<;c\!)eCJ`W#o<JcF!p!9X1H"MN[BhX::@"Q#s)k+)GN"SUBrhS&XN!)iOY
+"#6UA.=_~>
+!liB.p?ho\NrSh@!<;c\!*+UM`W#o<JcF!p!9X1H(V8>GddHi*s8)clg7csSV>C5cmaBP;](YOl
+<VGh_H-4-8J,~>
+!quZ5p>u?QNrSh8!<;cT!)eCJ`W#o<JcF!pqW7p^e]#eqqt:HdhY.!"p@dq:`QcZ7p>u?Qp>uIr
+s7W7=~>
+!i2>Hp?hoYNrSh@!<;c\!)idq!!)Bc!W`6#lMgharVllus8E#frr<&irr<&trrN3#!;lcr!;?En
+!<<#unG`Igo)A[ijo5;\JcF!p!9X1H(UW&LeT6t5Me_t![-mYUXO[@NmbZ4F[.`nf;YKM\3Lllo
+J,~>
+!m8N2p?ho\NrSh@!<;c\!*0!t!!)Bc!W`6#lMgharVllus8E#frr<&irr<&trrN3#!;lcr!;?En
+!<<#unG`Igo)A[ijo5;\JcF!p!9X1H(UDW;dZLi@Y)W"dY3PTCV:,56lI*i/Y4h8`<VGh_IE'E<
+J,~>
+!rqu=p>u?QNrSh8!<;cT!)idq!!)Bc!W`6#lMgharVllus8E#frr<&irr<&trrN3#!;lcr!;?En
+!<<#unG`Igo)A[ijo5;\JcF!pqW80ec,IZYme6A2mcNs:s8V3cp?pe^`RUdXjoA<Qjo`m%s."T~>
+!h?&@p?hoYNrSh@!<;c\!)igr!!)Bc!s&B$!:'Ra!<3!#!<<'!hZ!QUrr3'#s8N)grrW9$rrCpU
+!!)-\!!%TMc2Re+qsG8rhTaSK]r[`NK@U#%mdB4ik4\5fc./ohmJp/YmK52>S1/s~>
+!liB.p?ho\NrSh@!<;c\!*0$u!!)Bc!s&B$!:'Ra!<3!#!<<'!hZ!QUrr3'#s8N)grrW9$rrCpU
+!!)-\!!%TMc2Re+qsG8od`0Rdmc)s'NRn.'k2tNWhX9OOb0m!WmJp8\mK7aW`aOA~>
+!quZ5p>u?QNrSh8!<;cT!)igr!!)Bc!s&B$!:'Ra!<3!#!<<'!hZ!QUrr3'#s8N)grrW9$rrCpU
+!!)-\!!%TMc2[Y&"J!`M`TI1"!qtLEr;R#PmcNBF`QaqHjoA<Qjo`U&p8!3~>
+!i2>Hp?hoYNrSh@!<;c\!)igr!!)Bc!s&B$!:'Ra!<3!#!<<'!nc&Rhn,E@frr3'#s8N)grrW9$
+rrDTh!!)Kf!!)Qh!s&B$!;ZWp!.k0prrD3YmJrdVeIu-2XIQ*[s8VNTk08gKk1/#,hOO<-!)iOY
+"$)mI.=_~>
+!m8N2p?ho\NrSh@!<;c\!*0$u!!)Bc!s&B$!:'Ra!<3!#!<<'!nc&Rhn,E@frr3'#s8N)grrW9$
+rrDTh!!)Kf!!)Qh!s&B$!;ZWp!.k0prrD3YmMD/:b0GkDk.[kds8)0KimO*chU9]hdZsOo!*/a\
+"+A23@=S~>
+!rqu=p>u?QNrSh8!<;cT!)igr!!)Bc!s&B$!:'Ra!<3!#!<<'!nc&Rhn,E@frr3'#s8N)grrW9$
+rrDTh!!)Kf!!)Qh!s&B$!;ZWp!.k0ps8(j`Pg.1dk5YJThY[<Yp>4?fe]#5HMtZ95;YK5Tc1_1-
+J,~>
+!h?&@p?hoYNrSh@!<;c\!)igr!s&B$!<3!"!<<)t!<3!(!<3'!rrE*!!<3#s!<)rr!!*&t!<2uu
+!<3!!!<<#us8W&urr;oss8W&u"TJK%!!*#u!<E/u!<2uu!<3!&!<<'!rr<&urr`?%rrE)u!<3!!
+!<<#us8W&urr;oss8W&u"TJK%!!*#u!<E/u!<2uu!:p0e!!*&t!<<'!!.k0prrD3YmK\[,c.-"B
+SAkC*$%#9R6"3.)c./'PmJp/YmK52>S1/s~>
+!liB.p?ho\NrSh@!<;c\!*0$u!s&B$!<3!"!<<)t!<3!(!<3'!rrE*!!<3#s!<)rr!!*&t!<2uu
+!<3!!!<<#us8W&urr;oss8W&u"TJK%!!*#u!<E/u!<2uu!<3!&!<<'!rr<&urr`?%rrE)u!<3!!
+!<<#us8W&urr;oss8W&u"TJK%!!*#u!<E/u!<2uu!:p0e!!*&t!<<'!!.k0prrD3YmK\Ts`m0G@
+]#O^K$i9R^EJ\C\=j"b0NV;c?<VGh_H-4-8J,~>
+!quZ5p>u?QNrSh8!<;cT!)igr!s&B$!<3!"!<<)t!<3!(!<3'!rrE*!!<3#s!<)rr!!*&t!<2uu
+!<3!!!<<#us8W&urr;oss8W&u"TJK%!!*#u!<E/u!<2uu!<3!&!<<'!rr<&urr`?%rrE)u!<3!!
+!<<#us8W&urr;oss8W&u"TJK%!!*#u!<E/u!<2uu!:p0e!!*&t!<<'!!.k0ps8(j_K?_*Kk5Xl3
+qu6f]hX8qNrP\bhp>u?Qp>uIrs7W7=~>
+!i2>Hp?hoYi;`fWg&M'Pg].!8!<;c\!)igr!s&B$!<3!#!<<'!qu?Zrrr3K/s8N*!rr<'!rr<'!
+rr<&prrW9$rrE&u%06G.!<<'!s8N'!s8N)rrrrK'rrE*!!<2uu!;uj!!<<'!rr3Q1s8N'!rr<'!
+rrE*!!!*'!!<3!-!<<'!s8N*!rr<'!rrDrr"p"]'!<<'!rr2rur;Qj!s8N)hrrrK'rrE*!!;uis
+!.k0prrD3YmMCf3c-9/2P]N(RMi33k3Ee^@+>MEkhLkOi!)iOY"$)mI.=_~>
+!m8N2p?ho\i;`fWg&M'Pg].!8!<;c\!*0$u!s&B$!<3!#!<<'!qu?Zrrr3K/s8N*!rr<'!rr<'!
+rr<&prrW9$rrE&u%06G.!<<'!s8N'!s8N)rrrrK'rrE*!!<2uu!;uj!!<<'!rr3Q1s8N'!rr<'!
+rrE*!!!*'!!<3!-!<<'!s8N*!rr<'!rrDrr"p"]'!<<'!rr2rur;Qj!s8N)hrrrK'rrE*!!;uis
+!.k0prrD3YmMCT*`la#8^6,_(WhlD;Bpk*O>suuXdXh,[!*/a\"+A23@=S~>
+!rqu=p>u?Qi;`fWg&M'Pg].!0!<;cT!)igr!s&B$!<3!#!<<'!qu?Zrrr3K/s8N*!rr<'!rr<'!
+rr<&prrW9$rrE&u%06G.!<<'!s8N'!s8N)rrrrK'rrE*!!<2uu!;uj!!<<'!rr3Q1s8N'!rr<'!
+rrE*!!!*'!!<3!-!<<'!s8N*!rr<'!rrDrr"p"]'!<<'!rr2rur;Qj!s8N)hrrrK'rrE*!!;uis
+!.k0ps8(j`K?_BSk5Y/;pAXI]k2+torrqi0`P'NCp>u?Qp>uJ%pA^Y5~>
+!h?&@p?hoYr;Zcsrr;uurr;uunc/UhqZ$Emk5YG]oDegjli6\H!<;c\"&f1!!<2uu!<3!$!<<'!
+!;uis!<2uu!<3!#!<<'!rVls"s8N)orrrK'rrE*!!<3!#!<3$!rr3*$s8N'!r;R''s8N*!rrE*!
+!;ld#!<<'!s8N)urr<&urrrK'rrE*!!<3!#!<<'!rr3'#rr<&urr`?%rr<&srs8]*rrE*!!<<'!
+qu6`us8N)hrs&Q(rrE*!!!)ut!!%TMc2Re+qsG8IhSm`;eP]kXUm-LQC2,a`+960$c..17mJp/Y
+mK52>S1/s~>
+!liB.p?ho\r;Zcsrr;uurr;uunc/UhqZ$Emk5YG]oDegjli6\H!<;c\"',C$!<2uu!<3!$!<<'!
+!;uis!<2uu!<3!#!<<'!rVls"s8N)orrrK'rrE*!!<3!#!<3$!rr3*$s8N'!r;R''s8N*!rrE*!
+!;ld#!<<'!s8N)urr<&urrrK'rrE*!!<3!#!<<'!rr3'#rr<&urr`?%rr<&srs8]*rrE*!!<<'!
+qu6`us8N)hrs&Q(rrE*!!!)ut!!%TMc2Re+qsG8Cd_a.\s,i;\`kJaTRAGUg=Vu/$`m/l'mJp8\
+mK7aW`aOA~>
+!quZ5p>u?Qr;Zcsrr;uurr;uunc/UhqZ$Emk5YG]oDegjli6\@!<;cT"&f1!!<2uu!<3!$!<<'!
+!;uis!<2uu!<3!#!<<'!rVls"s8N)orrrK'rrE*!!<3!#!<3$!rr3*$s8N'!r;R''s8N*!rrE*!
+!;ld#!<<'!s8N)urr<&urrrK'rrE*!!<3!#!<<'!rr3'#rr<&urr`?%rr<&srs8]*rrE*!!<<'!
+qu6`us8N)hrs&Q(rrE*!!!)ut!!%TMc2[Y&#BS/'`TI3gk5PA^pAajcrs%o1`P&t(F8"_r;YK5T
+`W,Y-J,~>
+!i2>Hp?hoYqu6Wrrr;uurr2runGiLgqu?ZrrVlitk5YG]p](6nkPt8D!<;c\"&f1!!<2uu!<2uu
+!<3#t!<2uu!<2uu!<3!#!<<'!rVls"s8N)rs8;rtrrW9$rrE&u!<E/s!<3#t!<3!)!<<'!s8N'!
+rrE&ur;clt!s&B$!<2uu!<3!&!<<'!s8N)urrW9$rrE&u!<E/s!<3#t!<3!)!<<'!s8N'!rrE&u
+r;clt!!)orrW)uurW)uu!s&B$!<3#t!<<'!!.k0prrD3YmMBrpc-8l"3Sr<CXFj\B+;bA$&<t_i
+hK/DY!)iOY"$)mI.=_~>
+!m8N2p?ho\qu6Wrrr;uurr2runGiLgqu?ZrrVlitk5YG]p](6nkPt8D!<;c\"',C$!<2uu!<2uu
+!<3#t!<2uu!<2uu!<3!#!<<'!rVls"s8N)rs8;rtrrW9$rrE&u!<E/s!<3#t!<3!)!<<'!s8N'!
+rrE&ur;clt!s&B$!<2uu!<3!&!<<'!s8N)urrW9$rrE&u!<E/s!<3#t!<3!)!<<'!s8N'!rrE&u
+r;clt!!)orrW)uurW)uu!s&B$!<3#t!<<'!!.k0prrD3YmMBlk`l`l+EUMuhhR],+AP=?l*1b6l
+dV\^G!*/a\"+A23@=S~>
+!rqu=p>u?Qqu6Wrrr;uurr2runGiLgqu?ZrrVlitk5YG]p](6nkPt8<!<;cT"&f1!!<2uu!<2uu
+!<3#t!<2uu!<2uu!<3!#!<<'!rVls"s8N)rs8;rtrrW9$rrE&u!<E/s!<3#t!<3!)!<<'!s8N'!
+rrE&ur;clt!s&B$!<2uu!<3!&!<<'!s8N)urrW9$rrE&u!<E/s!<3#t!<3!)!<<'!s8N'!rrE&u
+r;clt!!)orrW)uurW)uu!s&B$!<3#t!<<'!!.k0ps8(jXCAu0RhZ)I/rsAD]c,IB8`P'N2p>u?Q
+p>uJ%pA^Y5~>
+!h?&@p?hoYqu?Zrs8W&us8N'!rr;rtrr;os!<;rsr;Zcsq>^Eorr;`nrr;lrs8W*!rr;oss8W#t
+!ri6#rr;rtrr;uu!ri6#q>^0V!<;c\"&f1!!<2uu!<2uu!;uls!<<'!!<2uu!<3!#!<<'!rVls"
+s8N)srr<&urrrK'rrE*!!<3!#!<3$!q#C?os8N0$s8N)urriE&!<<'!rr30&s8N*!rrE&u!!*#u
+"p"]'!<<'!rr3'#s8N)urrW9$!!)forrE*!!s&B$!<3!%!<3'!rrE&u!s&B$!:g'k!<<'!r;Zcs
+!WN.Ns3:QDk54Q_@c#)K;M/`HXH[cu0c1/r!#R/uc-=dRp?hoYp?i#;Umrla~>
+!liB.p?ho\qu?Zrs8W&us8N'!rr;rtrr;os!<;rsr;Zcsq>^Eorr;`nrr;lrs8W*!rr;oss8W#t
+!ri6#rr;rtrr;uu!ri6#q>^0V!<;c\"',C$!<2uu!<2uu!;uls!<<'!!<2uu!<3!#!<<'!rVls"
+s8N)srr<&urrrK'rrE*!!<3!#!<3$!q#C?os8N0$s8N)urriE&!<<'!rr30&s8N*!rrE&u!!*#u
+"p"]'!<<'!rr3'#s8N)urrW9$!!)forrE*!!s&B$!<3!%!<3'!rrE&u!s&B$!:g'k!<<'!r;Zcs
+!WN.Ns3:QDk54Q_A^\H<Ku/uPg;^:PD,;o+(aM)T`l?G<p?ho\p?i$.b/Rk?~>
+!quZ5p>u?Qqu?Zrs8W&us8N'!rr;rtrr;os!<;rsr;Zcsq>^Eorr;`nrr;lrs8W*!rr;oss8W#t
+!ri6#rr;rtrr;uu!ri6#q>^0N!<;cT"&f1!!<2uu!<2uu!;uls!<<'!!<2uu!<3!#!<<'!rVls"
+s8N)srr<&urrrK'rrE*!!<3!#!<3$!q#C?os8N0$s8N)urriE&!<<'!rr30&s8N*!rrE&u!!*#u
+"p"]'!<<'!rr3'#s8N)urrW9$!!)forrE*!!s&B$!<3!%!<3'!rrE&u!s&B$!:g'k!<<'!r;Zcs
+!WN.Ns3:T?jp#;>]uB.-med"kmcMd5`P'O0]u=ISjoA<Qjo`U&p8!3~>
+!i2>Hp?hoYqu?Zrs8W&u%K?D.s8N'!rr<'!rr<&us8N'#rr<&ss8N)qs8N'%rr<'!s8Duus8E!$
+rr<'!s8E!>rr<'!!!*'!!!*'!!!*'!!!*'!!!*'!!!*$!!<<)u!!<0#!;c`hmK!:\mK-;d!<)p#
+!<<'!!;ld#!<<'!s8N)trsSo-rr<'!rr<'!rr<&trr<&urriE&rrE'!rVls"s8N)nrrrK'rrE*!
+!<3#u!<2uu!<3!%!<<'!rrE#t$3:,+!!*'!!<<'!rr3$"rrE#t!s&B$!;HKt!<<'!s8N)us8N)u
+rr<&urrW9$rrDTh!s&B$!;lct!<3%Ms3:QDk54QU@b&`J;Hfm0K5+R^.1#nQ"pe,`e]lr[p?hoY
+p?i#CS>7Ta~>
+!m8N2p?ho\qu?Zrs8W&u%K?D.s8N'!rr<'!rr<&us8N'#rr<&ss8N)qs8N'%rr<'!s8Duus8E!$
+rr<'!s8E!>rr<'!!!*'!!!*'!!!*'!!!*'!!!*'!!!*$!!<<)u!!<0#!;c`hmK!:\mK-Dg!<)p#
+!<<'!!;ld#!<<'!s8N)trsSo-rr<'!rr<'!rr<&trr<&urriE&rrE'!rVls"s8N)nrrrK'rrE*!
+!<3#u!<2uu!<3!%!<<'!rrE#t$3:,+!!*'!!<<'!rr3$"rrE#t!s&B$!;HKt!<<'!s8N)us8N)u
+rr<&urrW9$rrDTh!s&B$!;lct!<3%Ms3:QDk54Q_@FE0<Kos7?cD@(cANV@d(_g-(b/Vk8p?ho\
+p?i$2`l__?~>
+!rqu=p>u?Qqu?Zrs8W&u%K?D.s8N'!rr<'!rr<&us8N'#rr<&ss8N)qs8N'%rr<'!s8Duus8E!$
+rr<'!s8E!>rr<'!!!*'!!!*'!!!*'!!!*'!!!*'!!!*$!!<<)u!!<0#!;c`hjoGGTjoSH\!<)p#
+!<<'!!;ld#!<<'!s8N)trsSo-rr<'!rr<'!rr<&trr<&urriE&rrE'!rVls"s8N)nrrrK'rrE*!
+!<3#u!<2uu!<3!%!<<'!rrE#t$3:,+!!*'!!<<'!rr3$"rrE#t!s&B$!;HKt!<<'!s8N)us8N)u
+rr<&urrW9$rrDTh!s&B$!;lct!<3%Ms3:T?jp##6`P(-jpAFpup?pefc+Ug8`P'N"p>u?Qp>uJ%
+pA^Y5~>
+!h?&@p?hoYqu?Zr!<;ut"oeQ&rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'Irr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!!!*'!!!*'!!!*'!!!*$!!<3#u!!`H'!<<'!!;c`hmK!:\mK-;d!<)rs
+!!E6$s8W#trr3'#s8N)trr<&us8;rrs8;ots8)currE'!rVlitrr;oss8W#trr;uu!WN0!s8N)u
+s8)currE'!rVufrrr3'#s8N)urrN3#!<)ot!<3#s!<<)t!<3#u!!3*"rr;uurr;iq!WN/is8N'$
+rr<'!r;clt!!%TMc2Re+qsG7uhTa;*;SC>^S;V_t5s[Lk(j"QYc.-"kmJp/YmK52>S1/s~>
+!liB.p?ho\qu?Zr!<;ut"oeQ&rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'Irr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!!!*'!!!*'!!!*'!!!*$!!<3#u!!`H'!<<'!!;c`hmK!:\mK-Dg!<)rs
+!!E6$s8W#trr3'#s8N)trr<&us8;rrs8;ots8)currE'!rVlitrr;oss8W#trr;uu!WN0!s8N)u
+s8)currE'!rVufrrr3'#s8N)urrN3#!<)ot!<3#s!<<)t!<3#u!!3*"rr;uurr;iq!WN/is8N'$
+rr<'!r;clt!!%TMc2Re+qsG8#d`0FDM;%CS_QokdBjk"4/:H6pb0j;`mJp8\mK7aW`aOA~>
+!quZ5p>u?Qqu?Zr!<;ut"oeQ&rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'Irr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!!!*'!!!*'!!!*'!!!*$!!<3#u!!`H'!<<'!!;c`hjoGGTjoSH\!<)rs
+!!E6$s8W#trr3'#s8N)trr<&us8;rrs8;ots8)currE'!rVlitrr;oss8W#trr;uu!WN0!s8N)u
+s8)currE'!rVufrrr3'#s8N)urrN3#!<)ot!<3#s!<<)t!<3#u!!3*"rr;uurr;iq!WN/is8N'$
+rr<'!r;clt!!%TMc2[Y&"]EUY`STbTrs\Vhk2t4=]uAO8`Q_<SjoA<Qjo`U&p8!3~>
+!i2>Hp?hoYqYpp'rrE*!!<3'!rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'8rr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!qZ-ZrrrE*!rr<-#!!*#urr<9'!!*'!!!)lqp?hq\p?hu[rrDEc!!)'Z
+!!(XN!!)Ed!!'\3!!%TMc2Re+qsFVchUU-fF8c+JmcNBV`P&WEXPVLXhGX(8!)iOY"$)mI.=_~>
+!m8N2p?ho\qYpp'rrE*!!<3'!rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'8rr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!qZ-ZrrrE*!rr<-#!!*#urr<9'!!*'!!!)lqp?hq\p?hu^rrDEc!!)'Z
+!!(XN!!)Ed!!'\3!!%TMc2Re+qsFVaf$;E'RK!3rp?LYgd_`T$<MeEpb1]P_mJp8\mK7mWb$ff~>
+!rqu=p>u?QqYpp'rrE*!!<3'!rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'8rr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!qZ-ZrrrE*!rr<-#!!*#urr<9'!!*'!!!)lqp>uATp>uESrrDEc!!)'Z
+!!(XN!!)Ed!!'\3!!%TMc2[Y&"\R%Y`QdiLs8VfmmK;V.e]%O4!l`\^p>u?Qp>uJ%pA^Y5~>
+!h?&@p?hoYqZ$Nps8W&us8W*!rr;uu$NC)+s8N'!s8N'!r;Zcsqu?Zrrr;uu)?0[:s8N'!s8N'!
+s8N'!s8N'!rr<'!rr<&rs8N*!s8N'#rr<&us8N''rr<'!rr<&qs7Yj\s7Yj\;M"kerr<%Ms3:QD
+k54QM6/L/B&@DB8%.<9.`P&W5hWEA=hFdM0!)iOY"#6UA.=_~>
+!liB.p?ho\qZ$Nps8W&us8W*!rr;uu$NC)+s8N'!s8N'!r;Zcsqu?Zrrr;uu)?0[:s8N'!s8N'!
+s8N'!s8N'!rr<'!rr<&rs8N*!s8N'#rr<&us8N''rr<'!rr<&qs7Yj\s7Yj\<It1hrr<%Ms3:QD
+k54QM7,#r34N@@"%JoADb/1He5h=Z7dagh[mJp8\mK7aW`aOA~>
+!quZ5p>u?QqZ$Nps8W&us8W*!rr;uu$NC)+s8N'!s8N'!r;Zcsqu?Zrrr;uu)?0[:s8N'!s8N'!
+s8N'!s8N'!rr<'!rr<&rs8N*!s8N'#rr<&us8N''rr<'!rr<&qs7YRTs7YRT;M"kerr<%Ms3:T?
+jon&q`Pp*qr;R3!mcNBVe\0M``QcXnp>u?Qp>uIrs7W7=~>
+!i2>Hp?hoYqZ$Nps8W&us8W&u$i^2,s8N'!s8N'!s8E#qs8N)ts8;p2rr<'!rr<'!rr<'!rr<'!
+rr<'!rW!*$!!*'!rW)lrrrE*!rr<'!rW!<*!!*'!!!*'!!!)lqp?hq\p?hoYJcE^h!!%TMc2Re+
+qsFVcc/-tV3W25Q3ADs3+<V5!mcNB_eOoQ'!)iOY"$)mI.=_~>
+!m8N2p?ho\qZ$Nps8W&us8W&u$i^2,s8N'!s8N'!s8E#qs8N)ts8;p2rr<'!rr<'!rr<'!rr<'!
+rr<'!rW!*$!!*'!rW)lrrrE*!rr<'!rW!<*!!*'!!!*'!!!)lqp?hq\p?ho\JcE^h!!%TMc2Re+
+qsG7ob1>!#Bl.^$AR/G483f9k@H-.pf$6\WmJp8\mK7mWb$ff~>
+!rqu=p>u?QqZ$Nps8W&us8W&u$i^2,s8N'!s8N'!s8E#qs8N)ts8;p2rr<'!rr<'!rr<'!rr<'!
+rr<'!rW!*$!!*'!rW)lrrrE*!rr<'!rW!<*!!*'!!!*'!!!)lqp>uATp>u?QJcE^h!!%TMc2[Y&
+(J;Zk`P'gPhUU0$c+Uft[&gste]l@X62'F@;YK5Tc1_1-J,~>
+!h?&@p?hoYqZ$Qqrr;uur;Z`rrr;uurr;lrqZ$Ems8W&urr;uus8W*!s8W*!s8Vuss8W*!rVufr
+rr;uu!ri6#rr;rtrr;uus8W*!qZ$9W!<;c\!)eCJJcCi3!9X1H(Ljc.hUUK>k2,7Wk2,7Wk2,7g
+mbZg-;YKMY;YKM\0r1<gJ,~>
+!liB.p?ho\qZ$Qqrr;uur;Z`rrr;uurr;lrqZ$Ems8W&urr;uus8W*!s8W*!s8Vuss8W*!rVufr
+rr;uu!ri6#rr;rtrr;uus8W*!qZ$9W!<;c\!*+UMJcCi3!9X1H(LaJtf$`:+hV-i?hV-i?hV-iO
+k1\Ol;"j;W<VGh_H-4-8J,~>
+!quZ5p>u?QqZ$Qqrr;uur;Z`rrr;uurr;lrqZ$Ems8W&urr;uus8W*!s8W*!s8Vuss8W*!rVufr
+rr;uu!ri6#rr;rtrr;uus8W*!qZ$9O!<;cT!)eCJJcCi3qW7f^V#JU@e]lXhrm_(pe]n*Ds5!k&
+eYH+:joA<Qjo`U&p8!3~>
+!i2>Hp?hoY^&S*4eGo71!<;c\J`_OGNop6,#)cC0hWE\_roO:Mk3i62#O^aSp?pI/@eT3i;YKM\
+3LlloJ,~>
+!m8N2p?ho\^&S*4eGo71!<;c\J`_OGNop6,(PPQ.f%S^7hW!DOhW!DOhW!D_mc)Yk@J9*h<VGh_
+IE'E<J,~>
+!rqu=p>u?Q^&S*4eGo7)!<7W4J`_OGrT4oK9#]'*c/."-e_\j5e_\j5eaDSVbu.a=joA<Qjo`m%
+s."T~>
+!h?&@p?hoY^&S*4eGo71!<7W<JaS*Wr9aZ.6*/?'h?E?(Zq=6ip?hoYp?i#;Umrla~>
+!liB.p?ho\^&S*4eGo71!<7W<JaS*Wr9b>?7&A&[f%S^/f%S^/f%S^/lIrC3<V#kO!*/a\"*r&/
+@=S~>
+!quZ5p>u?Q^&S*4eGo7)!<7W4J`_OGr8nc96);KMc.1(hc.1(hc.1(hk1-7n;XX8@!)iOQ"3(<6
+Ujr~>
+!i2>Hp?hoYNrSh@!<7W<JaS*WrU0^Z'oP[E.5<8+.5<8+.5<8+.5<PC@eTNhmJp/YmK5J>Ua^f~>
+!m8N2p?ho\NrSh@!<7W<JaS*WrU(HlmY+1g-nHbt-nHbt-nHbt-nI&;@Ij*Z!*/a\"+A23@=S~>
+!rqu=p>u?QNrSh8!<7W4J`_OGrT=.J!eX*"o-jes6!E^Ep>u?Qp>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;ZYqZ-Za!!':l!s%cW!.jQhm`"So;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;ZYqZ-Za!!':l!s%cW!.jQhm`"So<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;ZQqZ-ZY!!':d!s%KG!.j9`k/HH_;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;]ZrrE#c!s%cW!3tql!.jQhm_\Al;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;]ZrrE#c!s%cW!3tql!.jQhm_\Al<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;]RrrE#[!s%KG!3tYd!.j9`k/-6\;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;`[rrDl_!!)'I!!(C6!!%T<JaUDC!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;`[rrDl_!!)'I!!(C6!!%T<JaUDC!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;`SrrDlW!!)'A!!(C.!!%T4J`ai3!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;`[!!)f^!<DQe!<;Kc!<2Bg!:BjTr;cfaq>gQ`rW)rc!W_WgqsOF`rpBde
+mf!4cmem.cmem.amem.cmK<OXmJu\S!<2Eb!<;He!.jQhmage+;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;`[!!)f^!<DQe!<;Kc!<2Bg!:BjTr;cfaq>gQ`rW)rc!W_WgqsOF`rpBde
+mf!4cmem.cmem.amem.cmK<OXmJu\S!<2Eb!<;He!.jQhmage+<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;`S!!)fV!<D9]!<;3[!<2*_!9O:Dr;cfYq>gQXrW)r[!W_?_qr[kXroO4]
+k5GA[k5>;[k5>;Yk5>;[job\HjoFQC!<2-Z!<;0]!.j9`k18Yp;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;`[!!)f^rrE)e!!)oa"9@lX!!)oa"9@lX!!)uc$NTV_!:K7T!:K7T!;l0p
+!:K7T!:K7T!:K7Tmd:&TrU0[cs6fmes6fmes6^I!md:)CmJm7TmJu\C!!)HT!.jQhmaLS(;YKM\
+0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;`[!!)f^rrE)e!!)oa"9@lX!!)oa"9@lX!!)uc$NTV_!:K7T!:K7T!;l0p
+!:K7T!:K7T!:K7Tmd:&TrU0[cs6fmes6fmes6^I!md:)CmJm7TmJu\C!!)HT!.jQhmaLS(<VGh_
+H-4-8J,~>
+!rqu=p>u?QNrSh8!<;`S!!)fVrrE)]!!)oY"9@TH!!)oY"9@TH!!)u[$NT>O!9WDD!9WDD!;kmh
+!9WDD!9WDD!9WDDk2lXDrT=+[s5s=]s5s=]s5jmnk2l[+jo>DDjoFQ+!!)0D!.j9`k0rGm;YK5T
+`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;`[!!)f^!!*#d!!)oa!s%cW!;c*c!:K7Tr9aXemJm7dmK3IWmK!.PrrE&d
+!s%cW!<2Bg!:K7Tr9aObrU'afmd:)SmKN[ZmJu\C!<2Bg!:K7TrpBadJaS*We*[36p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;`[!!)f^!!*#d!!)oa!s%cW!;c*c!:K7Tr9aXemJm7dmK3IWmK!.PrrE&d
+!s%cW!<2Bg!:K7Tr9aObrU'afmd:)SmKN[ZmJu\C!<2Bg!:K7TrpBadJaS*We*[39p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;`S!!)fV!!*#\!!)oY!s%KG!;bg[!9WDDr8n(]jo>D\joYVGjoG;@rrE&\
+!s%KG!<2*_!9WDDr8mtZrT41^k2l[CjothJjoFQ+!<2*_!9WDDroO1\J`_OGe)gX.p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;`[!!)f^!!*#d!!*#dr;clc!!)ucr;clc!!)rb!<DQb!<;He!;l3]!<;He
+!<2Bg!:K7Tr9aObrU'afmd:)SmKN[ZmJu\C!<2Bg!:K7TrpBadJaS*We*[36p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;`[!!)f^!!*#d!!*#dr;clc!!)ucr;clc!!)rb!<DQb!<;He!;l3]!<;He
+!<2Bg!:K7Tr9aObrU'afmd:)SmKN[ZmJu\C!<2Bg!:K7TrpBadJaS*We*[39p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<;`S!!)fV!!*#\!!*#\r;cl[!!)u[r;cl[!!)rZ!<D9Z!<;0]!;kpU!<;0]
+!<2*_!9WDDr8mtZrT41^k2l[CjothJjoFQ+!<2*_!9WDDroO1\J`_OGe)gX.p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;`[rrDl_!!*#d!s%cW!<2Bg!:K7TrpBadrpBjgmd:)QmK3IW!!)oa!!)oa
+rrDra!!*#d!s%cW!;u6b!<)<f!:K7TrpBsjmd:)CmK!7S!s%cW!<2Bd!.jQhmaLS(;YKM\3Lllo
+J,~>
+!liB.p?ho\NrSh@!<;`[rrDl_!!*#d!s%cW!<2Bg!:K7TrpBadrpBjgmd:)QmK3IW!!)oa!!)oa
+rrDra!!*#d!s%cW!;u6b!<)<f!:K7TrpBsjmd:)CmK!7S!s%cW!<2Bd!.jQhmaLS(<VGh_IE'E<
+J,~>
+!quZ5p>u?QNrSh8!<;`SrrDlW!!*#\!s%KG!<2*_!9WDDroO1\roO:_k2l[AjoYVG!!)oY!!)oY
+rrDrY!!*#\!s%KG!;tsZ!<)$^!9WDDroOCbk2l[+joGDC!s%KG!<2*\!.j9`k0rGm;YK5Tc1_1-
+J,~>
+!i2>Hp?hoYNrSh@!<;]ZrrE#c!s%cW!<2Bg!:K7TrpBjgmd:)SmJm7dmK<OXmJm7cmK3IWmK!.P
+!!)l`!!)oa!!*#d"9@lX!!)ucrrE)errE)e$39M^!!)HT!:K7TrpC!kmd:)CmJm6<mXafTmJp/Y
+mK52>S1/s~>
+!m8N2p?ho\NrSh@!<;]ZrrE#c!s%cW!<2Bg!:K7TrpBjgmd:)SmJm7dmK<OXmJm7cmK3IWmK!.P
+!!)l`!!)oa!!*#d"9@lX!!)ucrrE)errE)e$39M^!!)HT!:K7TrpC!kmd:)CmJm6<mXafTmJp8\
+mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;]RrrE#[!s%KG!<2*_!9WDDroO:_k2l[Cjo>D\job\Hjo>D[joYVGjoG;@
+!!)lX!!)oY!!*#\"9@TH!!)u[rrE)]rrE)]$395N!!)0D!9WDDroOFck2l[+jo>C4k(2[DjoA<Q
+jo`U&p8!3~>
+!h?&@p?hoYNrSh@!<;ZYquH`a!!*#d!W_ZVqZ$Zb!<2E`!<;Kc!!M]i!:K:R!<;He!;Z']!<;He
+!<2Bd!<2Eb!<;Kc!<)?c!!holmd:)CmK!7S!!*#drr<2i!:K7TJaS*Wf'WN9p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;ZYquH`a!!*#d!W_ZVqZ$Zb!<2E`!<;Kc!!M]i!:K:R!<;He!;Z']!<;He
+!<2Bd!<2Eb!<;Kc!<)?c!!holmd:)CmK!7S!!*#drr<2i!:K7TJaS*Wf'WN<p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;ZQquH`Y!!*#\!W_BFqZ$ZZ!<2-X!<;3[!!MEa!9WGB!<;0]!;YdU!<;0]
+!<2*\!<2-Z!<;3[!<)'[!!hWdk2l[+joGDC!!*#\rr<2a!9WDDJ`_OGf&cs1p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7rErr@W<JaV"T!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<7rErr@W<JaV"T!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<7r=rr@W4J`bGD!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<9\!q>f7;r;_E:JaUtS!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<9\!q>f7;r;_E:JaUtS!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<9[nq>f73r;_E2J`bDC!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;c\s7V$DJcC<$pAb*bp?hoYp?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;c\"7kmRqLSZts+14Hrrr8mmdff:p?ho\p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;cTs6fjZAcMK(pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAb/#pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds'YR#pAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAb.rpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7ZKkpAOFQjoA<Q
+jo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;`[s7ZBjs6a=XmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+k$[W>mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNY>mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"k#Up4mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mec,Lme6ABp@[hR;YKM\
+0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;`[s763`B)h_ulK7*gio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7[@-6J2io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io4A.io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7[@HQS3io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_iniPOhW!\co'Z)A
+mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;`Ss6^-cmf3"KhVQf^h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+hZ).*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hZ).*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*hZ).*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hYYh+hWF7gme,]B;YK5T`W,Y-
+J,~>
+!h?&@p?hoYNrSh@!<;c\"SV9Ok4XB+JcC<$s8N/gk2-(!rq?'R!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;`[#3+e)lMCP\rq^$rqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'd^@.sHjqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqYFUnqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'd^@eTZlqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*
+p?ho\p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;cT!:KjC!p94Vqt:$Xrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6N`p?pefc2H2lme5cC;YK5Tc1_1-
+J,~>
+!i2>Hp?hoYNrSh@!<;c\s5s=;JcC<$JcG`L!p8@irSI27!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\!8d\.!;?Bk@J^$#s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)S"s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqI'@"s8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)Rss8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqY'(&df%l"lLjQF
+<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cTr7(r<pAajdJbFZgK_>Z=hTa<qc.1A:joA<Qjo`U&p8!3~>
+!h?&@p?hoYNrSh@!<;c\"lAD(e_^"Ns+137rri&qpAajUrs%W9e`P`=hY$::;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\"k),Ydamu?s+137rrhWelMp/>rs/8SdaI"+cJ%sZ!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cT"jPTJc->\QrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDclrrhKak5XTCrrDcjrrDcjrsADee]l@he]lY4p>u?Qp>uJ%
+pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\!R9d+eH#;os+137rrhcimf2_ErrDKdeH=[Qc0"`f!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\#0,BFcI2.WJcC<$Q2_!Ps6BXLnc&mgim,itg;_:tp?ho\p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<;cT$bb*8`Pq95p@eO[s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'C]lhY,h"hY.!Kp&b9fs8M^$s7ZKds6ea_`QcrH`SU=N
+!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\"i]?Tc.265s+137rrhcimf2_Ers.uBc/.U%`THm^!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\#JSp?`mX/KqLSZts-EZfk5XTDk48NYqY&po`mWST_W(:W!*/a\"+A23
+@=S~>
+!quZ5p>u?QNrSh8!<;cT"hiI2^!5^<p4*,9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7UsBpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAai4s7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds5s@Ds5s@Ts7ZKds7ZKds7ZKkp'9Hn^!5*@^#&JF
+!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\!OU__blI0_s+137rrhKak5XT6rrMi]rlkQ%[(Y>imJp/YmK52>S1/s~>
+!m8N2p?ho\NrSh@!<;c\#I`@/`ldT;p4<'kqNgs\hYQ+*hX^LLp@@@g`ld#D^>ASO!*/a\"*r&/
+@=S~>
+!rqu=p>u?QNrSh8!<;cT#-?(g]uB.%JbFZgQ1b@2p=8lenb*7VhS$VAeZ?I7p>u?Qp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;c\$FJ[?`RX,NpAb-mk5PD]q>UKrrrE&uquHZpr;cWmr;cisr;cltquH`r
+rW%NLJcG<@"QoaHs5rnP$24D]e]$(q[(YVqmJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;c\1p5EP_TLm/o(r%[pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4I_pA4LZ
+pA4LZ!;Z]lpA4[e"T%igpA4^f#kn,gqY'dZqY'jf!rDWer;ZllqYU<pqY'db!.Xk=qY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY#F8
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4J6qY'dZqY'dZqY'dZqY'd>qV(f"qY'dZqY'dZqY'dZqY'dVo&@g/b1<`,hY-@;<VGh_
+IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT1p"s@[)Lnime6&Kme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6&Kme6)B
+me6)B!;6Edme6PY"SV9Wme6SZ#k%ESp?qYBp?qkZ!qu'Ur;ZldpA=mlp?qYR!.X_1p?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?mG(
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6'"p?qYBp?qYBp?qYBp?qY)p=8lep?qYBp?qYBp?qYBp?qYBma]:i`QbKkhY-(3;YK5T
+c1_1-J,~>
+!i2>Hp?hoYNrSh@!<;c\"f1#"`QdQEp1++&s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZHms7ZKd
+s7ZHms7QHdrrE)ms7ZKds7ZHms7ZHm!;?Hds7ZKd!;?Hd!!*$!s7ZHm!;6Eds7ZKdrrE)mrrE)m
+s7ZKds7ZElJ+ip9rrE)ms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds*sbBpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAYQps7Y":eb7Pes7ZKdp]1<e#Nj:Mc/,80hY-@;;YKM\
+0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\Cn9.s^;f$to()JSp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@nWp@@qJ
+p@@nWp@84Sp&OgWp@@qJp@@nWp@@nW!:ojSp@@qJ!:ojS!!)]mp@@nW!:g-\p@@qJp&OgWp&OgW
+p@@qJp@A1_J+E=(p&OgWp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp4)Z,o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(EL_p@?N"cLT9Op@@qJp]1?b#k$Qh^;e`p]&*/K!*/a\
+"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT#+WrO[(Y#PrpBadk3`3LqX+Ofmd:)CmK!%M!!*#drrDo`!!*#drr<)f
+!<2Ed!!2KfqsFFarpBadq<n4^rU'XcJaS0Y"NBfJm`#+lp]1?^#j0[N[(X_S[+4m4!)iOQ"3(<6
+Ujr~>
+!h?&@p?hoYNrSh@!<;c\7%DfP`QdQ=pAagdpAajdpAajdpAajdpAajdpAajdpAajdpAagdpAajd
+pAagdpAY-mp&OgdpAajdpAY*mpAajd!!%NBs7ZKdrrE)ms7QHd!;?HdrrE'!s7ZKds7QHds7ZHm
+s7ZKds7ZKdrrE)ms7ZHms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZJBpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd9D8DZs7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKCs4./"s7ZKds7ZKds7ZKds7ZKdp?'W5c./>t
+k4\3C;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\$C0&Z]#NUpmdfoKk4/KPqXOgjo'ueOnc8LVrrE#grrDre!!)ug!W_ck
+rUL!inc8RX!!)ug!!)fb!!)rf!!%T@K^o8ko$6gOo()hK#N!J3`mU-`hY-@;<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT$C&fS[)LS`k3hX;k3`3LqX+Ofmd:)CmK!(NrrE#crrDra!!)uc!W_Wg
+rU'^emK!.P!!)uc!!)f^!!)rb!!%T<K^Ju^m`"V5o'QhHma]:``QaXShY-(3;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;c\!K5M-`<GDlp?qVSrq6H^p?qYQ!!)HdpAFskpAG!jp&Y6fmf)nomJu\K
+p&OOS!!)`dme6)Bp&OOSmf)n]!;>j[p)rc'!;?*dme-V\p@\L[mJutSme6)B!;>jSmJutSme6)J
+p&aX^mf)n]mJm7dp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&a[Umf)ncme6(fp;QI=mf)n]me6)Jp':$Zme6)BmcOMf"5\sLhY-@;;YKM\
+0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\&WP5U]#*=dlK[d;mcs6*mcs6=!!DNSlL+TN!:'L_;srr=!:K.?lL*p;
+lL*p;lL"WPlL*s*lL*p;lL*s*lL"Z?lL*s*l2UhPl2^,;!!)<P!:K+PlL*s*lL"Z?lL*p;lL*s*
+lL*s*l2^,;lL*p;!.XG%mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mco;ilL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*rSlGDg(_WpRSmcs6*mcs6*mcs6*lK6s?]#)mT]&*/K
+!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT#(t16[(Y#HroO1\qW@_VrT=%Y!9X4[roO1\qrRkYroO=`k2lXDqW7bX
+qrRkYqr[nYs5jXgk2lXDk2l[+joG;@!!)u[!!)fV!!)rZrr@W4L#rNOk.Tojn`C,6e\/?'c%ECR
+p>u?Qp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;c\%?&c]^!5F%me6>Sp@dqRpAY*tme-V\p@\IdrUp6Zrq6Eop?hqZp&a[U
+!<2Zl!<2]k!;uNj!;uNkmK!4Z!q,dUrVurdrq?<krq?<krV$6ks7ZHm!VYsZp&a[U!<2Zrme6>S
+p@dqPp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOY
+p&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOY
+p&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OOYp&OO[p&rA.`V.:Mp&OO[
+pA=pipAaOchT`aYeVh-'p?hoYp?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;c\1l9Z#]#NIdlL*p;lL*s*lL"WPlL"WPlL"WPlL*s*lL*s*!:K+PlL*s*
+lL"Z?lL"Z?lL+WO'CP/RlL"Z?lL*s*l2^,;lL*s*lM^bclL*s*rW!#flL+WO$1@*Hl2UhPl2Ug6
+mcs6*mcs6*mJu\?mcs6*!:'";mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*J*uUilL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*l58sSmcs6*mcs6*mcs5Wm_\D/mcs6*mcs6<!"A;\mcrrg`k'1<M7VR;
+mJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cT$A6U:[(Y#HhWEr#qr[nYs5s=]s5s=]q;qbZk2l[@jo>D\jo>D\k5GAY
+jo>DYjo>DXk5GAZk5GA[k5GAZk5PG]k5PGVjo>DYjo>C4k(Vq#^#m#j^&$mh!<)$chT`a@]u>W2
+hY-(3;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;c\2M9l*]uAjjmcNp;mcNs"mcFN3mcNp;mcFN3mcNs"mcNs"!9W\LmcNs"
+mcFN3mcFN3mcNs"rW";-mcFN3mcNs"mJu\;mcNs"!!)Ee!9W\L!9O7]mcNs"mJm7LmcOKKJ*$an
+mcNs"mcNs"!9W_3mcNp;mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mXOBek3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3a/MmcNs"mcNs"mcNs"mcM4F^#m#jmcNs"mcOEI"m578mcNC*`<4YC^#&JN
+!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\#(=q:]#*1Xro*nXqr.SUrSdnZio0t5iWB2?iW/l8!!*#X!!)rVrW)rW
+!!)oU!!)oUrr<Ab!!)$<!!)!Y!;tjV!<2!W!!2'Zpu28Rqr.SUJ`;CC"Ld<uijS^CquH]T#i=:P
+]#)mD]&*/K!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT#'8&&[(Y#?rn[\VhUVS]!<C[Lh?*c7eH#R)!7h&)!s$m.!<1g[e_]-_
+hVQc_rS@P)rW)uT!S%2Kh?)6a!<1gbe_]-_!8[\UhVJ54eGoUKh?MNe!!(m4ec#OMh>l+(h?MNe
+h>lEhec+D,!8c9(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(
+h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(
+h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+(h>l+)h?U.4
+XPU&8hUVS]quH]P#h@25[(X_*[+4m4!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\++)P_^!5F%k3h@3k3hC"k3`6;k3h@3k3`6;k3hC"k5>9ImcFN3mcNs"
+mJu\;mJu\;mcNs"mJm7LmJu\;mcNs"!9W_3mcNp;mcNp;!9O:DmcFKLmcNs"mJu\;mcNs"mJu\;
+rW%H1mcNp;mcNs"mcFN3mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNqek3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"'B\`FmcNs"m_/&%m_/&NmcNs"med%nmcNs"mbZ4%c..0Sk4\3C
+;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\"aSP9]#N>"iW&uUiW&uWiWB2?iW/l8r;clW!!)oU!!*#X!!)lTrrE)Y
+!!)oU!!)oU!!*#Xrr<)Z!<2!X!;tgV!;b[V!93#;!<(mW!;kaU!.j-`iWQ^L[c4aliqrfSiWn&S
+]#N0D]&*/K!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cT$?O2"[(X`@e_]-_qq_;QrS@VVhVJ80hYdHSh>dQQh>dQTh>dQPhZ!TU
+h>dQQh>dQQh>dQThZ!QVh>mQ3rrDuR!!)lP!W_*6rW)oR!!)oQ!!%T,L#)s6hQ5S8qVM,Mrn[t3
+hT`a@^!1W*hY-(3;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;c\"_uT,]uAk,jo>DYjo>D[joYVGjoG>A!!*#\!s%KG!;kmY!<2*\!;Ya[
+!9WDD!<)'[!;kmY!<)$]!9O:[jo>DZjo>DYk5PGVjo>DYjo>C4k(Vq#[-"aX[/B(]!<2*chSm1I
+hJ0a\p?hoYp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\"`;])]#*%thH]%?ini\Oina[liniYpina[lini\O!8c_l!8c]8ini\O
+ina[lina[lini\OiniYpinaY8ini\O!!)$8ini\O!8c_liW.s<ini\O!8c_lina[lini\OiW&t.
+hW!DOhW!DOh>lElhW!DO!92kphW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOJ)92Aini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\OiYLD1hW!DOhW!DOhW!CphQG_<hW!DOhY7*Mh?VWK]#)m4]&*/K!*/a\
+"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT"_,`i['\*VeH5g%e_^;U#QWE3e^XZMeH#Nt!!*#K!s$m.!<(FLhUMW*
+eGoUIeHas]eH".M!!)uJrrE#J!oDH-rm_;2!7_)"e_\gVrm_),eH#U!#2[n\!!(R+r7(l*eH#U!
+#2[n\!7fWVr7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(
+r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(
+r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(r7(f(rm_.IeYL`k
+rm_&+ebB.DeHa@+[(X^n[+4m4!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\"_uT4^!5F4jo>DYk5PG]k5PG]k5PG[jo>D\joYVGjoG;@!!*#\!s%KG
+!<)'[!<2*\!<)$[!;bjX!<;3]!!_Qc!9WDD!<)'[!;kmY!;GUU!;u!Z!.j9djoi'R[-"amk5#)V
+jp0bf^!5)B^#o%V!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\"_lE)]#*%sh>dQQhZ!TUhZ!TUhZ!TSh>dQTh?*c7h>mH0!!*#T!s%37
+!<(dS!<1gT!<(aS!;bRP!<:pU!!_9[!8cQ4!<(dS!;kUQ!;G=M!;t^R!.j!\h?9k8WnscQhYI6N
+h?VWK]#N04]&*/K!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cT$=_8n[(X`7e_\gVqpk]Hs4.,Ls4.,LrRClJrm_)Ne^XZseGoUKeH5g%
+eH#QurrE&K!!)uJ!!)lGrrE)Lrr<8R!!(R"!!)uJrrDrH!!)cD!!)rIrr@W#L"-=%eYL`kqpkNC
+$e=+ae]ke7]u=HfhY-(3;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;c\$"Dc1]uAjbk2,7t!!1s=r;ZrVk2,8!!!(mQ!"S,kk2,7Wk2,5#k2$*p
+k5,,]hWE\WhYdE[k2,7Wk2,7Wk5>8]hWE\n!!26=r;Zr^hWE\o!!qHDhWE\WhWE\m!.Wkfh>lEp
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWB=Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,5/hPB#(hPB#jhWE\WhY[?WhWE\WhVS7N"5[M#hY-@;;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\"^TQn]"ZbogA:mMgAM$MgAM!OgA:jNg&V!'"T[91!8?0(!;tRL!;P:H
+!<1^N!<:dO!<(XN!;P:G!<1[P!.ijWg'",'U"Z4:gACsKg'?3G]#)m$]&*/K!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT#$T9b['\*&rmglG!R90n!!CKrc.2am!6tB@%b1R0c.1(hc.)gEblH#=
+qZ$cDe]lXhr;[,Rc.1(hc.1(hr;ZoDe]n$m!S,Hn!!Ccre]n'n#gLoEe]lXhe]n!lJ'HNg!6s'=
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+eUPioc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.*6ISB[SKSB]U/e]lXhqu?`Armh%ns0MpBc!%L)p>u?Qp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;c\Ip1CI^!5ErhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWEYphWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\Wh>lEphWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWCWrXQH>@hWE\WhWE\o!"IfIhWE\WhT`aYhHIVT
+p?hoYp?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<;c\#?fKp]#)nLg4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?!8?;`hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV%t`hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:P-hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-h[hP&f"hV-i?hV-i?rW!D]hV-i?g=!jL`mS#$
+hY-@;<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT"^90i[(X`;eGoT^eGoT#eUuBTSCO.[SGC_7!;k:Oc+UL'c!%L2p>u?Q
+p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\##a=&`Pp]jJ*,VMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\Wh>lEphWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE[jhPB#(hWE\WhWE\Wh>lEphWEZ$k2+t6`Qd7;
+^#&JN!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\"]3di^;A=Ng&M,(g4@tlg'!u#S_BY0g&M-Lg'?3G^;e`#]&*/K!*/a\
+"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT#"m.R['\*&J(;foc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hblH#=c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc%"9ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]iToc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1('c'6J;c.1(hc.1(hblH#=c.1&Fe]l@P[(X^V
+[+4m4!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\Io>.R`Qd9%hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWCp%Uunc@hWE\WhWEYuk2,7Wk2-+"#N!_Ee_X3;
+k4\3C;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\In\G=_T($\g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>8O[U#)L"g>:Q?g>:NphV-i?hV-i?hU]]`cIP\#
+hY-@;<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT"\R%Y]tM[AeUc88eHDDmSCO/!eHa@<]uA5g[,1N=!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\$VK:+c,JPrk2,7Wk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"
+h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?`9#Uu%p(Uu(85h?)irk5O3Hk2,7Wk2+t>c.1ZC^#&JN
+!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\#=R.k`kp0XhLXC3g6UFqU"Z3oU%6nDhV-Q'`mWF+]&*/K!*/a\"*r&/
+@=S~>
+!rqu=p>u?QNrSh8!<;cT#!pMQ]tM\8J(;foc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc%"9ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]iToc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(/c'6JCc.1(hc.1(hc.1(hc.1&Fe]l@P`Pp(f
+[+4m4!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\"^91-e]lYDjoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\o
+joXE%hYuX=hWE\ojoXE%hYuX=hWE\ojp9i+XQHVHXQJC=joXE%hYuX=hWE\ojp0bne_\PK^#o%V
+!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\#?Aptb0&/dg4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV*J9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:P5hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-h_hPK)*hV-i?hV-i?hV-i?hV-iC#iaR`cIU-3
+]&*/K!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cT!`H_^rl'H=J^p"8"JjSDeYM`c#i=+N`RVq"[,1N=!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuXChWEsrhPB;0hYuX;hYuX;hYuX;hYuX<mcON*"0>tFk4\3C;YKM\
+0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\#B?ctda$.hgA]r:g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?hI,'og>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:[og>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?hI>3qg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:PWg7d5og>:Q?g>:Q?g>:Q?g>:iKk2+\;g9+_m
+hY-@;<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT#BQ]kc,IZHc%4DreX"_gSCO.[SFb;1h?VTUc./Un[,1N=!)iOQ"3(<6
+Ujr~>
+!h?&@p?hoYNrSh@!<;c\!khLVrn[_,hVNhGJ``<]"K^aek,e.9$1@NTk2t2lMoFQHmJp/YmK5J>
+Ua^f~>
+!liB.p?ho\NrSh@!<;c\#eE^Pf%/9tf%P]3J_laM"JstOhPKf"$0(C8hVQOOKtcF;mJp8\mK7mW
+b$ff~>
+!quZ5p>u?QNrSh8!<;cT!jkS=rlkM`c-:giJ^p+;"JjSDeYMcd$/Xh$e^_W2K>#h/joA<Qjo`m%
+s."T~>
+!i2>Hp?hoYNrSh@!<;c\#53sIXOZ1irn_)GhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\Wk$['.hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEs.hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\Wk#U@$hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhYuXBmcNB58nt`X
+p$MfXp?i#;Umrla~>
+!m8N2p?ho\NrSh@!<;c\#P*jBV9[ZGeq)P+g4S)ZhYuL=euhPXZHD>'mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cTC[R*QUrCU/c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(heR6YPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1?Pc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(heQ0rFc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@
+p#Z6Pp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;`[#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r@.b$"B'lZ^#&GM!)iOY"$)mI
+.=_~>
+!liB.p?ho\NrSh@!<;`[C@\fE1b:%+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbp?n<]W-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n&IS-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbp@OroY-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&X
+p?ho\p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;`S"7EO*0nCd).=irG.0VG(K<2c:p#Z6Pp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\rq6H^k0:kr]n*kJ^&5PH`QdQ5p@dnS;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\#4h3QlJB\#J\$EDJ\(cj"N&=<lLOZ:!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cTrpFI^hSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJd@'mVS]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tIg\]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJd@^NhU]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tLed[(Wi[`STbF
+p>u?Qp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;`[CA.)hmdArohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\O@-6>.hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVMZ&hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\O@HQG/hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOk2,7WmdBfA
+mJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;`["S2!KlK3ZSJ_kt7qVD88lLaKE<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;`SC@:6Pk2t4Ne_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j,@,BGje_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^\'ae_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j,@G]Pke_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^`O,hUUK5k2u+)
+joA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\rr2ulrr2ulrr2ulrr2ulJaS*WJaW4!!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\%efJeo(MYJo(MYJo(MYJJaS*WJaW0u!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cTrU'[ZrpBd[rpBd[rpG@"J`_OGp#Z6Pp>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;c\!8dAJ!T*O$mXaeWme,uJ;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\!8@)F!S[*qmXaeWme,uJ<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT!7g`A!R:%`k(2ZGk4Rj:;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;c\%b:UZc.1(hc.1(hc2[goJaS*WJaW0u!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\&'FqP`lc<D`lc<D`rH(]l@JASmXag!mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cT%`S/A]u@\(]u@\(^&S,OJ`_OGJ`cUe!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\&&&#C>$>B=@Tm5E@fQJAhYQ[<!:9+R!;Ps^!:9+R!5._"!:]CV!;l0a
+!.jR(mJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;c\"1J70=nuA'rrKR^qX47]m-XiRq!J+^m-XiR]^>b"nEp8VqsFFaJaSil
+!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cT&$5g2>$>B=@Tm5E@fQJ0eb\G+!:8hJ!;P[V!:8hJ!5.Fo!:]+N!;kmY
+!.j9ujoA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;c\&$5g2@L)u%k3h@3!<<)#c26o/!9`bM!;Ps^!:9+R!5._"!:]CV!.jR!
+mJp/YmK52>S1/s~>
+!m8N2p?ho\NrSh@!<;c\&#K=+@0?Smio]5'!<<(qcMR#0!9`bM!;Ps^!:9+R!5._"!:]CV!.jR!
+mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cT&#B7*@L)trhWEYp!<<(pc26W'!9`JE!;P[V!:8hJ!5.Fo!:]+N!.j9n
+joA<Qjo`U&p8!3~>
+!h?&@p?hoYNrSh@!<;c\"-iicF8c1>s8E#urrJA7qsFFakO&<MqsFOdmd:)AmJm7^mJm7AmJm7S
+mJm7VmJm7ImJm6<m]PsX;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\"-NW`EW,t<s8E#urrJ8-qsFFakO&<MqsFOdmd:)AmJm7^mJm7AmJm7S
+mJm7VmJm7ImJm6<m]PsX<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT",m3ZF8c1>s8E#urrJ&&qrRkYkN2aEqrRt\k2l[1jo>DVjo>D9jo>DK
+jo>DNjo>DAjo>C4k-!hH;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;c\#)iN]F8l4GrVup(rr3"Webee7!;Z'^!<2Be!:KgdrpK^br9jOa!q$'V
+rW)rcrW)c^r;clcr;clcrVurdr;c]^r;cibr;c]^r;clcrVurdr;cib!<DQe!<2Eb!<;Kc!<2Bh
+!:BjTmem._mK<OXmJu\S!<;Hh!:BgerpBadrpBdemf!3;m]Z$Y;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\$AJN[EW6"A!!E9)rr3"QcMR&0!;Z'^!<2Be!:KgdrpK^br9jOa!q$'V
+rW)rcrW)c^r;clcr;clcrVurdr;c]^r;cibr;c]^r;clcrVurdr;cib!<DQe!<2Eb!<;Kc!<2Bh
+!:BjTmem._mK<OXmJu\S!<;Hh!:BgerpBadrpBdemf!3;m]Z$Y<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT#(uXLF8l4GrW!*-s8VeFc26Z'!;YdV!<2*]!9X7\roX.Zr9!tY!p0LF
+rW)r[rW)cVr;cl[r;cl[rVur\r;c]Vr;ciZr;c]Vr;cl[rVur\r;ciZ!<D9]!<2-Z!<;3[!<2*`
+!9O:Dk5>;Wjob\HjoFQC!<;0`!9O7]roO1\roO4]k5G@3k-*nI;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;c\"ag:LF8u:=!<)ouHe%u\rW)la&ch@f!!)HT!!)HT!:K7T!:K7TqsFpo
+md:&Tmd:)CmJu\C!!)oarrE)e!!)oa!s%cW!;l0a!;Gm`!:K7Tp[/"]qsFFaqsFpomd:&Tmd:)C
+mJm7TmK!.P$NTV_!!)HT!!)HT!;l0r!:K7T!:K7Tmd:&TmJm7TmK!7S!s%cW!.jR@mJp/YmK5J>
+Ua^f~>
+!liB.p?ho\NrSh@!<;c\"a0kFEW?(;!<)ouFjBjOrW)la&ch@f!!)HT!!)HT!:K7T!:K7TqsFpo
+md:&Tmd:)CmJu\C!!)oarrE)e!!)oa!s%cW!;l0a!;Gm`!:K7Tp[/"]qsFFaqsFpomd:&Tmd:)C
+mJm7TmK!.P$NTV_!!)HT!!)HT!;l0r!:K7T!:K7Tmd:&TmJm7TmK!7S!s%cW!.jR@mJp8\mK7mW
+b$ff~>
+!quZ5p>u?QNrSh8!<;cT"`sD;F8u:=!<3!"p2eLTk5GAYjq7[Vjo>DDjo>DDjoFQ+!!)0D!;kmg
+!9WDD!9WDDk2l[+jo>DYk5PG]jo>DYjoYVGjoG;@!!)cU!s%KG!;GUU!;kmY!;kmg!9WDD!9WDD
+k2lXDk2l[@jpM1Ojo>DDjo>DDjoG;@&HLtU!!)0D!9WDD!9O7]k2l[CjoYVGjoBtpY3#^^p>uJ%
+pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\$$6.HF8u7?!!iT'rrI2cq!S+]s6fmerpBjgmd:)SmK3IWmK!7S!!)oa
+!s%cW!<2Bg!:BgerpBadqsFFarpBadqsFOdmd:)PmJm7]mK<OXmJm7^mf*:bmJm7amK3IWmK!7S
+!s%cW!<2Bd!;l0d!:K7TrpBadrpBadqsFOdmd:)SmK3IWmK!7S!s%cW!<2Bg!:K7TJaT]/!)iOY
+"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\$#TP=EW?%A!!E<#rrHu^q!S+]s6fmerpBjgmd:)SmK3IWmK!7S!!)oa
+!s%cW!<2Bg!:BgerpBadqsFFarpBadqsFOdmd:)PmJm7]mK<OXmJm7^mf*:bmJm7amK3IWmK!7S
+!s%cW!<2Bd!;l0d!:K7TrpBadrpBadqsFOdmd:)SmK3IWmK!7S!s%cW!<2Bg!:K7TJaT]/!*/a\
+"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT$#926F8u7?!!iT(rrVn/c1pH#!<;3]!<2*_!9WDDroO:_k2l[Cjo>DY
+joYVGjoGDC!s%H`!<2*\!;kmY!<2*\!;km\!9WDDqrRkYpZ;SYk2lXDpu_SVr8mtZqrRt\k2l[C
+joYVGjoGDC!!)oY!s%KG!<2*\!<2*\!;km\!9WDDroO:_k2l[CjoYVGjoGDC!s%KG!.j:8joA<Q
+jo`U&p8!3~>
+!h?&@p?hoYNrSh@!<;c\"ChE2F8u+;rr3".eb8G2!!)Ha!<;He!<2Bg!:K7TrpBadqsFOdmd:)S
+mK!=UqZ-N]!!*#d!!*#dr;clc!!*#dr;c]^r;cibrW)c^rW)rc!!*#dr;clc!!*#d!s%cW!<2Bd
+!<2Eb!<;He!<2Bd!<2Bd!;l0d!:K7TrpBjgmd:)SmK3IWmK!7S!s%cW!.jR@mJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;c\"C:m(EW>n9s8N/o?-`03rr<&eqZ-Za!!*#d!s%cW!<2Bd!;l0d!:K7T
+rpBdeme["]mJm7dmJm7dmem.cmJm7dmem.^mem.bmf!4^mf!4cmJm7dmem.cmJm7dmK3IWmK!7S
+!!*#dr;clc!!*#d!!*#d!!)oa!s%cW!<2Bg!:K7TrpBjgmd:)SmK3IWmJqh+Y3l9ip?i$2`l__?~>
+!quZ5p>u?QNrSh8!<;cT"BtO!F8u+;s8N/g>0Zd'rr<&]qZ-ZY!!*#\!s%KG!<2*\!;km\!9WDD
+roO4]k5,/Ujo>D\jo>D\k5>;[jo>D\k5>;Vk5>;Zk5GAVk5GA[jo>D\k5>;[jo>D\joYVGjoGDC
+!!*#\r;cl[!!*#\!!*#\!!)oY!s%KG!<2*_!9WDDroO:_k2l[CjoYVGjoBtpY3#^^p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\%pK#5ErZ1Gs8N')!<;Ijeb/>4!:BgeqsFFarpBjgmd:)SmJm7amK3IW
+mK!7S!s%`h!;Gm]!<2Bg!:K7TrpBsjmd:)CmK!7S!!)oa!!*#d!!)rbrrDi^rrE)e!s%cW!<2Bg
+!:K7TrpBjgmd:)SmK3IWmK!7S!s%cW!<2Bd!<2Bd!;l0d!:K7TrpBjgmd:)SmK3IWmK!7S!s%cW
+!.jR@mJp/YmK52>S1/s~>
+!m8N2p?ho\NrSh@!<;c\%or?'E<H7Es8N'%!<;=acLpT-!:BgeqsFFarpBjgmd:)SmJm7amK3IW
+mK!7S!s%`h!;Gm]!<2Bg!:K7TrpBsjmd:)CmK!7S!!)oa!!*#d!!)rbrrDi^rrE)e!s%cW!<2Bg
+!:K7TrpBjgmd:)SmK3IWmK!7S!s%cW!<2Bd!<2Bd!;l0d!:K7TrpBjgmd:)SmK3IWmK!7S!s%cW
+!.jR@mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cT%oViqErZ1Gs8N')!<;1Zc1U3$!9O7]qrRkYroO:_k2l[Cjo>DYjoYVG
+joGDC!s%H`!;GUU!<2*_!9WDDroOCbk2l[+joGDC!!)oY!!*#\!!)rZrrDiVrrE)]!s%KG!<2*_
+!9WDDroO:_k2l[CjoYVGjoGDC!s%KG!<2*\!<2*\!;km\!9WDDroO:_k2l[CjoYVGjoGDC!s%KG
+!.j:8joA<Qjo`U&p8!3~>
+!h?&@p?hoYNrSh@!<;c\"\SgpK)boMs8N'$s5lr(qsFFarU0[cs6]jeqsFFarpC!kmd:)CmJm7a
+mK3IWmK!7S!s%cW!;Gmd!:K7T!:K7TrpBsjmd:)CmK!7S!!)oa!!*#d!!)oa!!)c]"p")Z!:K7T
+rpBjgmd:)SmKrs^mJu\C!!)HT!<2Bg!:K7TrpBmhmd:&TqsFOdmd:)SmL]HemJu\C!!)HT!:K7T
+!:K7TJaT]/!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\"\A4aJH,]Ks8N'$s5$;lqsFFarU0[cs6]jeqsFFarpC!kmd:)CmJm7a
+mK3IWmK!7S!s%cW!;Gmd!:K7T!:K7TrpBsjmd:)CmK!7S!!)oa!!*#d!!)oa!!)c]"p")Z!:K7T
+rpBjgmd:)SmKrs^mJu\C!!)HT!<2Bg!:K7TrpBmhmd:&TqsFOdmd:)SmL]HemJu\C!!)HT!:K7T
+!:K7TJaT]/!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cT"[VSVK)boMs8N'$s4'E[qrRkYrT=+[s5j:]qrRkYroOFck2l[+jo>DY
+joYVGjoGDC!s%KG!;GU\!9WDD!9WDDroOCbk2l[+joGDC!!)oY!!*#\!!)oY!!)cU"p!fJ!9WDD
+roO:_k2l[CjpD+NjoFQ+!!)0D!<2*_!9WDDroO=`k2lXDqrRt\k2l[Cjq.UUjoFQ+!!)0D!9WDD
+!9WDDJ`a,t!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\"@;JLpAb$`s6]sN6-];pqZ-T_r;clc!!*#d!!*#drr<)f!;l3a!!2Kf
+rpBadrpK^bqX4@`"7?0WmeZtdmJm7TqZ-Q^qZ$War;c]^r;cibrr<&eqZ$Zb!<2Bd!<2Ed!!DWh
+mdBrP!U]sdmf*7fmK!.P!s%cW!<2Bf!:K:R!<2Ec!!Vcjmd:&TJaT`0!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\"@2,;me6YJ#P.<Nk2P5_cMR&,!<)?a!<;He!<2Bd!<2Ed!!2KfqsOIa
+!U]semJm7dmem.^mf*7hmJu\CqZ$`d!!)Ha!;u9^!!)Hc!;c-^!<2Ed!!)Ha!!2KfrpBadrpKdd
+"7?0WmeZtbmK!4Rrr<)f!;l0d!:K7TrpBgfmdC#RrpKac"muBYmJm6<m]Z$Y<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT"@:o,k4\f:#O^a:hVQdKc26Z#!<)'Y!<;0]!<2*\!<2-\!!23^qr[nY
+!TjC]jo>D\k5>;Vk5PD`joFQ+qZ$`\!!)0Y!;u!V!!)0[!;bjV!<2-\!!)0Y!!23^roO1\roX4\
+"6KUGk5,,ZjoGABrr<)^!;km\!9WDDroO7^k2uUBroX1["m,gIjo>C4k-*nI;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;c\!'1#?rU0[Y"7Gk;eUd/?mJm6<m\&tJ;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\!&X]3$f^=6lK7C"mcs'oc@PE8mJm6<m\&tJ<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT!&=H&$Kg4-hWEtgk2nDCJ`bSH!!%T4T]Q5Pp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\!/'nu!F"$)mc*[6!;Z$_!.jR2mJp/YmK52>S1/s~>
+!m8N2p?ho\NrSh@!<;c\!.jbr!Em^!mc*[6!;Z$_!.jR2mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cT!IH9p0`W[%0`W[%0`ie-c%5$:k5GAVjo>C4k+Li:;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;`[%c4"GMj0-aMj0-aMj1$oJaS*WJaW4!!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;`[!SXCDN<,m0JaS*WJaW4!!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;`S!S+">MZKX(J`_OGJ`cXf!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\"8;0>c2Q5nc2Q5qc.1A$JaS*WJaW0u!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\&+]#>cI1"dcI1"dcI1"ll@JASmXag!mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cT!q,4$p<<TfJ`_OGJ`cUe!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<;c\rr2ulrr2ulrr2ulrr2ulJaS*WJaW4!!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\%efJeo(MYJo(MYJo(MYJJaS*WJaW0u!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cTrU'[ZrpBd[rpBd[rpG@"J`_OGp#Z6Pp>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\!8dAJ!T*O$mXaeWme,uJ;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\!8@)F!S[*qmXaeWme,uJ<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT!7g`A!R:%`k(2ZGk4Rj:;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;c\%b:UZc.1(hc.1(hc2[goJaS*WJaW0u!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\&'FqP`lc<D`lc<D`rH(]l@JASmXag!mJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cT%`S/A]u@\(]u@\(^&S,OJ`_OGJ`cUe!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\&&&#C>$>B=@Tm5E@fQJAhYZ^@!;u6b!:B1S!:0%Q!86c?!8m2E!:K7V
+!:K:S!9!8I!:K7TqsFFaJaU;@!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;c\"1J70=nuA'rrKR^qsFFar9aObmHsrSlg=`Qg$Sh?hsLIEmd:,VmdC&S
+i9g[Imd:)PmJm6<m_A/i<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT&$5g2>$>B=@Tm5E@fQJ0ebeJ/!;tsZ!:AnK!:/bI!86K7!8lo=!:JtN
+!9WGC!8uuA!9WDDqrRkYJ`a`0!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\&$5g2@L)u%k3h@3!<<)#c26o/!;u6b!:B1S!:0%Q!86c?!6FR.!8HoA
+!;l0a!.jRQmJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;c\&#K=+@0?Smio]5'!<<(qcMR#0!;u6b!:B1S!:0%Q!86c?!6FR.!8HoA
+!;l0a!.jRQmJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cT&#B7*@L)trhWEYp!<<(pc26W'!;tsZ!:AnK!:/bI!86K7!6F:&!8HW9
+!;kmY!.j:IjoA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;c\"-iicF8c1>s8E#urrJA7qsFFar9aObmHsrSr9aXemd:)ImJm7?mJm7.
+mJm7AmJm7amJm6<m_A/i;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\"-NW`EW,t<s8E#urrJ8-qsFFar9aObmHsrSr9aXemd:)ImJm7?mJm7.
+mJm7AmJm7amJm6<m_A/i<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT",m3ZF8c1>s8E#urrJ&&qrRkYr8mtZmH+BKr8n(]k2l[9jo>D7jo>D&
+jo>D9jo>DYjo>C4k.g$Y;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;c\#)iN]F8l4GrVup(rr3"Webeb7!;u6d!:K:R!<)?b!;c*d!:K7TmeZta
+mem.amem._mem.bmK3IW!!)ucrW)obrW)obr;Zoe!:KgdqsOC_rU0XbrpBdemf!4cmK*CV!<2Eb
+!<;Kd!;c*a!:Kgdr9aXemJm7cmem.bmem.bmem.bmKN[ZmJuYT!<2Bd!<2Ec!.jRWmJp/YmK5J>
+Ua^f~>
+!liB.p?ho\NrSh@!<;c\$AJN[EW6"A!!E9)rr3"QcMR#0!;u6d!:K:R!<)?b!;c*d!:K7TmeZta
+mem.amem._mem.bmK3IW!!)ucrW)obrW)obr;Zoe!:KgdqsOC_rU0XbrpBdemf!4cmK*CV!<2Eb
+!<;Kd!;c*a!:Kgdr9aXemJm7cmem.bmem.bmem.bmKN[ZmJuYT!<2Bd!<2Ec!.jRWmJp8\mK7mW
+b$ff~>
+!quZ5p>u?QNrSh8!<;cT#(uXLF8l4GrW!*-s8VeFc26W'!;ts\!9WGB!<)'Z!;bg\!9WDDk5,,Y
+k5>;Yk5>;Wk5>;ZjoYVG!!)u[rW)oZrW)oZr;Zo]!9X7\qr[hWrT=(ZroO4]k5GA[joPPF!<2-Z
+!<;3\!;bgY!9X7\r8n(]jo>D[k5>;Zk5>;Zk5>;ZjothJjoFND!<2*\!<2-[!.j:OjoA<Qjo`m%
+s."T~>
+!i2>Hp?hoYNrSh@!<;c\"ag:LF8u:=!<)ouHe&#]!!)rb!s%cW!;l0e!:K7T!;l0m!:Bgemd:)C
+mJu\C!;l3a!<;He!;l0a!;l3a!#4i$!:K7Tmd:&Tmd:)CmJm7TmJm7cmf*:emJm7amJm7amL'$_
+mJm7TmJm7TmK!7S"p"&kmd:&TrU'dgmd:&TqsFOdmd:)Pmf*7rmJm7TmJm7TmJm7TmK!.P!!)oa
+&HM7e!!)Ee!:K7Tmd:)CmJm6<m`+Yp;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\"a0kFEW?(;!<)ouFjBmP!!)rb!s%cW!;l0e!:K7T!;l0m!:Bgemd:)C
+mJu\C!;l3a!<;He!;l0a!;l3a!#4i$!:K7Tmd:&Tmd:)CmJm7TmJm7cmf*:emJm7amJm7amL'$_
+mJm7TmJm7TmK!7S"p"&kmd:&TrU'dgmd:&TqsFOdmd:)Pmf*7rmJm7TmJm7TmJm7TmK!.P!!)oa
+&HM7e!!)Ee!:K7Tmd:)CmJm6<m`+Yp<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT"`sD;F8u:=!<3!"p2eLUjo>DZjoYVGjoG;@"9@TH!!)oY$ioDi!9WDD
+k2l[+joG;@rrE)]!!)oY!!)oYrr<bq!!)0D!9WDD!9WDDk2lXDk2lXDrT=+[s5j:]qrRkYqrS7d
+k2lXDk2lXDk2l[CjothJ!9WDD!<)$_!9WDD!;km\!9WDDqr[nY%H[Wjk2lXDk2lXDk2l[@jo>DY
+jq.UUjo>DD!!)0D!9WDDk2lXDJ`au7!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\$$6.HF8u7?!!iT'rrI2cqsFFar9a[fmd:&TrU0[crpBadqsFLcmK!7S
+#6=2[!:K7T!;u6b!<2Bd!;l3a!;u6b!<2Bg!:BgerpBjgmJm7dmK3IWmK!1Q!!*#d!!)oarrE#c
+rrE&d!s%cW!<2Bm!:K7Tmd:)CmK!4RrrE&d!!)oa!s%cW!;l0a!<2Bg!:K7TrU'dgmd:&Tr9jRb
+r9aXemd:)SmKN[ZmJuYT!<2Bd!.jRXmJp/YmK5J>Ua^f~>
+!liB.p?ho\NrSh@!<;c\$#TP=EW?%A!!E<#rrHu^qsFFar9a[fmd:&TrU0[crpBadqsFLcmK!7S
+#6=2[!:K7T!;u6b!<2Bd!;l3a!;u6b!<2Bg!:BgerpBjgmJm7dmK3IWmK!1Q!!*#d!!)oarrE#c
+rrE&d!s%cW!<2Bm!:K7Tmd:)CmK!4RrrE&d!!)oa!s%cW!;l0a!<2Bg!:K7TrU'dgmd:&Tr9jRb
+r9aXemd:)SmKN[ZmJuYT!<2Bd!.jRXmJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cT$#926F8u7?!!iT(rrVn/c26W'!;ts^!9WDD!<)'[!<2*\!;km[!9O:\
+jp(nKjoFQ+!!)rZ!!*#\!!)oYrrDuZ!!*#\!s%H`!<2*_!9O7]roO:_k2l[Ajo>D\jo>DYk5PG[
+k5PG\joYVGjoGDC#ls,M!9WDDk2l[Bk5PG\jo>DYjoYVGjoG;@!!*#\!s%KG!<)$_!9WDD!;u!Z
+!;ts]!9WDDroOCbk2l[+!!*#\!!%T4`o[8!p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<;c\"ChE2F8u+;rr3".ebeb7!;u6b!<2Ec!<;Ka!;l3a!<)<f!:K7TrpKac
+rpBadrpBadqX4=_rpBadrpBdemeZtame["amJm7bmJm7dmJm7`mf!4dme["amJm7dmf*7lmJu\C
+!:K7TrU0O_qsFOdmd:)PmJm7dmK3IWmK!4R!!*#drW)obrW)rc!s%cW!<2Bh!:K7Tme[!8m`+Yp
+;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\"C:m(EW>n9s8N/o?-`?8!!)rb!!*#drW)udqZ-N]rrE#c!s%cW!<2Ec
+!<2Bd!<2Bd!;c-_!<2Bd!<2Be!:K^a!:K^as6]jer9aObrpBadqX4=_s6faas6]jerpKdd#OVT[
+mJu\C!<)?_!;l0d!:K7TqsFFarpBjgmd:)RmJm7dmf!4bmf!4cmK3IWmK!7S"9@lX!:K^aJaUPG
+!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;cT"BtO!F8u+;s8N/g>0Zs,!!)rZ!!*#\rW)u\qZ-NUrrE#[!s%KG!<2-[
+!<2*\!<2*\!;bjW!<2*\!<2*]!9X.Y!9X.Ys5j:]r8mtZroO1\qW@bWs5s1Ys5j:]roX4\#Nc$K
+joFQ+!<)'W!;km\!9WDDqrRkYroO:_k2l[Bjo>D\k5GAZk5GA[joYVGjoGDC"9@TH!9X.YJ`au7
+!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\%pK#5ErZ1Gs8N')!<;Ijebeb7!;u6b!;u9b!!;Qg!;Gm_!:BjdmK3IW
+mK!1QrrE)e!!*#d!!)f^rrE)e!!*#d!s%`h!;u9b!;l0a!;u6b!<2Bd!;Q!^!!;Qg!;l0a!<)<k
+!:BjTmJu\C!<)?c!;Gm`!:K7TqsFFarpBjgmd:)RmJm7bmf*:bmf*:emK3IWmK!7S"p")Z!:Bge
+JaUDC!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\%or?'E<H7Es8N'%!<;=acMR#0!;u6b!;u9b!!;Qg!;Gm_!:BjdmK3IW
+mK!1QrrE)e!!*#d!!)f^rrE)e!!*#d!s%`h!;u9b!;l0a!;u6b!<2Bd!;Q!^!!;Qg!;l0a!<)<k
+!:BjTmJu\C!<)?c!;Gm`!:K7TqsFFarpBjgmd:)RmJm7bmf*:bmf*:emK3IWmK!7S"p")Z!:Bge
+JaUDC!*/a\"+A23@=S~>
+!quZ5p>u?QNrSh8!<;cT%oViqErZ1Gs8N')!<;1Zc26W'!;tsZ!;u!Z!!;9_!;GUW!9O:\joYVG
+joG>ArrE)]!!*#\!!)fVrrE)]!!*#\!s%H`!;u!Z!;kmY!;tsZ!<2*\!;P^V!!;9_!;kmY!<)$c
+!9O:DjoFQ+!<)'[!;GUX!9WDDqrRkYroO:_k2l[Bjo>DZk5PGZk5PG]joYVGjoGDC"p!fJ!9O7]
+J`ai3!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<;c\"\SgpK)boMs8N'$s5lr(qsOIarpKddqsFOdmd:)LmKim]mJu\C!:K7T
+qsF[hmd:)CmJm7]mKrs^mJu\C!!)HT!;l0a!;l3a!<)<c!<2Bd!;Gm`!:K7TqsFFarU0[crpBmh
+md:&TrU'Xcp[/+`md:)PmL0*`mJm7TmJm7TmJm7amJm7amLTBdmJu\C!:K7T!:K7Tmd:(+m_\Al
+;YKM\0r1<gJ,~>
+!m8N2p?ho\NrSh@!<;c\"\A4aJH,]Ks8N'$s5$;lqsOIarpKddqsFOdmd:)LmKim]mJu\C!:K7T
+qsF[hmd:)CmJm7]mKrs^mJu\C!!)HT!;l0a!;l3a!<)<c!<2Bd!;Gm`!:K7TqsFFarU0[crpBmh
+md:&TrU'Xcp[/+`md:)PmL0*`mJm7TmJm7TmJm7amJm7amLTBdmJu\C!:K7T!:K7Tmd:(+m_\Al
+<VGh_H-4-8J,~>
+!rqu=p>u?QNrSh8!<;cT"[VSVK)boMs8N'$s4'E[qr[nYroX4\qrRt\k2l[<jp;%MjoFQ+!9WDD
+qrS+`k2l[+jo>DUjpD+NjoFQ+!!)0D!;kmY!;kpY!<)$[!<2*\!;GUX!9WDDqrRkYrT=+[roO=`
+k2lXDrT4([pZ;PXk2l[@jpV7Pjo>DDjo>DDjo>DYjo>DYjq%OTjoFQ+!9WDD!9WDDk2lYpk/-6\
+;YK5T`W,Y-J,~>
+!h?&@p?hoYNrSh@!<;c\"@;JLpAb$`s6]sN6-]8oquH`ar;cfar;c`_$NTV_!!)Ee!:Bgemem.a
+mf*7fmK!.Pr;cibr;cfar;cibr;cibr;Zld!<2Bd!;l3_!<)?a!<;He!<)?c!<2Bd!<2Eb!<;Kc
+!;l0d!:K7TqsOC_rU0UarpK^brpK^brpBgfmdC#RrpBadrpK^bJaUPG!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\"@2,;me6YJ#P.<Nk2P5_cMHu,!<2Eb!<)?a!;l0l!:K7T!:BgemJm7T
+r;cfarr<)f!;l3_!<2Eb!<)?a!<2Eb!<2Eb!!2KfrpBadqsOC_rU0Uas6]jerU0[crpBadrpK^b
+s6fgcqsFOdmd:)Pmem.amem.bmem.bmem.bmK*CVmem.bmJm7dmem-:m`+Yp<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT"@:o,k4\f:#O^a:hVQdKc2-T#!<2-Z!<)'Y!;kmd!9WDD!9O7]jo>DD
+r;cfYrr<)^!;kpW!<2-Z!<)'Y!<2-Z!<2-Z!!23^roO1\qr[hWrT=%Ys5j:]rT=+[roO1\roX.Z
+s5s7[qrRt\k2l[@k5>;Yk5>;Zk5>;Zk5>;ZjoPPFk5>;Zjo>D\k5>:2k/QN`;YK5Tc1_1-J,~>
+!i2>Hp?hoYNrSh@!<;c\!'1#?rU0[Y"7Gk;e[t5L!2f/a!.jR*mJp/YmK52>S1/s~>
+!m8N2p?ho\NrSh@!<;c\!&X]3$f^=6lK7C"mcs'ocF`KE!2f/a!.jR*mJp8\mK7aW`aOA~>
+!rqu=p>u?QNrSh8!<;cT!&=H&$Kg4-hWEtgk2nDC]B0(nVWIjYJ``?^!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\!/'nu!F"%Ome?e(mJm6amJm6<m[3DB;YKM\3LlloJ,~>
+!liB.p?ho\NrSh@!<;c\!.jbr!Em_Gme?e(mJm6amJm6<m[3DB<VGh_IE'E<J,~>
+!quZ5p>u?QNrSh8!<;cT!IH9p0`W[%0`W[%0`ie-c2?`!!6O@'!2elY!.j:"joA<Qjo`m%s."T~>
+!i2>Hp?hoYNrSh@!<;`[%c4"GMj0-aMj0-aMj1$oJaS*WJaW4!!)iOY"#6UA.=_~>
+!m8N2p?ho\NrSh@!<;`[!SXCDN<,m0JaS*WJaW4!!*/a\"*r&/@=S~>
+!rqu=p>u?QNrSh8!<;`S!S+">MZKX(J`_OGJ`cXf!)iOQ"3(<6Ujr~>
+!h?&@p?hoYNrSh@!<;c\"8;0>c2Q5nc2Q5qc.1A$JaS*WJaW0u!)iOY"$)mI.=_~>
+!liB.p?ho\NrSh@!<;c\&+]#>cI1"dcI1"dcI1"ll@JASmXag!mJp8\mK7mWb$ff~>
+!quZ5p>u?QNrSh8!<;cT!q,4$p<<TfJ`_OGJ`cUe!)iOQ"3pQ>S:C~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@!<7W<JaS*Wg?nr=p?i#CS>7Ta~>
+!liB.p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$2`l__?~>
+!quZ5p>u?QNrSh8!<7W4J`_OGg?&B5p>uJ%pA^Y5~>
+!i2>Hp?hoYNrSh@!<7W<JaS*Wg?nr=p?i#;Umrla~>
+!m8N2p?ho\NrSh@!<7W<JaS*Wg?nr@p?i$.b/Rk?~>
+!rqu=p>u?QNrSh8!<7W4J`_OGg?&B5p>uIrs7W7=~>
+!h?&@p?hoYNrSh@JPq%sJPt,up?i#CS>7Ta~>
+!liB.p?ho\NrSh@JQ78$JQ:?&p?i$2`l__?~>
+!quZ5p>u?QNrSh8JPq%sJPt,up>uJ%pA^Y5~>
+!i2>Hp?mq?JaS*WJaUDC"#6UA.=_~>
+!m8N2p?mq?JaS*WJaUDC"*r&/@=S~>
+!rqu=p?%A7J`_OGJ`ai3"3(<6Ujr~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@p?mK0JPq%sJPt0!p?i#CS>7Ta~>
+!liB.p?mK3JQ78$JQ:B'p?i$2`l__?~>
+!quZ5p?$p(JPq%sJPt0!p>uJ%pA^Y5~>
+!i2>Hp?mM3JcC<$JcFF'p?i#;Umrla~>
+!m8N2p?mM3JcC<$JcFF'p?i$.b/Rk?~>
+!rqu=p?$r+JcC<$JcFF'p>uIrs7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@p?ocjJaS*Wna?AL"4a2o;Z8s)3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3W25G
+;M1dqrV$-V]Cu-iZhF+\"$)mI.=_~>
+!liB.p?k09mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+o'Z):o'Z):o'Z("mXafrmK`=No'Xr&I8JTZ#>fiFddH\oo)%iDo'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)>mdff:mdff:mdg8C:%I`Cmdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+o'Z):o'Z):o'Z)BmK7mWb$ff~>
+!quZ5p?'3ZJ`_OGn`Kf<"O3`h8jV8n#!k708pdAYrU0RF]C,RYZgRPL"3pQ>S:C~>
+!i2>Hp$P!:me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6):
+p?qYBp?qYBp4;X_mdKR$p?n_:5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+3C,Yk3C,[$me6JE6h]sAme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6):p?qYBp?qYBpA+,Lp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qABme6)Bme6)Bp$Mo:Umrla~>
+!m8N2p$P!6mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff6
+o'Z):o'Z):nq$4[mdKQFo'W(G4<caI3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3;P`=
+SaQ(EmR-R5o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):mdff:mdff:mdg2A9ChNAmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff6o'Z):o'Z):o(DDQH-4-8J,~>
+!rqu=p#\F*k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBo
+mcNs"mcNs"mXaMOk3qF6mcL%e3<G`5meQ!4mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcN["k3hC"k3hC"q;t?<k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2u*omcNs"mcNs1jo`U&
+p8!3~>
+!h?&@p?qtSa8c,3JaS*Wna?GN"+*="3W;;j3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk5rnp1"Z\k7HhR11mf3!ss8DZgmf3!ks8DZbmK5J>Ua^f~>
+!liB.p?i%Rme6M#rrr8mmdff:JaS*Wna6JLmWHi<!d3r%qsFRWme6Lrrrr8mmdff:qsFRWme6Lj
+rrr8mmdff:p?i$2`l__?~>
+!quZ5p?)DCrUquGpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0d
+s8DZimXaMOk4.U6mJq>-3<2@u3<2AE3<VW.F7/Jnk5XlJp,E$Fs7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmpAb*brU0RFs6fjZ5QCHWpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0ds8DZime5cFc1_1-
+J,~>
+!i2>Hp$VkRr;Zfb.H^'\mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs7jok,G
+p?qX*mXafpmKT1A5ri\ek1Tb=k-Sk`5rkJ2mf3"Ys8VL?k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"qrS%Lp@dqJq<n:Vr;Zfb2s0PjmcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mec,Lme6ABp@[hU0r1<gJ,~>
+!m8N2p$VkNs7SJQqXWq6io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7W
+hW!DOk3hg.nq$4[mdKQDQ2WltBsQIhs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+qZ$EGZ>';#!1!BJs763`5QCTNlK7*gio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7WhW!DOk3hg.o(h_Ro)JDRs8)<Ok2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2P7Sini\Wmdff:p$Mp-b/Rk?~>
+!rqu=p#c;B#PRTcp?peoec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D,e_]0\
+eHFakmcNqgk(2[`joCYF3<Erse_0WteZ<Nb3<5<>k5XiSp?qtSmbZgNrn[Y*rn[Y*rn[Y*rn[Y*
+rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rndP&"Q&;/k3i'-s6^-cmf3"KhVQf^h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hYYh+hWF7gme,]E`W,Y-
+J,~>
+!h?&@p?i(WmdB62d/O18k2-(!rq:p2JaW'r"k>n)3McBIs8MEdk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5F`Ijp(8IUcC_,c26o3p?qA2p<*C:mcNC)k5P)OmKE7OmcO5[rrVWNhYlU9p@dnV
+3LlloJ,~>
+!liB.p$N%Dk2P\&s8W)p2"pe>qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+k2+\Gg>:iWmdbqsJaW'r!7(R+.%0Z&pAb!Oio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io^4!!p8p=r]C2'qX+RIk2P\&s8W)p3qiFDqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*qX+RIk2P\&s8W)p6MC9LqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*p?i$2`l__?~>
+!quZ5p>uACrn[_=pAb$`!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj["7G$r
+c2H2lmXaMOk4.R6c2K^,Pj\85s7Y.&"m2%05rlp]joFiKh?)j5s82Kimf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n`me6)*e]n'CrpK[G!:KjC!p94Vqt:$Xrq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6N`p?pefc2H2lme5cFc1_1-
+J,~>
+!i2>Hp?qtCrnc!$!p8@irSE+nJaW!p#Fn(GF6;oQp>#ZTmcNBghWEsA5s_%<mf2GKhT>d!k2+Ye
+hYHU>k5O5RrrV?>ec"@smK52>S1/s~>
+!m8N2p?hq;rRq8FrVnPIs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)Tc
+k17uZg&UDhmXafqmPgP!4Dj*?ip-7;pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LF
+g=G-7hVN675ahN;!8d\.!;?Bk2>[@Ls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)Tck17uZg&UF7mJu,Bg&UjFs#p5YqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$Egp?'rSrRq8:p$Mp-b/Rk?~>
+!rqu=p?);'"Rc!`pA`\:#O^Hnc.1(heUck6k3qFcPX.<EhVQfFmf2_Kme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)BmbZL=rRD!b3C/o,k5<a4me6\Ss3LBDmbZ45e]lXpq<%V*"Rc!`pA`2,
+#O^Hnc.1(heb%u+`W,Y-J,~>
+!h?&@p?i+@k2t4Np<WaCk1/#EhUUJ6mXafqmK7f.9!nT[!8cK1!q+pqroO<i8kOI-mKMJ0k1/>^
+ao;S-e^`g=e_^/j"lAD(e_^#9rs%W9e`P`=hY$:=3LlloJ,~>
+!liB.p?i+4g=k!+o$ICAp>46GhV-9/JaS*WnEquQ6qFK7hV-]Ws8)HcpA4LZqY'dZqY'd^pA4LZ
+pA4XZqY'dZqYKp^pA4LZqW?M[rn7IW847UtmKM%mg="RCb5V_?hU9j/g<SFKmKM%mg="RC_Z'l7
+hU9j/g<SFFmK7mWb$ff~>
+!quZ5p>uP'e^_phmeZq`pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAP!tp?pJUc.1@heaA"NJ`cLb
+"*6b#V#AgEpAb-c!:KaX!:KaX!:KaX!:KaX!:KgZ!oDJPrm_+P8jROqjos#[e]lA,qYpQhr;Qcj
+r;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;QcjrVm2tma]S,e^_ppmec,Mc.1@hc0kH.!;??j!;??j!;??j
+!;??j!;??j!;??j!;??j!;??j!;?<i$23f;c-=ehc.27Ujo`m%s."T~>
+!i2>Hp?ht+k5Nm2p<Wa=mf(`=hTa=-JaS*Wna?ET#"m.shUUKVg]%Q9e^`g=bt:l3qsFL0k5Nm2
+p<!=7mf(`=hTa=-qsFL0k5Nm2p;-b/mf(`=hTa=-p?i#;Umrla~>
+!m8N2p?i.)g="9pmeY?2#kmE+cI1Fdb2S!?JaW'r2c*1=b1bRtf(/k;s8)cls8)TlqZ$ElqYL6g
+s8)clqZ$ElqZ$Egs8)cls8)chhTjF#g<)r[;#BYb`nJkdddHtTrs8>\cHakl`ld<<mKU\bda$;/
+qSW==p?'ZGdb;^`iqDdBH-4-8J,~>
+!rqu=p>uChec*Mlk3hs:s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'(Ki
+pAaR;rl"ui]uAiZk(2[bk5S$X6,h+!`Qdi+p'0s8`PpBP`VrL,joN0Grl#*(me6ASpAb-c!rquo
+rq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6Nqp@eOShYtIre\/rYqrRpmec*Ml
+k3hs:s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp':Wk
+s7Z0dmb[r^"4b*(hY-(6`W,Y-J,~>
+!h?&@p?i+'hUTm$ma(n<ma]S4k/G$rJaS*Wna6N`;Hh?-rm_#Bg]%9Arm_/6c!""KqsFX,hUTm$
+m`GJ6ma]S4k/G$rqsFX,hUTm$m_So.ma]S4k/G$rp?i#CS>7Ta~>
+!liB.p?i1"g="!hlLt)'rsAPqim,Qlg:k;\JaS*Wna6]`:fYBdd`U#+qVD/Xp?'ZCdb;Q<:f[D\
+#JSp?`mX/GqT]$HqY&po`mWST^>f%X#JSp?`mX/GqSiI@qY&po`mWST^>ekS"+A23@=S~>
+!quZ5p>uOce]kePk5G!'s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKl
+p'9Hn^!5*7^#">&J`cLbr_b;\e]#MPk4\iKs7ZKds8VfmpAajds7ZKds7ZKmpAajdpAb0ds7ZKd
+s8VNDrl"og^&Cq,jor-Bc+VBarUqrFpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdrq6TR`P'OH[(Y>njor-Bc+VBarUr5NpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdrq6TR`P'OH[(Y>ijo`m%s."T~>
+!i2>Hp?hsghYtb#me6;Q!!)rs!!)fo!!)Kf!VYs\blch0^#">.JaW'rr`TK=hUTm$me$PX!<)ot
+!<)ot!;?Erk1.H$hS&nlqsFKlhYtb#me65OrrDKe!!)Ng!VYs\blch0^#&YS!OU__blR8+o)JRe
+jSo2[pAY0emf(H5hR'uQp?i#;Umrla~>
+!m8N2p?i0kf#kkPk486=q>^Nnq>^Njq>^Nbq?cldk/tQ`f!;mDJaS*Wna6]d?!4bicGIllp@\Ia
+!<)ot!<)ot!;QTop'B[#_Tp`D=^>2-mK^&Kb/2<`o(M\OrrDK`!!)Qc$23rPb/2<PZF\oimK^&K
+b/2<`o(M\OqZ,^R!!)ci$23rPb/2<PZF\odmK7aW`aOA~>
+!rqu=p>uOSc,IB0hYupDp?qqR!q,dMrq6Bnp?qqR!W_r^rq6Wcp?qVSp?qYBrq6E]p?qqR!Uf[[
+mK_U^]uA6l[+0`iJ`cLb#uXr)[*?S'`SU%^p&P-ip&Y3er;Zuos7Z-drq6Bm!;uNjs8M`lmKh[g
+]uA7';HcuqjoqR*`P&tArpBg\mf)n]me6)Jp'C*[!!)`dme6)Jp&a[Umf)ncme6)Bp&OOSmf)n]
+me6)Jp&XUTrU'pI]tMD0UpS\LjoqR*`P&tArpBg\mf)n]me6)Jp&XUTqZ$Warq6E]p?qqR!q,dM
+rq6E]p?qqR!q,dMrq6E]!:Kj["Rc!Op@eLR#N!/-`Qb3ceb8,-`W,Y-J,~>
+!h?&@p?i0ehTa$ik4\NHrrDcjrrMfnrVlol!<)otpAP!l!;??j!;??j!;?Bks7Q][e]#eiXM*bI
+mXafrmK@96C96:kblR8+pAY*mrr;uurr2rurr2rupAY0emf(H6hQ1I$CA[E(XPV4@e`QT!r;Qcj
+r;Qups8N'!s7ZBj!;??j!;??j!!)rs!;??j!;?Bks7Q][e]#eiXM*cnmK]iMc,J5qp@eFa!;??j
+#kn8u!<<)mrrE&u!;??j!;??j!;??j!;??j!quWorr2ulqu?]i#NjRUc/,P8k4\3F3LlloJ,~>
+!liB.p?k/Ad`T;HhX^72o(MYJo(MYJo(MVSo(MYJnc87So(MYJo(MVSo(MYJo(MYJo(MYJo(MYJ
+p@@e2b.c$HV7PN7mXafrmPe]cAZF>(_TM$3s8)cls8)cqqZ$BlqZ$Qq!;c`l!<;oq!<;oqs8)cl
+s8)cho&@g/b1<S(@:f?(7A\GT^<5='o(MYJo(MYJo(MYJo(MVS!;?!Wo(MYJo(MYJo(MYJo(MYJ
+!;?!Wo(MYJo(MYJo(MYJp@@e2b.c$HV7PO\mS0P+b.c$To()MFp@@qJp@@qJp@@nW!:ojSp&OgW
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@nWp@@qJp@@qJp@e(JhTERTd\XP3p?i$2`l__?~>
+!quZ5p>u^Xc,I'/eaDSnme6YJ!qu'UrpBgfme6YJ!W_Z^rpC'cme6&Kme6)BrpBj]me6YJ%JK5`
+p?qA!`O*V/UpT!0k(2[bk5JfpUs6ll^#&2Wrq6Hop@eOcp(7;upAY*mpAagds7Z-ds7Z0drq6^!
+p@dqBhS$VAc(t>JqrS6]c,I'/eaDSnme6YJ!qu'UrpC'cmJm7Tme6)BrpBj]me6YJ#km][md:)K
+me6YJ!qu'UrpC6hme6ABma]:``Qb3chYZFBUs6lc`RXD=p?qYRmK3+MpAXI]p&G*lmK3(^pAXI]
+p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p&OgcmLT$Zp?qABmdAWE[)L:c[,1N="3pQ>S:C~>
+!i2>Hp?j`,hSmIYk3hs:s7ZKds7ZKds7ZHms7ZKdrrE)ms7ZKds7ZHms7ZKds7ZKds7ZKds7ZKl
+p'C*Kc,IZYSA!d1mXafrmL3iOC8BD)^!5^5s8Vflrt4u)s7QEms7ZKm!!*'!!<<'!rr3)os8Vfl
+s8M]thT`aYeYHr$CA[E6SDM6(c0"HfpAajdpAajdpAajdpAb*l+TM08pAajdpAajdpAajdpAagd
+pAajdpAajdpAajdpAb-c#k$j"`Pp](^#&YS6(HfN`QdQ5p@eO[s7ZKds7ZKdrr<&ms7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7QHds7ZKds7ZKlp'C*Kc,IZYSA!eQmK52>S1/s~>
+!m8N2p?i-Md_``<hX:%,!!)rf!!)fb!!)KY#k$Qh^;A<`]&&#+JaW'r$#+6jS^PNh`np.XpAY-k
+pAY-mp&b<gp&Og[s6^0L`k'1<SS;qTqsFZRd_``<hX9t*rW)EX!!)NZ#k$Qh^;A<`]&*>P#*mWR
+^;f$to^`"^hXUXHp@8LWhT!:HdZqE#p?i$.b/Rk?~>
+!rqu=p>uRDc+UKte`QMl!!)rb!!)f^!!)KU#j0[N[(X_K[+0`iJ`cLb$Y!j[SB\aS^")Q=pAXIs
+p?qABmJm7\mdBcK!:KO\me-YKme6):pAXIgp?q)2e\/?'`LLCP@f,9lPg-nK^")99mf!4TmJm7V
+mKht*]sPJtPdK!<jp%'p]sPK'k4J*A!8d,D!;>gdk1./P^!2eKeb8,-`W,Y-J,~>
+!h?&@p?i*Ke]kePhXgF@!;uNj!<2]k!<2Zr!;?*dp&G*bp'9a)^!5)l^#jn6JaW'rrd-AahTa$a
+k3i9Cs7ZKds8Vfm!<;cms7ZHms7QHm!!)`mpAb0ds7ZKds7YmCc,IraPl?%,mKJj*c+VBYo(N(`
+!VQNlp&b<g!!*#l!s&#p!<2Zo!;6Bmrq6<lp@\aRc+VBPPeH5VmKJj*c+VBYoC`.aq"FXdrq6?m
+pAP'kpAG!kpAP'kp&G*cp'9a)^!5)l^#o%V"$)mI.=_~>
+!liB.p?i0Jd`/l<g?RtrmJm7bmJm7dmf!4cmKN[ZmJuYT!;>j\l3H%_]#N0\]&&#+JaW'r2gKOk
+Oj_+\`np"So(MYJo(MeJp&OgWp@e(N!;>s`p&G*`p@@qNo(MYJo(MM:hT!:HdZJftH2I"7Oj_7\
+`nK_Co^;_Z!U]sdmK3IW!!*#d!s%`h!<2Bg!:BgerpBadq!S1I#MR2/`mU!\hYZ^GOj_7\`nK_C
+p$Me[q!S(\rpBdemf!4cmem.cmf!4cmJm7]mf2PWg;^_DdZM,tp?i$2`l__?~>
+!quZ5p?!BR`P&Xle`Q#^k3hC"k3hC"k3h@3k3hC"joFQ3k5G?%k3h@3k3`6;!!)0Lk3hC"k3hC"
+mcNZ^]sPJtMmV>lk(2[bk5KE+Mp8rB^")9>mJm7amKN[ZmJuYT!;>j\jos;K[(X_Brc@u!7>o-u
+[(Y#Pk3hC"k3hC"k3hC"k3`3LjoFQ3k3`6;!!)0LjoFND!:K";!:Bgek3h@3k3hC"k3hC"mcNZ^
+]sPJtMmV@<jrKB!]sPK'k2u*omcNs"mcNs"mcFN3mcNs"mcNs"r;Zugk3`6;rW!#fk3i0J!TrhL
+!#P(cmJu\;mcNs"mcNs*k2t4-[(X_B[,1N="3pQ>S:C~>
+!i2>Hp?hs6ec*MfhYupmp?qYBp?qYBp?qVSp?qYBp&OgS!:KO\!:KO\p?hn\p&G*\p?qYBp?qYQ
+mK_mn]uAi\^#">.JaW'r$%%;WMq-(cc/.m_p&G*ip&Y6fpAP'bpAaOdhT`aYeVed,KDY';K@Tt?
+!8d_C0_Xr.me6)Bme6)BmJu\K!;>jSmJm7\!!)H\!!)Ee!;>g\me-YSme-YSme6)Bme6VI#Nj"=
+`SQ6\hYZ^AK@Tt?!8d_C3;2e6me6)Bme6)B!;>jSme6)Bme6)Bme-YSmJm7\mJu\K!!)H\me-YS
+mJm7\mJu\Kme6)Bme6VI#Nj"=`SQ6\hY-@>0r1<gJ,~>
+!m8N2p?i-=d_`T4g?/%m!!)r^&HM+]!:&hL!:&hLlKS?Ll2UhXl3QP+_RdV4Kt?,lmXafrmf%V=
+M9a,P`nKSLmJm7amK*CVmf!4Zmf2DQg;^_DcADOKqsFZBd_`T4g?/"l!s%WO!<)3_!"\>p!:&hL
+!9sOalKSB7l2^hK!!)cY#j0jX]#)mL]&*>P#)1LB]#*1`o]cDVo]cealKS?LlKSB7l2Uh_l3@=S
+l2UhLl2^PC#j0jX]#)mL]&*/K"*r&/@=S~>
+!rqu=p>u^/c+UKte_]HFk2-+"!oE(rroO7^k2-+"'EI:P!9WDD!8ci<k2$(<jo>D<k2-+"%Gp7(
+hWE\F]sPJtHaM=Sk(2[bjp?*UH\9;N[(X`@roO4KqrRkYqrRq[k2uXC!TrhIjoFiKk5X9Dc+U3l
+`Ii5YHi)q4Hd072^")!%hWE\ojoXE%hYuXUh>lEp!9W/#h>dQ<!!(m<!!(jU!9WDDhW=h;joPPF
+hYuXHhWE\Ok2+Y%[(X_2[+5'9$@C%2[(Y#Hk2,7WroO:=k2-+"!W_B>roO:=k2-+"%c6=Jk2lXD
+k2$+#jo>D<roOIdk2$(<k2$*proOaJk2,7_hWE\F]sPJtHaM>sjo`U&p8!3~>
+!h?&@p?i0<e]kePhX9P(mJuDImJuDG!"A8q!:K";!:K7Tk3`6KmJm7bmJuDJmKr%DhT`aYeUtQt
+JaS*Wna6^JMj/kNc,IZak5P&Smec\X!;lHp!;?*dp&OgSqt:$Xrq6]ek2+(rc/+);Mj4,,#D:RO
+^!5F%k5=WIk5=WOk3`6;mJm7dmM#Zhk3`6;mJuD;mJu\C!:K7Tmd:)QmJuDJmKr%DhT`aYeUtQt
+qsF]Ae]kePhX9P(mJuDImK)GMrU'[Jr9adOmd:)CmK!7S!s%cO!<)?c!<2Bg!9W\LrpBdKqsFdQ
+mbZ4%c..H[k4\3F3LlloJ,~>
+!liB.p?iTFd`/l<f&G]Oio]7_io]7_io]7s!$pP(!9W;'!9W8@ioU7'ioU7'io]7_io]7_k2PCO
+`k'1<J\']hmXafrmf&%tIF?!D_V4#;lL*s*lL+**mJu\?mdBB.!:K+PmJu\?mcs6.lL*s*lL*Zk
+g;:G<dXD+OqsHn(d`/l<f&G]Oio]7_io]7_io]7_!9W8@!9W;'!9W;'!9W8@io]5#ioU7'iW/!#
+!9W;'io]7_io]C_imu,\`mTFLhYZ_8J^VQL`n'//k2PO_k2PO_k2PO_!93/#k2PO_k2PO_k2HC#
+joFQ'joFQ'!93/#jo>D@k2HC#joFQ'k2PO_k2POcio8P/]#N0L]&*/K"+A23@=S~>
+!quZ5p>uU,c+UKtc/."DhYI3Rh>dQTh?Eu:h>lEh!<1gT!;51Rc+UKt`I"uKJ`_OGn`C.9K7eNq
+]sPK'ebA2+!;km^!9WDDjoG):$Js=`]sPJtH]*N/qrS-1c+UKtc/."Ch?3i8h>dQTh>dQTh?*c7
+h>mQ3#lri=!8cQ4hVJ8*h?V<=[(XG*[,1]B#CF_/[(X`@eb.c!!;,+M!8cQ4rn[_WhVJ82hZ!TT
+h?*c7h>m6*#L0rh]u>?*hY-(6c1_1-J,~>
+!i2>Hp?i**hSm1IhYuXMmcNs"mcNs"mcNp;mcNs"mJu\P!#F_b!:JtLk3h@3k3hC"k3hC"k2u*o
+hYtIreT8F\JaS*Wna7olS<SBNc+VBYk2u*omcNs"k3h@3k3hBomcFN3mJuAL!:K";k2u*omcNs:
+jp9hg^!5)SPan!8mKI[g`P'7IroORUk3hC"k3hC"k3i*H,j+OW!9W_3!9W\LmcNp;mcFN3mJm7L
+!9W_3mcNs"mcN["k2-*V"4_J+hYZ^EF5FmL`SUUV(%15Pk3hC"k3hC"!:K";k3hC"k3hC1!"JAY
+!9W_3!9W\LmcNs"qZ%/pjoFQ3k3hC"k3hBomcNC*`<4Y3^#&JN"#6UA.=_~>
+!m8N2p?i--d_`T4f&$&Y!!)rV!<D-V!<;$\!92u<ro*nXp>QA7f###8dWN.XJaS*Wna?C="a/,-
+[_gVhiW&uUiW]DBiW.s<!;>CWhW!,'[_g=4rfR*G#'JA2]#*%To]#`Jro*nXro+"[io0t;iX#VE
+iW.ut!!)!Yp>QA7f###8dWN.XqsFZ2d_`T4f&$&Y!!)cQr;clW!!*#X!s%??!<(pS!<;$Y!;>CX
+hU]QT_U<S<hY-@>H-4-8J,~>
+!rqu=p?!</c*Xjkc.1\$hUUK5hUUK5hUUH_hUUK5h>lF0!$0VH!8c6+e_\gVe_\j5e_\j5e^`O,
+c+UKkc"aW9J`_OGn`Kh/"`qYrXM)mXh>l+*h@\;phUMV_hUUK>eH"I_!8[\Urn[b-hVQf^hZ)+1
+hT`a8]u>'lMu2WMC<a,m^!5*ae_\j5e_\j5e_\j5qZ&.shUMVVhUMVVh>lE_h>lE_!7fp+!7_)"
+hUUK5hUUK5e_\j$]sP/kC:)OgjrS9^['[Nke_\j5e_\j5e_\j5e_U;_e_\j5e_\j5eboIWhUMVV
+hUMVVh>lE_hUVK'(>dRAe_\j5e_\j5e^`O,c+UKkc"aW9p>uIrs7W7=~>
+!h?&@p?i**e]kePhXfk0!;ts]!9O7]qrRt\k2l[Cjo>DSjp0bf^!5)K^#jn6JaW'rrhKR0hYtJA
+hWF7gmcNs"mdB6*!!)0LmcFKLmcFN;jo>DLk3h["mcNs"mcNZgrl"opCAt%+mKI[^c+VBYoB$#Q
+rT4([roO1\roO:_k2l[CjoYVGjoGDCrW)WR#N!_=c.-mKk54QMF4JOKc//'SrrDlW!!*#\!s%KG
+!<2*_!9WDDrT=+[qrRkYp#ZM9c+VBPF1p`0mK5J>Ua^f~>
+!liB.p?k.^d`/l8f&#9ChW!DOhW!DOhW!AlhW!DOh>lC4!92kphW!AlhVnOphVnOphW!DOhW!DO
+iniPC_Rdb8D7\STmXafrmf&a]C!sl0_UdT<ir9#Wir9#YiWK8@iW&uQir@j=f###8dV8]OqsH(R
+d`/l8f&#9ChW!DOhW!DOhW!AlhW!DO!92kp!92kp!92i8hW!AlhVnOphW"M7'B7m.hW!DOhW!PO
+hU]QT`mS_8hYZ_8D:6G8_UdT#ini\Oini\Oini\O!!)$8ini\Oina[lina[liW.upiW.up!8c_l
+iW&u8ini\OiW.upini\Oini\ShVQi#]#N08]&*/K"+A23@=S~>
+!quZ5p?"SS`P&Xlc/."-e_\j5e_\j5e_\gVe_\j5eH","!8c8_e_\gVe_U;_e_U;_e_\j5e_\j5
+hUUK-]r\olC:)iKk(2[bjpR]DS79aV[(X`7hUVV^(tIL"e_U9+e_]05!!(m+!8c6+!8c8_hUVV^
+!S-'+eH`dp^!1#VPaqX5/o&A=[(X`@e_\j5e_\j5e_\j5eH".Ve_U;_e_U;_e_U;_eH".VeH".V
+!8c8_rW!Vge_\j5e_\j5hUUK-]r\olC:)jpk"TU0]sPJthUUK5hUUK5hUUK5hUMT+hUUK5hUUK5
+!7frV!7fp+hUUH_hUMVVhUUH_!7frVhUUH_hUUK5hUUK5hVQf>c+U3lc"aWBp>uJ%pA^Y5~>
+!i2>Hp?hrjec*PfhDjZSk2,7Wk2,7Wk2,5#k2,7WjoFQ#!8ckpk2,5#k2$*pjo>D<k2,7Wk2,7W
+hWE\O`P'7I@_LWLmXafrmL$&&XCB`)]uAOahYuX>hWEtWroOdmk2tO_!9W/#!8cl#!!)0DhYuXH
+hWEtWk2+(jc.-:)[&j/m!FjUY`W+dYk2,7Wk2,7Wk2,7WjoFQ#k2$(<k2$*pjo>D<joFQ#!!)0<
+!8ckp!!)0<k2,7Wk2,7WhWE\O`P'7I@_LXqmK$eIrl+oo7crRihWE\WhWE\WhWEYp!9W/#h>lEp
+!9W/#!9W,<hWEYphW=e<hWE\W!9W/#hWEYphWE\WhWE\WhVRDOhSm1IhI=1Tp?i#;Umrla~>
+!m8N2p?i,nd_`T0f%U,[2;6p@hV-i?hV-fdhV-i?h>lEd!8?;`hV-fdhV%t`h>dQ0hV-i?hV-i?
+hVQu;^:M20@Ck<HmXafrmf'3j@Eu`u_U@03h>dQSh>dQTh>dQThZ!TNhZ):5d_`H0c=-^PqsFYs
+d_`T0f%U,[45/QFhV-i?hV-fdhV-i?!!(m0!8?90!8?90hV%r0hV%t`hV%r0hV-i?hV-i?hV-iC
+g=F!L_U;l(hYZ^F@FE$(^=M$;hF$#Rg>:Q?g>:Q?g&M-0g>:N`g>2hdg>2hdg&Tj`g&Tj`!!(a0
+g>2hdg>:Q?g&Tj`g>:Q?g>:Q?hV-Pp]#)m(]&*/K"*r&/@=S~>
+!rqu=p>uQ_c+UKkc-?7<29j[re]lXhe]lVEe]lXheH".E!6s'=e]lVEe]e*=eGoToe]lXhe]lXh
+e^_ph['[Nk>-uh2k(2[bk5M.[@`?$^^!66#!!)uJ!!*#K!!*#KrrDiE#L1fD]r\od@fE2#jp##6
+]sP/kc2Q6Tc.1(hc.1(hc.)gEc.1&=!7f<oc.)doc.)gEbl@aoblH#=bl@aoc.1(hc.1(hc.1@h
+c*Xjkc!%L)qrS)dc+UKkc-?7<6d=0+e]lXhe]lXh!!(Qoe]e*=eH".EeH".E!6s'=!6s$o!6s'=
+eH".Ee]lXh!6s'=e]lXhe]lXpc-<W&^!0`feb8,-`W,Y-J,~>
+!h?&@p?ir1e]kePhWE\WhWE\WhWE\WhWEYphWE\Wh>lEphYdEWk2$*pk5>8ohWE\WhWE\WhWEtW
+k2+@rc.-::k(2rOmd]]O`P'5ohTa$YhVS7o!8dV8!T)u;!!MH@k2l[CjoO<=r8n"9rT=.:s2>/d
+hHIn3`V]'C@b&`:c/.U>k2,7Wk2,7Wk2,5#!8ckpk2$*pk5>8]hWE\n!$14YjoFQ#jo>D<k2,7W
+k2,7Wk2tO_hT`aYeRH5SqsG2.e]kePhWE\WhWE\WhWE\WhWE\WhY[?ThWE\l!!q]ek2,5#k2,8!
+!!1s=r;[VijoFQ#k2,7Wk2,7_hWE\>^!5):^#o%V"$)mI.=_~>
+!liB.p?ir,d`/l8db<F3g>:Q?g>:Q?g>:N`g>:Q?g&Tj`gAM!ShV%t`hYdEgg>:Q?g>:Q?g>:]?
+g=!jL`mS/(hLY*Gmd]`E\e8/s`kK=@g>:Q?g>:Q?hV-i?hYdEmhV-i?!8cGdg&Tj`hV-i?hV-iC
+g=F-T`n";l])1n8?.-a(_U@/lhV-i?hV-i?hV-fd!8?;`hV%t`hYdEUg>:Q^!$0qMh>lEdh>dQ0
+hV-i?hV-i?hVQu?d_`T8dTsH@qsG2)d`/l8db<F3g>:Q?g>:Q?g>:Q?gACpPg>:Q\!!qE]hV-fd
+hV-ib!!1g1r;[Veh>lEdhV-i?hV-iCg=jul]#N0(]&*/K"+A23@=S~>
+!quZ5p>uN^c+UKtc1BHc!;t@I!<1OI!<:RN!7fWu!;+eHc+UKtc!%L2J`_OGn`KhX"]EUY[(X`V
+eboLHeGoUJeGoUCeHO42[(X^^rj;Rb"^90a[(X`Vec,XIeH,a$eboLIeboLIeGoUKec,XAeHa@4
+[(X^f[,1]B"^90a[(X`SebfFHeb]=IeH#U!!!*#Kr;clJr;clJ!!)]B#L0rh^!0`fhY-(6c1_1-
+J,~>
+!i2>Hp?k.ChTa$YhVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7Wk2,7Wk2,7W
+hWE\O`Pp*Y;SCq<mXafrmPi,0`DYRC`QcrqhWE\WhWE\Ok2,7Wk2+tWhWE\WhVRDOk2,7WhWE\W
+hWE\Ok1._qe_X3Cc,KSJ78i!e`Pp]jk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7WjoFQ#k2,7W
+k2,7W!8ckpk2,7Wk2,7WhWE\O`Pp*Y;SCramS-U9c,IZYhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOhSmIYhGV&Dp?i#;Umrla~>
+!m8N2p?i)af#GG@dbrgZ!:ebJf##/@elB<<JaS*Wna6\"`kkR'b.bmDgY)q]`kKUH:r:5hqsFVf
+f#GG@dd#Nd!;kIM!;G1I!;"nLf##/@elB<<qsFVff#GG@d_XWBf##/@elB<<p?i$.b/Rk?~>
+!rqu=p?"S;c+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]e*=e]lXhe]lXhe]lXh
+c.1(`]sPJt;RFu*k(2[bk5N%K9$P>^^!5*Pe]lXhe]l@hc.1(hc-=e`e]lXhc.1(hc.1(`e]lXh
+e]l@hc+UL'bt@uKqrU=Fc+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXh!6s'=e]lVEe]lXhe]lXh
+e]e*=e]lXhe]lXhe]l@hc-<r/^!0H^ebeK';U)n^^!4gPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(`e]l@P[(X^^[+4m4"3(<6Ujr~>
+!h?&@p?i)^hUTTiec+\;hWE\WhWE\WhWFS5,NdkFhWE\WhWE\W!9W/#hWE\WhWE\WhWEtWk2+A%
+e_X3;k(2rOmd]`FeI^S0hUTlqhVRDOk2,7Wk2tOp!#j_Vk2,7Wk2,7_hWE\WhWEtWhTa<qk"=1S
+hYZ^E;VosCc.2gU$/Xh$k2,7Wk2,7q!%I%1k2,7Wk2$*pk2,7Wk2,7WjoFQ#k2,7Wk2,7Wk2tO_
+hTa$ihGV&LqsFVchUTTiec+\;hWE\WhWE\WhWFP40](sKk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7_hWE\>`RWgC^#o%V"$)mI.=_~>
+!liB.p?iPef$;.Pdb`^7g>:Q?g>:Q?g>;T),Mq/2g>:Q?g>:Q?!8cGdg>:Q?g>:Q?g>:]?hU]]`
+cIP\#hLY*Gmd]]Xda$93g<R^Xf%T!7hV-i?hVQu\!#jSJhV-i?hV-iCg>:Q?g>:]?f#G_Tg.9Z;
+deiGF9\.M+`mW_thV-i?hV-i?hV-i]!%Hb)hV-i?hV%t`hV-i?hV-i?h>lEdhV-i?hV-i?hVQuC
+f#GSPekE[3qsG(jf$;.Pdb`^7g>:Q?g>:Q?g>;Q(0\YC;hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-iCg>:E#_Tp_+]&*/K"+A23@=S~>
+!quZ5p>uNNc,IB0c1KQ]!;=qC!:eSEc+UL'bt>A"J`_OGn`C/&`Q^^!`P&t0c1oi`!:JD;]`lC*
+6-[BnqrS&Sc,IB0c1KQ]!!1UMqpbZHpXK6Do@4)j]sPc'9!mIPjonB%`P&t0o[W[9f[U5O]sPc'
+9!mIKjo`m%s."T~>
+!i2>Hp?i5QhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9k5='9k5='9k5F-Ck2+t>c.1Z:^#">.
+JaW'rrn[fVc/-^iec">)k54!8k54!8k54!8k54!8k5F-@k2+Y5hT\sthYZ^I6/L/:`STJ6hWFgo
+!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X7:$0L+$c-=eq6+u.PmKl29e]l(ihWE\Wrn[Y;
+r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9qq_YAhVQN%e_WU*hY-@>0r1<gJ,~>
+!m8N2p?i/Rf$;:Pdb<R,g'QWif#l"Xg-iO/JaS*Wna?G2#1cVnf#l"Xh:hnc#hI;Df#gh?g=lGl
+#=R.g`kp0XhTaa\hV-Q'`m3:+]&*>P#=R.g`kp0XhSn1ThV-Q'`m3:+]&*/K"*r&/@=S~>
+!rqu=p?"S*c,IB0c-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+c.1(`]tMD86+#0nk(2[bjos#[bt>t"rl+o^/Ci"qc.1(`e]lXhe]l@hc.1(hc-=e`e]lXhc.1(h
+c.1(he]l(Pc,E<"e]n!R77#2;]tM\8e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhc.1(`]tMD86+#2>k"S.d`P&t0c.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc-=e`c+Ug0eNpRmp>uIrs7W7=~>
+!h?&@p?i/hc/-^qe_]0\joF99joF99joF99joF99joF99joF99joF98jp0bne_\PK^#jn6JaW'r
+$23fTF0sf\c.1\MjoF98joF98joF98joF98joF9;jpLP=k1/>FZubs/pA=7_>0YpKe^`O5r8n"9
+r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9qrS.?e^`O$;SD5imKZq?hTaU$hVS1m!8dY9!8dY9
+!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dP6#N""]hT\s3k4\3F3LlloJ,~>
+!liB.p?j_:b1=_Xdb<F3g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q_
+h?`,pcHb"`9Y0)3mXafrmPjFnl><iXf#lFlhV-i?hV-iCg>:Q?g>:]?hV-i?hVQuCg>:Q?hV-i?
+hV-iGini,7f!9/Xk3Dj33E=5Qb0&/dg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q_h?`,pcHb"`9Y0*XmQjjqf#l.`g=kE;hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?rn[q?g<S!pb"TD'p?i$2`l__?~>
+!quZ5p>uNV`QcB@c-XuHhTa<ac,E;^hLXg?k4%L=hWARSc-=5Pc/."Nh>l+*blb%^k2,ss"]E=a
+`Pp*EeHk$Vc,IrH9!mIPjonZ%c,IZH_USqKc-=5P`CdMop>uJ%pA^Y5~>
+!i2>Hp?i0,XPVgae_]0\joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF99joOo4
+rn[aY@_LoTmXafrmf*4f`DY7bh>m!CjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjpLP=k3hs2
+k2t2l`W#o7mK[g7hVQf5hVS1m!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!Uf+Lh?0ig^#o4[#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX<mcON*"0>tFk4\3F0r1<gJ,~>
+!m8N2p?i0*WnPnHcIU_KhDEsCg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+io9+Wf$`9T?+SmDmXafrmPjk9qS#YKg=F^#ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\SmcrZcdSR[SqY'gS#B?ctda$.hgA]qig>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?io9+Wf$`9T?+SnimK[a3g="9lf%U,[6JC;MhV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hW!PWhU^-/Y$JWqp?i$.b/Rk?~>
+!rqu=p>uU$Ut*`/`QcZWec+D1e]l@hUft.^J`_OGn`KiE"11\>ec*fChUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK>k2t4Nbt>ABpA<tWF/7@2`Pp*HcIMpN#M%)DeYHBUhYZF?F/7@2
+`Pp*H`mt(F#M%)DeYHBUhY-(6`W,Y-J,~>
+!h?&@p?i!q;U,3t!nH/aeE.)*p?q)*eP_=EhLY*Gmd]]FpAY'oPY/%-gti7tp@d@M8sK>T!;?<X
+!khLVrn[_,hVQQ?$1@NTk2t2lMoFQMmK1("c2QQ$e_]0&jpCJLmcNZ^;N&NNp?i#CS>7Ta~>
+!liB.p?i3t9Zkr;daH_#eD:MkmcNB_c:ir+hLY*Gmd]]Fo)AYBO[Q%kf%S^/f%S^/f%S^/f%S^/
+f%S^/f%S^/f%S^/f%S^/f%S^/f&#iceuhQ+rr2uhqsFa$9Zkr;daH_#cJAlemcNB_c:ir+hYZ^H
+\kL8tf$`!tg;_tUipPschTefK^>ASO"+A23@=S~>
+!quZ5p>uF`9#^eS!l`F/eC=l^k2+Y=`CbcreUck6k4.R6mf*5>Ma<lPc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1tEc(msirr2udqrRse9#^eS!l`F/cIE6Xk2+Y=`CbcrebeJ1
+ZqA=:blYl/c,S9?hWE\Fe\t.5^")i="3pQ>S:C~>
+!i2>Hp?i.YMb:)$hWFgo.H]LLhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\o
+jp1>:hR#mi[*=0iJaW$q!;?Bk/^8W.0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+
+0ek+36$(<LrrDcimKWBC9!$S"k5O3jk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7WroOIRk2*I;C:)7^mKWBC9!$S"k5O3rk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WroOIRk2*I;C:)7YmK52>S1/s~>
+!m8N2p?i1VNC9Vgf%S^)g&U"/iWdu:885BPk(2rOmd]]Go(r@c/]Mcm/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1`2#4E8C?rrMueqsF^[NC9Vgf%S^#g&U"/iWdu:885BPk54QO
+nr6&6cIU_#`nCFLro+.5Y"394b3&Ec"*r&/@=S~>
+!rqu=p?"1!Mb9eac.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1)<
+ec4J0c(ms@XMobQJ`cIa!Uf[\rrTlT3S>h_3HMn5rrMi]qrTp,Mb9eac.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@qW:*3Mb9eac.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8n
+h?D0"8n+m@p#Z@qs7W7=~>
+!h?&@p$N%X]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=@"s"OXS
+K=&>KJaS*Wn*U2Lc2Re;q<eI\]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=F$s"OXSK=&>Kq<eI\]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=F$s"OXSK=&>Kp$MoBS>7Ta~>
+!liB.p$P$7[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbp
+/1<&+<J@`mg?O7WJaW$q!V6*5rrMueq<gZA[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&XqX.&J[Uh9H-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&Xp?i$2
+`l__?~>
+!quZ5p#ZAEZskc7.0VG(K<2c:J`_OGn)aZ=p<Wa>p?qb="7EO*0uk^H0iEY*^")r@"7EO*0u#.@
+0iEY*^")f<"3pQ>S:C~>
+!i2>Hp?qqR"7G<r`Qc(!`QdQ5p4;X_md]`Ep<Wd<pA=:Wp&jaFc,I`:"NAXJme6PGrq6H^k0:l[
+]`c=!k3hs:mK52>S1/s~>
+!m8N2p?i.UmdfZ"b/2E7"N&=<lLKMoJaW'r"7kmNqU,<FqXX(FqsF[ZmdfZ"b/231"N&=<lLOi?
+#4h3QlJB\#^UaQbb22FSp?i$.b/Rk?~>
+!rqu=p?)AB4QbM>]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd
+[(Wi[[(XH8k3df_J`cLbrpBd[dJj4?rpK[GrpE,8hSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd[(Wi[[(XH8k3i-/rpED@hSm18]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd[(Wi[[(XH8k3hs*
+"3(<6Ujr~>
+!h?&@p$P!:me6):hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\O
+k2,7Wk2,Oop4;X_mdKQGp?qYJe,TIA!Uf[WmR-^9p?qA*k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WhWE\WhWE\_me6JE9D7fImdArohWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Ok2,7Wk2,Oop@[hU
+3LlloJ,~>
+!liB.p$MtRmdBB&bME9^l@JASmdBKHo'Z)>qYJhDs8)cd!UfOSmKE+KmcrrRh>ud(q!J:UmdBB&
+^"rePlLaKHIE'E<J,~>
+!quZ5p#\F*k3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,
+hUUK5hUUcNmXaMOk3qF9mcNs*p@d,<s7ZK\!TrhGk!SS!mcNZ^hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5e_\j5e_\j=k3i'-9CCs1k2t4Ne_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,hUUK5hUUcN
+me,]Ec1_1-J,~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+!h?&@JaS*WJaS*W_sRUeS>7Ta~>
+!liB.JaS*WJaS*W_sRVT`l__?~>
+!quZ5J`_OGJ`_OG_r_'GpA^Y5~>
+!i2>HJaS*WJaS*W_sRU]Umrla~>
+!m8N2JaS*WJaS*W_sRVPb/Rk?~>
+!rqu=J`_OGJ`_OG_r_'?s7W7=~>
+"JhPs@VYmOrFu=Arb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+qe?+?rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;ICCAqZFC1=!/0n9~>
+!QrFYV1GXtWe%1$Wm7XAV#nfZ@=S~>
+"98)gmf)n[mXb(_p4;pgp<*(4me6ASp8!3~>
+!M#taF8]hRF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnV
+F)#H2rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrG):?!h?&8J,~>
+!QN:\Xok],WiCQOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)Wii@OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)-EaAOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA%J$,fSWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)Wdh1OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,Vo5WiiA)WiiA)WiiA%rM9S8b$ff~>
+!quZ^rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6H^p@dqRp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p'U6]me6)Bme6ASS:C~>
+"f.Z'@VTZVEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Es$/uF)(\q!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLSs(_OB!i2>8J,~>
+"Nn`\V5f*LJZaR,JZd+ts/Q'p!m8MkJ,~>
+!<7WDJbFZgJbHqR"7H3_Ujr~>
+$(Reh>$>BEC1:Y%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peIqiG-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@O>i!C1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:pe@Xi-%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1;[-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT?cC1:peC1:peC1:peC1:XU>+DB;J,~>
+$-(,YTqS<ZWhlPAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lJ#]?FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV'`4=Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lV15MAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhk3FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5g@*Whl_lWhl_lWhl_lWhlD[TuP5`J,~>
+$24Dep?qYBp?q?up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBJ+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmO%Yqp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBmXOrup?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?mG(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6&^p?qYBp?qYBp?qYBp?qYBp@eNVJ,~>
+"/MGb;Z0f!@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO5
+@TlrEr`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2
+r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2
+r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2
+r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2
+r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`T;2r`TS:>%1Z=;P]g;J,~>
+!QrF\SUmJcTn/ngTuiu4V4F<Nb/Rk?~>
+#QOMkme6)BmeuhZmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mec\Xmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n`me6)Kp8!3~>
+!M#tb8d&$a;G'Q2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8g[G.;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ8q0`2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G)F:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA7j;G'hZ;G'hZ;G'hZ;G-pd!h?&8J,~>
+"NJTLR?`>kJXM(WJXOQH"eD'P`l__?~>
+!VZQmmJutZmJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[s7QKnS:C~>
+$)F)eS>;[NS>;s1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NJ"3=)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUaDV-S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NUjno1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>:Y)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"4oS>;[NS>;[NS>;[NS>;[NS>;Z(J,~>
+$-L91`lc<D`lcGR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<DJ&]XNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDasP-N`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<Db(%FR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`l`eNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VR;`lc<D`lc<D`lc<D`lc<D`lc;0J,~>
+$30`!pAajdpAb/BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds!II>pAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajds*sbBpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpA]X9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZI+pAajdpAajdpAajdpAajdpAai^J,~>
+JLQ.!JLQ.!]IA@~>
+JRO+<JRO+<]O?<~>
+$(Rf]Un"6NUn!s)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NJ#&U1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS0k&%Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NS:@?)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUmuq1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;YgUn"6NUn"6NUn"6NUn"6NUn"6NJ,~>
+%%EndData
+showpage
+%%Trailer
+end
+%%EOF
diff --git a/doc/kmouth/kmouthctts.png b/doc/kmouth/kmouthctts.png
new file mode 100644
index 0000000..6d0b6f4
--- /dev/null
+++ b/doc/kmouth/kmouthctts.png
Binary files differ
diff --git a/doc/kmouth/kmouthcwcp.eps b/doc/kmouth/kmouthcwcp.eps
new file mode 100644
index 0000000..db0e111
--- /dev/null
+++ b/doc/kmouth/kmouthcwcp.eps
@@ -0,0 +1,3136 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: GIMP PostScript file plugin V 1.15 by Peter Kirchgessner
+%%Title: /local/src/kde32/kdeaccessibility/doc/kmouth/kmouthcwcp.eps
+%%CreationDate: Sun May 30 14:52:07 2004
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%Pages: 1
+%%BoundingBox: 14 14 596 357
+%%EndComments
+%%BeginProlog
+% Use own dictionary to avoid conflicts
+10 dict begin
+%%EndProlog
+%%Page: 1 1
+% Translate for offset
+14.173228 14.173228 translate
+% Translate to begin of first scanline
+0.000000 342.077918 translate
+581.132369 -342.077918 scale
+% Image geometry
+581 342 8
+% Transformation matrix
+[ 581 0 0 342 0 0 ]
+% Strings to hold RGB-samples per scanline
+/rstr 581 string def
+/gstr 581 string def
+/bstr 581 string def
+{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
+true 3
+%%BeginData: 201809 ASCII Bytes
+colorimage
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+JcC<$JcC<$]`3K~>
+g]%?3[%r82QAYj0XMsmas+14"s*t~>
+g]%NDd`T;<]"Yn.]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"YbiBtD$i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%qcJJDKs+14"s*t~>
+f`)*Js7ZKmJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds(;!)pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+p4<6ps3^js~>
+h>[fLUk=SXMh?q?K7Af3Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh>c&K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?Mp6hQJcF:#J,~>
+h>[NHb(7-c\cKP)JcC<$ec1.~>
+g])iuO7n/)JcF7"J,~>
+hZ!r-Mh?q?Mh?q?Mi3(;Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q(K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YAXmXbChs4@:$~>
+hZ!W5^4EkT\cKtEJcC<$fDg@~>
+h#@EKs8M]os7Z0drq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6En
+pAb-c!WVkEs+14#s*t~>
+q>UNQ[&!)I"-iNZ]n(fnK*.&"s3:P$!/#i\JW&iP".Z13pA"Z<~>
+q>Vc+d`T;<]"Yni^:M%i^:M%i^:M%i^:M2Ts44ci]!f2Y]!f2Y[XYls]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!cUi[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^ro]pAa-`\pqH*^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:Jg.]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Y`p^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i`ld<7q#>j~>
+pAYj#s7ZKmpAajdpAajdpAajdpAaj[rr7QCM>$rKrUta@pAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAai9s7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd(]X4/pAajd
+pAajdpAajdpAajdpAajdp@eN:~>
+qu7W'Uk=SXMh?q?K8YA?K8YA?K8YA?K8YA?ec4KWK8>-]SH&V=P`(0PK8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?ItNZ3Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?M]RM/
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?`W#l;^&@t]~>
+qu6]fb3QVL^?5I\]!f2Y]!f2Y]!f2]J$uqs]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y\oY<k[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roes8TgE]"Wa,J\('V!P[FirrCdOs*t~>
+q>]aRrr<#l!<<&l!<<&l"98)gs8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8;Qjs8M]ms7ZHlrq6?lJbFZgkP"]NJ,~>
+r;Rb]Mh?q?Mh?q?Mi34GK8YA?K8YA?K8YA?MuWg8JU<0!"jR(lH\6s#Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?IuAr;K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K--#(Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mkp(Hs-3N_J,~>
+r;QfS^?W9?^An5IZF7'IZF7'IZF7'EJ$uYkZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZ?*I[[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?Iir@l@]!d1$J\(!T"NpH<s2+d8J,~>
+qYpTis8M]os7Z0drq6?lrq6?lrq6?lrq?BlJbFilrr3)gp@eOcp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lpAY'lpAY)B~>
+rVlr4K7!QL"+,[%hZ!3Lc(t>k!.4Wr"FIi^eT:_:!-A-d!-A$a!-A-d!-A-d!-A-d&9E2NXJBT?
+HZOO\@VVF7K6.$=!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-ds8W+G!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-ds8W+G!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A'b!-A-d"`o$Ks5n\,K)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK)g8t
+K)g8tK)g8tK)g8tK)g8tK)g8tK)g8tK*-IQXPWsM!R7G>K)g8tK+rZbK?a,ipAajdpAajdpAaj2
+K7eOMK+?0"s7ZKds7ZKds7ZKdc2N>"Mt[2N9)npA~>
+rVm5U]!f2Y[^roYcKbE&%c5LB[^roY[^roY[atK@jK\nJ!#/+`rNZQ_9G@Id]s@\<]<_J:^Tr@'
+s73>$]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f1c[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^scLrq8A/
+cFUHq[^roY[^rp(pA4LZpA4LZpA4LZp>3Bh[^roYhY-g>qY'dZqY'dZqY&dW[^s'Ds8SAas*t~>
+r;ZTdqZ$<`rr;'Q"B#4:C;p/F"N>*m!)gN(s8T_)s8Th,s8N)eJbGT,qZ$<`o)JU\o)J[^rr3&f
+s8RT~>
+rr3GXK6r5tK7eNHc0kW*mf)>W`M@j5H\6ZtH\9TCUucY.;ZG#As5p+\>,:Tds3:R9q/cN7mW8C-
+!d"DAj)b8#!s!EBs5S2#s8I*>s8R0>s8I*=s6k%/rrW7Bs8TrW!Ug!eH[gZpK6r5tK6r5tK6r5t
+K6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5t
+K6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6q6`H\6Zt
+H\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6Zt
+H\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH\6ZtH_epSs7Ym[jq#G,H\6ZtH\6Ztk5Y/Tp@eIQ
+r8nB6K7eN'HfkA%s7Z0bmel2RH\6ZtPlLcs3WFU~>
+rr2u\qR-RIhX:72mf)JPg;`rs+6*=CZECL9ZECL9ZECL9Y-P49Y-P49Y-P49Y-P49Fo24A&7Ju]
+qu@"FY-P49Y-P49rVmM5ZECL9ZECL9ZECL9ZECL9ZEF3,9s4NrZECL9ZECL9ZECL9ZECL9ZECL9
+ZECL9ZECL9ZEF6-!3ZA%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZEF6-ZECM5s/r[,rrTL/
+ZMsl-ZECL9ZECL9ZECL9ZECL9ZEF6-!3ZA%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9
+ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECM(s0Aq][[so2`np.[o'ZMB!SYQh[LVTrpAb!_
+o()5:lK[NslMJ""lLsrOqY'LNmdBB*k3D71[KXPJs43&,J,~>
+rVuWc!<<#k!:KUTs8W&k!:Kj[!:Kj["7GmVmf)n[mf)n[mf)n]me3a[!!='rM\u?l"/PYamf)n\
+me6VZs7QH\rq6?[rq6?[rq6?[rq6?[rr3,hs8Vf\rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6Wc
+s8N)es8Vf\rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6Zds8Vf\pAb0\pAY*kpAY'mp?qqR!:Kj[
+!:Kj[!:Kj[#k%`m!:Kmep?qqR!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:KdY!:Kj[!:Kj[s8N,nmXb)$p&P-kp&OOSpAFpkpAb*b!q,dMqY'je!VZQlp&a[UmeleX
+rrM9^J,~>
+rr2tVqg/aAhWFP3s7YmCk2+XQqKiD>s+>B6CAr8SCAr8VC3+H2rc8'Src8'Src8?[F)ssT]qhaS
+rVm,AXIQu*8onbHErg#sqZ$P9!,DLS!,DLS!,DLS!,DK4!s&B$!<.$>CAr8SCAr8SCAr8SCAr8S
+CAr8SCAr8SCAn/7F8u7?rc8'Src8'Src8'Src8'Src8'Src8'Src8E]F8u7?F8u7?!-A/>!W[:V
+rr2rurc8'Src8'Src8'Src8'SrVlt@s8N)uEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSErp)tCAr8SCAr8WC=W?KF+J\1HOQG$k4\iTp?q)*hURkeHNVg\me6SY
+s7ZHS!S)8hHNVg\me6SYs7ZHS!S)8iHN_Uns#L+0~>
+rr4"QZF7'IZEh@(lLt8Xo'Yf.inhPX[^*?I[^,W,]&g'tFTB!a*;]^=*+?DYFo&9;s7*8jrrW9$
+rrD/`rVlu&s8N)[Y5eM+!3ZA%!!'2$rrN2'Y5\G$!:d5jrr]G(rrBs>J*-dJWj]4AZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZ@96f[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I_VXSOs8VZXlK[Bc_QpVU[^*?IhWjP&
+s8Dctp@@M6k2-*C#I^qHhWjP&s8Dd)p@@M6k2*DL[^*@$s8RrUJ,~>
+rr;ff!Uf[[s8M`lmeQSUs5iqWU]A);)#F:9+C`"aV#'f]s7,g]rrW9$rrD0SrVluns8N)[pAb-s
+!;?Hm!!)`lrrN2opAY'l!:fd]rr_uprrBt1rr2u\JbG]/!Uf[[s8M`lmeQPWme6GUs7ZH[r:U0Z
+pA"[fpAXLYpAY'mk5Tr~>
+s8N,MF8gLjF*i88hX9h2rsA,UhWE@iHZOOTrd4\FjD#3'k$$Wu]p,U_Pf;M9;XRH[CB+>4!<<'"
+!,DK4rbDB2s(_N4"T\T&!,?9Hs8Qj6s8Qj6s8Qj6rrQs8CAe)3CAn/9!<<'!C23_IrbDB2nnS4)
+"p"]'!!$bKrr3$"C23bJ!WZtMrVuk3s8W+6s8N(6rVlitr;X`N"MOi*F*%>-!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d"`o$lhX9h0!!V6AeZ=+=rd+ijHbJS(me6SY!:KjK
+$b^"rHZOO\^#nJFpAFpjmf)>U]jc>0H[C\Ns/\52~>
+s8N)]qQ^4ChX9t6q??<Pk3Cg?qQg/$1od^YY,\Y)Y,\Y)Y,\M)WiiA)WiiA)WiiA)Wih$U=k;<<
+OfFP']%5S8!/7GUWiiA)s8W#ts8N*"Y5SA%WiiB"rrK.&rVm$$s8N)!Y5J;0Y,_O%Y,_O%Y,_O%
+Y5b[&rrB5#rriE&rrB(%rVlr!Y,_F"(TOX<Y,\Y)Y,\Y)Y,\Y)s8N*!rr<&!Y5\G&!334$rrN2#
+Y5SA,WiiB%s/rC%s/u>#!!)rs5cUueY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y1EWmV65BTTX"[>hX9t4!!DBKhST,p&'F2&meZt[s8)T_lK76O
+U&;2,b3J9[qZ$ElqYKdJk2sg[rNZR?s8UAqJ,~>
+rr;ig"6T%FpAY*lp&jaVk2uO6s8W,m1@Fl(p?qYBp?qYBme6)Bme6)Bme6)Bme6)B]`;6mhS#/T
+Pa'/DhGO?mme6)Bme6\\r;clt!<DilrrVW^mem(cme6VZ"T\T&!:KRYrsnbjs8Vf\s8Vf\s8Vfm
+pAFpjpAP!p!<<'!me6VZ!q,dMr;RT$p?qYBp?qYBp?qYBp?qt\!<<'!!:KR[rrN2gpAY'n!:KRZ
+rsA,emf3=\mf3=\rVlitr;T%Mp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYSs7YUCJbGc1"6T%FpA=mmme5f*qXsp>rq?6hs7QQ_p>4[(p&NYB
+pA=mip&jaVhVS5)rVllJJ,~>
+s8N(pqf;mm^#nJNrVm&hhVRD.KDT`irrHkDrb;FBrb;FBqe?+?rb;FBrb;FBrb<!RC5]0XMj2cl
+e_Z4KMl_hGrb;gMC23eK!,?7XC&e82s8Qj2s8Qj6s8N*!rrE+7qu6s&CB+;6CB+;6CARr1!<3!(
+CB+;6!<<'!CA\&2CA\&2C&h`BC&h`BC&h`BCAn24!<6d6@f?<,CAn/5!,DE2s(_T6#ln`?rr?g6
+rr<&rs8Qg6@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@f0s@@fC*H
+@VTYBs35;0F.dRVK>$F0q>^WSk.QEEEr`<@jpUn_rr<'!p>4roXCD*K!3H1^rrE#trrE)]!N]c.
+Es(k1p*kL~>
+s8N)AqlUC6`ocRWqZ$Ecmc*6k`qlk<s5U*g,WLpGOk0Q`er>fO3$e@#s8N'!rMoktqu?\rqu?\r
+s8W*!s8N*"Wr)f&!36)!!36)!!35nq!!*#u#cdq)!!*'!!35qrs/Ptro;_chrrE%urVlktrVllu
+Wr)hrWrN)*!36)!!36)!!!)or`i9-Xs5KT#Y+Vp"ZGu%lq>^TVlGi\'!4r0l$hjGs!!)ldio]C7
+Q2Icb])Ljl!"&]%s7u]qk2s7?r2p.qs7U/W~>
+s8W&k#4D3Ymb[[2r;QromdBf*k5=oSmf3=Ip'i`:P`(dVs4,taP`%OVqY'sh!!)ukrrDrrs7Z?i
+s7ZKmrrE*!!<Dijrs8]!s8N)ms8N)mqYpNqrr38ts8N'!s8N)mqu?]iqu?9]rVultrq?<j!;?Bk
+!<Dijs8Vfmrs8]!s8N)ms8N'!qu=\0rr2uTrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6N`p?pf2pA+akme5N"rq6Qap@d&1p?qq[rrE*!#4D3Qc.2OUrq6NGp@dnS!<)rt
+!!Dr_c.2dd!:Kjd!3C\~>
+s8NX_C3+-2C3,$PhWF8+pAaj[rn[t#HYRV:F)#drs5RPt9(&5+hNY++Phsrdk">JZs8N'!r*o^+
+r;clt&Rte?!!*'!!+Q!.!+Q!.!<<)u!<<',!+Q!.!+Q!.!+Q!.qZ%%6s8N*!rr?O.rrE*!r;clt
+#@d`5!!*'!!<$C*s86@(s8?F*rr<&trrN3#s8;rtrtAlArr?O.rr?O.rr?O.rr<'!rrC)KJ#r[?
+@VTt!F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2
+F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2
+F)#c2F+7qGC3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2
+C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-2C3+-Bc/.R_!;?Hd!!(m4
+`Hu?@C3+-2MrrRHmf34c%dr3(k)3DaF)#c2MrrRHrW!!!pAP%#e`McnF)#c2F3Xab0n9~>
+%KH:9WiiA)Wii2Lk2u76q@<5iio9+GTrP8qY,\Z)s5TpbJH/6perctpNS;rS!.k!Cs8N'!r2'Gn
+r;clt&Z,O-!!*'!!2]_q!2]_q!<<)u!<<',!2]_q!2]_q!2]_qqZ%&$s8N*!rrAnqrrE*!r;clt
+#GqJ#!!*'!!<&bms88_ks8Aemrr<&trrN3#s8;rtrtD7/rrAnqrrAnqrrAnqrr<'!rrC*9J("A6
+RAI'dY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y(*ISWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)Wii@uf&l)p!;cQc!!)$@
+cCq8@WiiA)U#t(go(r:b%eAW5k+Rp?Y,\Y)U#t(grVuuqpAP%#g?,)kY,\Y)Y2]K]@=S~>
+rr;lh"O6)sp@eFarpBgDc2757s#f`Cme6)Bme6)Bme6):p?qYBp?qYBp?qYBp?qYB`;iNehNY++
+Phsq_!58*op?qYBpAb-mp?qYBpAb0k!<<'2mf3:e!<<'!mf3:emf3:es8W&us8NH,mf3:emf3:e
+mf3=a!"AT$rrE*!!:Kme!<<)t!<<',mf3:e!<<'!me6)BrVm#gp?qYBr;Qlep?qYQrr<&trrN3#
+s8;rts&/:brrDKerrDKerrDKerr<'!rrDK\me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)BpAaj:mXb)*p'&_'me-V\rr;uus6]pEc272<^%UUVpAb'k
+"nqBHp:]#Sp&i#%k3i3Ks8W&u"6T<jebo.?rrAjF~>
+s7ZJ-!+PqB"(HW6k4eptk1+ff@VT@eCB+<C>%1ZE>%1ZE>%1ZE@Tm5E@Tm5E@Tm5E@Tm5E@Tlst
+XH^Eue\-mBk#u4t@Tm5E@Trg3!*Wi8@Trg3!*Wi8s8N*!rr?O.rr?O.rr?O.rrE*!!*Wk3rr?O.
+rr?O.rr?O.rr?M3qu7T8s8N(.s8N*!rr?53>6"U&s8N(.s8N(.>%1\6s)S0D@Tm7@rrE*!!*Wi8
+s8N*!!<3'!rrE*!!*Wi8s8N*!rr?O.rr?O.rr?O.rr?O.rr?M3@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E^&O!oC1@0W!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB#CG=ihX:+;pAP$qe`PD/@Uf=O"_)i8e^a*b!<:RXhKrF8
+C2.3mHf!<'me["aeHOfV>%25UrbDK5!%EE~>
+!VZBdWWJIFk4eoYk1Z)or2TesBVhE!Tr"HZTr"HZTr"TZV4j`ZV4j`ZV4j`ZV4j`ZD#bPq])U?m
+E?"sqV4j`ZV4j`Zs8N(mV4j`Zs8N(mV4mqh!<<'!V>pPqV>pPqV>pPqs8N(mV>pPqV>pPqV>pPq
+V>pPqV4med)Z]p<!2]_q!<<'!Tr"I_rrE*!!2]_q!2ZBcU&G"3!266_V>pPqs8N(mV4mqh!<3'!
+!<<'!s8N(mV4mqh!<<'!V>pPqV>pPqV>pPqV>pPqV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4lK?^6POGWhHEtQ/^rco(MqRrW!)Xk1Z)or2Kmb
+inE8WqZ$cUg>\B[r2KmbinE8WqZ$cUg>\B[ql9\r!+CB~>
+s8NDnp?qYBp?o<Up@nUpp?''Vme6)Bmf3=dp&OO[p&OO[p&jaVp?qqR!:Kj[!:Kj[!:Kj[%.9nk
+(j!Cje\-#H!1a&^!:Kj["Rc<i!:Kj[0(/c>!:KRSs8N*!rrDcmrrDcmrrDcmrrE*!!:KR\rrDcm
+rrDcmrrDcmrrDcdqu7H4s8N)ms8N*!rrDK\pAb-ms8N)ms8N)up&OOZs"aZKp?qYSrrE*!!:KRS
+s8N*!!<3'!rrE*!!:KRSs8N*!rrDcmrrDcmrrDcmrrDcmrrE&l!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6Qas8VfCmd>Sume6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6'Xp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qX]me6)Is8E!*me5eVmdBf:p?o<emK!:a!<2Bk[+4U4
+p?qX]rpBddqZ-W`$FJ@Op?qYBpAb/_J,~>
+%/0+(@VT@e@VTB7hVS)/rn[oi>&%M]@VYrCi*$B1s37XPc2Z&_>6"U&!<-1#rr<&u>6"UL!<<'!
+>6"U&>6"U&>6"U&s8N(&>6"U&>6"U&>6"U&>6"U&>6"X%!<<'+!<<'!>6"U&s8N)u>6"U-!<<'!
+>6"U&r*'%!rEB7$!ruO)s8H4%rsAc+!<3'!rrE*!!<-1%rt>D4rr?7&rr?7&rr?7&rr?7&rrC)C
+"K_Wf>$?Dj@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@aC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe@clP(k4\NJ
+!!)0\h?m^qC1:peC1?&EebK1Tc/)o-C2.3m@Ue3=e`QT(!"S/Ac/)o-C1:peC1@5C.=_~>
+s7Qf"V5gAlV5f73injM3/DfCKKpes;Whl`qs.,jSTq.mJTq.mJTq.aJSY;UJSY;UJSY;UJSY;UJ
+SSe0&%r%`.Tq.mJTq.nWrrAa`U&G!B!25sWs8N*!rrAVirrAVirrAVirrE*!!25t`rrAVirrAVi
+rrAVirrAVis8E#uru;%=rrAVirrE*!!25sWs8N*!rrAVirrAU`SY;VQ!&:1<Tq25`!1j/iTq.nW
+rrE'!rrE*!!<<'!Tq.nWrrE*!!1j/i!1j/i!1j/i!1j/iIfQ%5SY;UJSY;UJSY;UJSY;UJSY;UJ
+SY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJcMtbDSZ8NdV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV15MAWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhh&BV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAGk2P7_o()b[%dMp1k(T5'V5gAlL#U\;q#CoUie<Al
+Whl_lL#U\;lLOlR%dMd!ie<AlV5gAlV>pC#J,~>
+s8Vrh!2TV^q>gN_!MnlUpAb.8me6)Bme6)Bme6)BmdBf:p?qYBp?qYBp?qYBp?qYBV"k!$SG)CE
+me6)Bme6\\!;>jSrVnDKp?qYSrrE*!!:Kme!:Kme!:Kme!<<'!p?qt\!:Kme!:Kme!:Kme!:Kme
+rW)uu*!$$=!:Kme!<<'!p?qYSrrE*!!:Kme!:KRKp?qkZEVAhomf3:emf3=\me6\\!<3'!!<<'!
+s8N)mme6\\!<<'!mf3:emf3:emf3:emf3:eme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6ASp=8;Vp7_0[V#Kc`pAb0l!!)`lmK'-Gr:U5gmcNs5
+!!DBOUt,D:"f1SKme6\Z!!W)ak3f%qqtC'i!2P,~>
+%Hd(^@Tm5E@Tlslk1/Vl!'ou&k06e->%1ZE>6"V3;Hct%;Hct%;Hct%>#JO%>#JO%>#JO%>#JO%
+>#JO%;IZa-s/]Br>#JO%>#JO%>#JQ#rr<&rs8N*!rs\s3s8N(&s8N(&s8N(&qu6Zs>5S='!*]F&
+!*]7!#QXo)!*]F&!*]:"rrE*!*<9:Crr?5#>#JO%>#JO%>#JQ(rr?5#s8Q8#s8N)urr`?%rr?7"
+s8N)rrsJg1s8N(&s8N(&s8RQK>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#N'6HW"<V@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E@Tm5j>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE
+>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE
+>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE3*Kcp@Tm5E@Tm5E@Tm5E@Tm5E@Tm5E
+@Tm5E@Tm5E@TqXNe`Q;n!!)HTe`P+S>$>B=@Tlsle^aHq%b9E>;Hd75>%1[le^a*Ur;[>qe^`M[
+;HdO5@Tm7/p*kL~>
+s7-PkV4j`ZV4i=ok2,D$!&*csk14g?Tr"HZU&Y.hSY;UJSY;UJSY;UJTq.mJTq.mJTq.mJTq.mJ
+Tq.mJO[T-J$qQAOSY;UJSY;UJSY>o[!!)orrrE*!%03+%rrAbmrrAbmrrAbirrE+nqu6g"U&Y,m
+U&+cp!<<'!U&Y,mU&4li!<<'>!29Gm!25sWSY;UJSY;UJSY?)`!25t`s.Q"`rrE&u"9AK%!29;i
+rrDrr9E:ddrrAbmrrAbmrrAa`Tq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJ
+Tq.mJTq.mJTq.mJTq.mJgAeUDTqQt4Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZ
+Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZ
+Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"H,V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`ZV4j`Z
+V4j`ZV4j`6hWE\[md^>Xo'YAsep3COV4j`ZIH&u7q#CoYidHf[Tr"HZIH&u7lL+TN%dMd%idHf[
+V4j`ZV=sUkJ,~>
+s8NJpp?qYBp?o$Mp?))H!&+'6p?&1-me6)Bmf3=\me6)Bme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+p?qYBhJ2uh$u4>dme6)Bme6)Bme6MW!!)orrrE*!%06,%rrDcmrrDcmrrDcirrE,nqu6g"pAb-m
+pA4dp!<<'!pAb-mpA=mi!<<'>!;?Hm!;>jSme6)Bme6)Bme6\\!;>j\s7Ym\rrE&u"9AK%!;?<i
+rrDrr9E=edrrDcmrrDcmrrDc\p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBs8VfCmd>Sume6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6'mp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qXUme5f:pAY*ms7YmSk+pl%p?qYBV!dC-q#LH_%&DGAme6)BV!dC-p@eFb%ef&Qm\JD$
+p?qYBpAb/_J,~>
+s5j;jr`TS:>$=P"hUU0ErW!/jk2+sr5t_)Z"(L-eF8f&;9)_]g9)_]j8lAPZr_`_gr_`_gr_`_g
+r_`_gr_`kk0f`-(r_`_gr_`_gr_`bh;Z6Xp!!#pqs8N'19)nnk9)nnk9)nnk9)nnk9)JVi!(p/e
+rrrHqs8N'k;Z?[u!<<'!rr3-os8N'k;Z6Xq!!l3srr>[krr>[j;?0>g;?0>g;@H1trr>Yh;ZHbp
+s8N)urriE&rr>YhrVult!D68frrE*lrr36rs8N'ks8N'kr_`_gr_`_gr_`_gr_`_gr_`_gr_`_g
+r_`_gr_`_gr_`_gr_`_gr_`_gr)*Mer_`_gr_a!Gs&r;u>$>D7=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=pAG>9!$n"ebnhGk2+sr5tY<a@Tlr$k0;H=r9agPe]m5B8m5^'=p..R
+c.1tR!!Lisk!;W<=p/;<md;f[~>
+s6f`W"b",EhVRPs!!`#Zio[shNVoJ.lMn/\R@Tb:R@Tb:R@Tb6SXH%:SXH%:SXH%:SXH%:SXH%:
+SXF2+SXH%:SXH%:SXH%:SXH&Is8DuuSc/Tg!"bRurrAJerrAJerrAJerrAJarrN1gSc&Kl!1Ele
+!1BDWrrW9$rrE&u"e#Dj!1BDVs8N'ARK*9eRK*9eR@Tb:R@Tb:R@Tb:RK*9eR@TcGs.02i!<3!%
+!<<'!R@X<Vrr<(fSc&Kg!1Eid7[a;V!1Ele!1BCGSXH%:SXH%:SXH%:SXH%:SXH%:SXH%:SXH%:
+SXH%:SXH%:SXH%:SXH%:SXH%:SXH%:SXH&.s.PF?JYAd2#(=5FhVRPcrpg6Xio[shNVoI\D<BR/
+lL+*2mdBAsg?*73r1O71k1\\WqZ$cUg?*73qk4)bnmR%~>
+s8W)l!:Kj[!OUDVmJut[!!`JsmdAVihZ!3Rme6\\p?qABrpBd[rpBm^mdBfJmJut[mJut[mJut[
+mJut[mKE7OS>>lXmJut[mJut[mK3+Mmf!1b!!)Hcs8N'1mf3:emf3:emf3:emf3:emed"c!:K:Q
+rrrJks8N)emf*4g!<<'!rr3/is8N)emf!1c!!hrlrrDKerrE&d!;?E[!;?E["SV9`rrE&ds8N2h
+s8N)urriE&rrDKTrVults6fgb!<DQers.ulrrDKerrE&d!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!qu'UrpBd[rpC$bs8VN;k4\6Bp&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&sgWp9`BLmf2tfs7ZKdmdAVihY-C:p(*DUk3hsCpAajdp?q)2Ph#a+
+"n%WCk3hs?!!M`PmZc9$p''mXpAb/gJ,~>
+s5"&[>#JO%>#It-k5O4,mJutKmcNYH0iCnQ;Hcu*s/\gj8lA8Z8lA8Z8lAPZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'jc!!>hk8lGTf&kZ%o!!#nh!!#nh!!#nh!!*'!rW)uu
+!ru4k;Z$M!;G$oh;G'jd!!?+!!)!4j"\Jap;G'jc!$Y$58cSih8cSih8lA8Z8lA8Z8lA8Z8cSih
+8lA7]!)`ds9)\eo8cSih8lGTf"%lH`;Z$Lq;G-og6qRFZ;G$oh;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;H!Pp8kOS:;Hct%;Hct%;Hct%;Hct%
+;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%
+;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct.>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>"WPlrn\:U!!)HTk2pD5;Gp[r>#IB;hUVE%s5")C
+8lAPj;Hc*;hUVT*s6fjds5")C8lAhj>#JPdjsbf~>
+s6BHOs+q3Iinihc!;?!Ok2qY7NVo=Kf)O%>RJd-aRJd-bRK!9eRK!9eRK!9eRK!9es8E#urr<&u
+RJ['bRK!9dRJm0gR/d5TrW!"f!!*"dr;chbrrE(errDYYrrE"crr<.h!!&Gd!!8Pg!</Db!<&>`
+!<8Jd!!\hk!1B5T!6CQ2ScA_<NIdXnSc=NUk2P7[mJm7XmcNYkAW?VY"(gKOhY@0OiW3VIr1*q$
+io8ho!!2NYrW)uX!G.,bScA*X@=S~>
+s8NDnp?qYBp?pJ4pAXIirrE)mp?qXUPhtj%me6)Js"s0;me6)Bme6)Bme6ABp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYQ!!DZ_me6SZ'(5J]!!)`\!!)`\!!)`\!!*'!rW)uu
+!s&&_pA=mpp?hn\p?qYR!!Dop!:Kgd"mu?jp?qYQ!$^k)mJm7\mJm7\me6)Bme6)Bme6)BmJm7\
+me6&K!;6Bmmf!1imJm7\me6SZ"7GmNpA=mkp?qn[7d^6Vp?hn\p?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qt\`RXDEJ+i=(me6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmU>hWp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp=68<rpC<s!!)`dme3`HhX:+*p?n1EmeHk_mK]!,
+mdBf:p6>RErVuums8E#umL#3/me6)Bme6\\S:C~>
+!T)B&;@Y^Ok2+tWmdBf2k05>89)MQiHiN5#62jIV62jIY5tXa8r^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m2W9)APi!(ojLr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m5X8jWGK!($TV"[S(H]fA]9;P-hs3L&[_hW=e<p?(M^.61#u
+;?/0FhY@-RhW?7Qr)*MDrndYTrpC!a!!(m<.7*i/!p8>gJ,~>
+!UAhCSITM:k2PC_mdfr:lIK*TOo1bL[f>c`Q'mo*Q'mo*Q'mo&R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*RJQr5!0rt;R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+-^g6fQ'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'moOs4VaXR=Up%SITM:k2PC_!!)TXlIK*T
+Oo1aP<T`<#q#LHW!EG!SSHW$Uio0q<rpC!]!!)0D<JgUD!q,>^J,~>
+s8NE!me6)Bme6@U`Vo6)p(.2sp?%:7hY-C2me6ASs7ZH[!;?E[!;?<X!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!qu'MqYpTsme6YJ
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;??Y!;?E["SV9Ws8RSUhX:+*p?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qWcme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BXMt/+rr<K-p@dX,XPW[=p?qX,rpKR^s6^,Ec1^l!
+p?mS4mf*8"pAajd!!)HTK?a,Xp?qYBs8SmF~>
+FNr?.;G'hZ;G'PI0pLhWk2uC2mZ]FK3D)nA8lA8Zec1P"5tXF85tXF85tXa88jQ'88jQ'88jQ'8
+8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88c\kj
+rW%F?5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXFm8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'89'6.g5tY$I;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8g.));G'hZ;G'50Pigibk4\N:PVF:@8kMuR;G&(g
+k2,7_rU(6jmcNXS5tXaI8l?egk2,7_rU(0hmcNXS5tY$I;G'j;hC3s~>
+!TN8;R1=pVWoiI/lLsr>Wa/GHOo(OJk5W0!PlLg`s8E"LQ/Ru3RI:*TI>rfGT:$1C?)m&LlK\*:
+m]'PhH'/#m%nu!Fk3D7"mdfrBmcrq.L&@>L9]G3slK[g*o()MBlK1coqjIKH!+CB~>
+s8W)d!;?BZ%b6KVp?qYJs8Vf3MhA_*rpEn^me6\\p@dqJme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qVSrr;rt
+J+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)BmO7esp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYSs7XFgmdBfJmJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mL[p,`V/`npAb0d`J]A^k3hsBmK8+0p?qnQ
+rr<#l!q(]crU'g^KC8I$rV$6js7QN^K?aD`"nqBPs8SU>~>
+s3:=2$ooG.PeH4uUfnTP0gYY.<g<XX;F*</3C,Yk3C,Yc5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4krW%F.5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4Z
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C0J@ZnXR56%MY#8dm^&;O"lW`M?ZS(bn>R
+8c]LcrndV9s6^$`md:WPr(6u$k5O69k5XiPp?q>[62O7Ue]fh!~>
+,3%IIQ'mo*Q'n&*I8G'_b3%-XI7-b?KpA'kR?a2*^An&#Y*&\`JW\iPJ'.fBD1Rh7R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R=:EhQ'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mnc:j&VWk0gP`6qh0GQ'mo*Q'k&&
+irA0>l4ECSp?qK>JXMpkR?^2&io]D%l4<=Rp?qK>JXMdkQ'mp"iaI?~>
+s8O27me6)Bme6ABc&8+2hY-*VS9'=QhX:+*p?qYBpAb/pmf!3;mbdG^pAaifc0"Hfme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BI.$^rp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?p1`SAj@Yk09E;K:Lfdp?qYBp2g3#
+!VYs[p'Uins)ZHYp?qYBF8bM-p?qnQ%KH/%F3XFHp?qYBs8SmF~>
+s2>")9)_*V9)LsU+;"MX#S7h%.60[d5t_,B"\M)"s5lrQ5l`qE5m',55rnp1!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!]`P,r]piN6&YdC5rh4s9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V
+9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)_*V9)V$V+;"MX"qVV#.60[dr]pTX5p5e*!"f,q
+"%kjF+S5pA&4&TSr]pWY`Q]i^~>
+%bfd%Q'%>oQ'%2oNIb5#r]CcX6rdfLNKoWkOd2&oQ/;Q/R=UKYOTN,os*p/RM34'cQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'#gHOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd1oW=[`6O$p[3\AV#i+Od2&oO^7TA
+#=O-*Od2&o?1^5d7"LJcOd2&ohVqso~>
+s8Vi]!nEffrc86XF,Qj=k54QIp?qq[!Uf[\mJut[mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;??Y!;?E[s7ZKm"R`t[me25"T'c[1S9t6V"_r+:Us8'!mJs'T
+ErgX4r9aQ\oQ(%[c26r/rrAR>~>
+!QDbG5liu#r$_Y$3VPfK9%Et(>!Y/73C,Yk3B;RT3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,ZF5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh6,s8Q7W3B;XVRm@'81&NI$0ff"p!BDV&+9<oOq`t6C
+.J=kb.678ks2=seJ,~>
+s4RpIOd2&oOd22oQ&UK?C&VBMBm#,hQ'%>oQ'%>oOd5)/m\,2kNf=@-b5_L8D1RP+OaiXYQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'#[DOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&o
+Od2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd2&oOd1o[F_Uh\3,*MhNKoWkOd2&o
+Q%<XL=]JU)=]JU)=]K0eQ'IJsOd1K3<EW=)<EW=)<EW=9JX)@_Od2'cg0oL~>
+s8O&3me6)Bme6ABp?peNXIPNFXM*KYp?qYBp?qYRmf*7dmK_nBk3hC"k2q0]k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hAQmcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs2s8Veoe`Q;fJ+i=(me6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+mWJ6kp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?peNXIPNFXM*KYp?qYBp?qYJ
+/Cgh[P`(caP`(caP`)Wnp@dqJme524Mj0-aMj0-aMj0.$eb8G)me6)Ks.k/~>
+*ONL?5rh4k5rgqk3C,Yc0f^sK0f_6[3C,Yk3C,\)5n$ZAs8TH03C,Yk3C,r\3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,YkE&g3E
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5s^.cs8Q7O3B@()IlTeT5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+6$51R3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yc0f^sK0f_6[3C,Yk3C,Yc
+/3u!N0f^sK0f^sK0f^sS3B9Ac5rh4c3AENK3AENK3AENK5rh4k5rh6E]d\I~>
+s4/-KOc>K_Oc>?_NKK3[JUr6#JW5YONKK3_NKK5"OTh04s8UN@JW5hP#a)R`s8Sd,I>.Z_IuTSM
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_O`QMENKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3[JUr6#JW5YONKK3_
+NKO4"%"WhPI<g6dI<g6dI=_BW)j-,BNK&L;H$ssdH$ssdH$t7'NKK3_NKMfG@=S~>
+!VZQdmK)J,rm_&+k4n?EpAXLYrrDcljob&6k3i62!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK#4CXAk2u+*rr3)oXNfUQm[<JDk2-*f!T)u4mJtf2blH;imJtf2blH;j
+mf3:eS:C~>
+s0O:B3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh4k5rh4kXS2\om]<LBMh?Y3Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?B8_D#
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8Yu$`W#lAZoKQi0f_7D5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+ImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3@$mN5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k['VQ<~>
+*S/Z$NKK3_NKK3_NKK3_Oc>K_Oc>K_Oc>K_Oc>M%N<b<cqZ$TdcH_!PR(<XAdbaj#s43$@H%GpR
+J!#_QNKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NIR(MOc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc:QINKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK4OdU@Y~>
+s8W)d!9X:K!9X:K"6T%>k5OcKk5OcKk5OcQk3hC"k3hC0rrMinJbGH(r;R,thQ4]Hk2u*omcON:
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K"m57@s8SmF~>
+s/Z5]62ikE62ikE62NYB62ikE62ikE62ikM5rh4k5ri,MhLY]hrsHGS0ek[K5rh4k62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikH6*..:J,~>
+s3;R?NJWXONJWXONJWXOM2d@OM2d@OM2d@OM2dAiN<>$*cK]u\OoG[;V.FLlJVf6_NIQeEM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d"ANJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWW=M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OcI--O~>
+!VZQRjoFiKjoOoDJcCf2"R`@uc.2dT!:GF#J`bqR!quYaJ,~>
+*NZ&&3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh713<2AD3<M!.F*iJ.R%+A5C.^300erVe!($TE
+ImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3Ia=T5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rg,T3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,[,Ua^f~>
+.F-(qM2d@OM2d@OM2d@ONJWXONJWXONJWXONJWXONJWXONJWLCQ*.Fl`dbkF_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T$Q3`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`jVn4EG9E8JVAr;IuT;EM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM1:MA
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJT!AM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2dA;b$ff~>
+!WVlTjoF9;jp0c*hVQfFmd>Z"R.gRJ$Kf%']uAOPk2,7WJ`_OGhrY"?p8!3~>
+-Cgkd3AENK3AENK3AENK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKpb;atr\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%pG%.X0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^t<3AENK3AENK3AENK3AENK3AENK
+3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK
+3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK.60+C0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKS>7Ta~>
+.`TVVI<g6dI<g6dI<g6dH$ssdH$ssdH$ssdH$ssdH$ssdH$ss`F`h\Drb[.!D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j'Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$D/jQ@H%16fI<g6dI<g6dI<g6d
+I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6d
+I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g<jH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$sreI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g7\b$ff~>
+*VTNPc,IrHc,IrHc,IrH`QcBH`QcBH`QcBH`QcBublu)2`PoO(rj70V[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gWFXL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XSoO+^&Q(Jc%!^W`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`Q`nOc,IrHc,IrH
+c,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrH
+c,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IpO
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBHpA^Y5~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@p?mr=!<7W<JaS*W_X7L\Umrla~>
+!liB.p?mr@!<7W<JaS*W_X7MOb/Rk?~>
+!quZ5p?%B5!<7W4J`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrRi$rrCa?rr@W<JaSfk"#6UA.=_~>
+!liB.p?ho\NrRi$rrCa?rr@W<JaSfk"*r&/@=S~>
+!quZ5p>u?QNrRhqrrCa7rr@W4J``6["3(<6Ujr~>
+!i2>Hp?hoYNrSh@rrE&drrE&drrDTWrrDo`qZ,dHrrDZYrr@W<JaTB&"$)mI.=_~>
+!m8N2p?ho\NrSh@rrE&drrE&drrDTWrrDo`qZ,dHrrDZYrr@W<JaTB&"+A23@=S~>
+!rqu=p>u?QNrSh8rrE&\rrE&\rrDTOrrDoXqZ,d@rrDZQrr@W4J``fk"3pQ>S:C~>
+!h?&@p?hoYdf0U'`Pp*P^!5F-`rG`"!!*#drrE&d!!)NVrrDrarrE#c!!)0LrrDf]rr@W<JaT6"
+"#6UA.=_~>
+!liB.p?ho\e,KaNf##/HcFV$Lp;[.*mJm7dmf*:dmJm7Vmf*:amf*:cmJm7Lmf*:]mf*9<mXaf"
+mK7aW`aOA~>
+!quZ5p>u?Qdf0R7e^`O5c.1sqs7PLS!<2-\!<2*\!:].N!;kpY!<)$[!9WGD!;GXU!.j9`k+Uo>
+`W,Y-J,~>
+!i2>Hp?hoYe,KLC^#&_f"8:9PhT,Zhmf*:emf!4dmJm7dmf!4cmem+cmed(_mf*:_mf!4cme?e]
+med(bmf*:dmem.cmem+emJm7dmf!4cmf*7gmJm6<mXaf4mK5J>Ua^f~>
+!m8N2p?ho\e,KLC]%6i["7jmKg;j6dmf*:emf!4dmJm7dmf!4cmem+cmed(_mf*:_mf!4cme?e]
+med(bmf*:dmem.cmem+emJm7dmf!4cmf*7gmJm6<mXaf4mK7mWb$ff~>
+!rqu=p>u?Qdf0?mk5G;^p?'?Va8bhprrE)]rW)u\!!*#\rW)r[r;Zi[quHZWrrDlWrW)r[p]1<U
+quHcZrrE&\r;cl[r;Zo]!!*#\rW)r[rr<,_!!%T4J`a<$"3pQ>S:C~>
+!h?&@p?hoYdf0CB^#o7m!qsU`aT(r$rrE)erW!Dq!!)HT!!)Ee!:K7T!<2Ed!!;Qg!;u9b!;c-`
+!!M]i!:K:S!!)Hd!!M]i!:K:S!$:P.!:Bgemd:&Tmd:&Tmd:&Tmd:&Tmd:&TmJm7Tmf!1fmJm6<
+mXaf5mK52>S1/s~>
+!liB.p?ho\df0C>[c[Mf!qO4RaT(r$rrE)erW!Dq!!)HT!!)Ee!:K7T!<2Ed!!;Qg!;u9b!;c-`
+!!M]i!:K:S!!)Hd!!M]i!:K:S!$:P.!:Bgemd:&Tmd:&Tmd:&Tmd:&Tmd:&TmJm7Tmf!1fmJm6<
+mXaf5mK7aW`aOA~>
+!quZ5p>u?Qdf0CBc0kK/!R9KBs7POS!<;3\!"J&j!9WDD!9O7]k2lXDroX4\!p0I_r9""ZqW@eX
+"Qf[ak2uXC!9X7\"Qf[ak2uXC*p*G&jo>DDjo>DDjo>DDjo>DDjo>DDjo>DD!!)0DrW!#^!!%T4
+J`a?%"3(<6Ujr~>
+!i2>Hp?hoYdJj:A[-%8c!PR%*s7Pg[!!)Hc!!Vcj!:BgerpKdd$LRlomd:&Tmd:&Tr9jRbqsOIa
+rpKdd...'8md:&Tmd:&Tmd:&Tmd:&TmJm7TmJm7TmJm7TmJm7TmJm7T!!*#drr<8k!!)HT!!%T<
+JaTo5"$)mI.=_~>
+!m8N2p?ho\dJj:=Y2]?Y!P6Rus7Pg[!!)Hc!!Vcj!:BgerpKdd$LRlomd:&Tmd:&Tr9jRbqsOIa
+rpKdd...'8md:&Tmd:&Tmd:&Tmd:&TmJm7TmJm7TmJm7TmJm7TmJm7T!!*#drr<8k!!)HT!!%T<
+JaTo5"+A23@=S~>
+!rqu=p>u?QdJj:A`U<X'!R9KCs7POS!!)0[!!VKb!9O7]roX4\$K_<gk2lXDk2lXDr9""Zqr[nY
+roX4\.-:L0k2lXDk2lXDk2lXDk2lXDjo>DDjo>DDjo>DDjo>DDjo>DD!!*#\rr<8c!!)0D!!%T4
+J`a?%"3pQ>S:C~>
+!h?&@p?hoYd/O1@XQKE[!Nb_3s7G^e!:BjTmJuYTmd:&TrpKdd$LRlomd:&Tmd:&Tr9jRbqsOIa
+rpKdd([_8'md:&Tmd:&Tmd:&Tmd:&TmJm7Tme["amf*:emf*7gmJm7dmf*7kmJm7TmJm6<mXaf5
+mK52>S1/s~>
+!liB.p?ho\d/O18Y29*V!rAq^b5_,%$NTSpmd:)C!:K7T!<2Ed!"/,o!:K7T!:K7T!;u9b!;l3a
+!<2Ed!#P&'!:K7T!:K7T!:K7T!:K7T!:BgemdBrPs6fmes6fme!q$$grpKdd#4;Hkmd:&TJaS*W
+[-e$Ab/Rk?~>
+!quZ5p>u?Qd/O1@`U<X'!PRpDs7GF]!9O:DjoFNDk2lXDroX4\$K_<gk2lXDk2lXDr9""Zqr[nY
+roX4\(Zk\tk2lXDk2lXDk2lXDk2lXDjo>DDk5,/Yk5PG]k5PD_jo>D\k5PDcjo>DDjo>C4k(2[%
+jo`U&p8!3~>
+!i2>Hp?hoYci4(7Uu)%L!T(3+s7GaY!<;Kd!<;Ke!<2Ed!"/,o!:K7T!:K7T!;u9b!;l3a!<2Ed
+!#b2)!:K7T!:K7T!:K7T!:K7T!:Bgemd:&TqsOIas6fme!q$$grpKdd#4;Hkmd:&TJaS*W[-e#V
+S>7Ta~>
+!m8N2p?ho\ci4(7V:tkI!SY!)s7GaY!<;Kd!<;Ke!<2Ed!"/,o!:K7T!:K7T!;u9b!;l3a!<2Ed
+!#b2)!:K7T!:K7T!:K7T!:K7T!:Bgemd:&TqsOIas6fme!q$$grpKdd#4;Hkmd:&TJaS*W[-e$E
+`l__?~>
+!rqu=p>u?Qci4(?^#o7m!TqYLs7GIQ!<;3\!<;3]!<2-\!".ig!9WDD!9WDD!;u!Z!;kpY!<2-\
+!#ao!!9WDD!9WDD!9WDD!9WDD!9O7]k2lXDqr[nYs5s=]!p0I_roX4\#3Gmck2lXDJ`_OG[,qJ8
+pA^Y5~>
+!h?&@p?hoYf`)!&hYI0Qm[W_DrrVnip<3L.mf!4dmf!4dmf!1omJm7TmJm7TmJm7TrW)i`rrE#c
+r;[N!!!)HT!!)HT!!)HT!!)HT!!)Hd!!M]i!:K:S!;u9b!<;Ke!!)Hd!"/,o!:K7T!:K7T!.jQh
+m^2Ba0r1<gJ,~>
+!liB.p?ho\f`)!#gA1aMm[<A=rrVbbo#q(*mf!4dmf!4dmf!1omJm7TmJm7TmJm7TrW)i`rrE#c
+r;[N!!!)HT!!)HT!!)HT!!)HT!!)Hd!!M]i!:K:S!;u9b!<;Ke!!)Hd!"/,o!:K7T!:K7T!.jQh
+m^2BaH-4-8J,~>
+!quZ5p>u?Qf`)!/k5##Yp9aPlrrVo-p<3L.k5GA\k5GA\k5G>gjo>DDjo>DDjo>DDrW)iXrrE#[
+r;[Mn!!)0D!!)0D!!)0D!!)0D!!)0\!!MEa!9WGC!;u!Z!<;3]!!)0\!".ig!9WDD!9WDD!.j9`
+k-X7Q`W,Y-J,~>
+!i2>Hp?hoYf`)#KSCRK9!kk,lr;Qf)hTPrkmf*:dmf*:bmf!4cmf*:dmed(]me["amf!4cmf*:e
+mf*:emf*:emed(bmf*:cmem.bmf*7gmJm7dmf!4cmf*:emf*9<mXaf5mK5J>Ua^f~>
+!m8N2p?ho\f`)#HS_!Z;!kOrjrVlrqZI[5!o^;_ZrpKddr9jOarpKddrpK[aqX44\s6fjdrpKdd
+s6fmes6fmes6fdbs6fmerU0UarpKdd!q$$grpKacrpKdds6fmeJaS*W[-e$E`l__?~>
+!rqu=p>u?Qf`1uY!9X.X!mS+Gr;Qf:k0*esk5PG\k5PGZk5GA[k5PG\k555Uk5,/Yk5GA[k5PG]
+k5PG]k5PG]k555Zk5PG[k5>;Zk5PD_jo>D\k5GA[k5PG]k5PF4k(2[%jo`m%s."T~>
+!h?&@p?hoYf`)&<m[Vi*rrTm0k5>5\p;P;"s0qFr!.jQhmZ-];0r1<gJ,~>
+!liB.p?ho\f`)&9k*afurrTd.ir&WSp:e\ms0qFr!.jQhmZ-];H-4-8J,~>
+!quZ5p>u?Qf`)&Tm^1jKrrUHYmed"bc.1#;\*!\jJ`_OGNogG_s7W7=~>
+!i2>Hp?hoYf`))Es5oQrrr3A5V!e9Vs7ZKdp9_f^s0qFr!.jQhmZ-];3LlloJ,~>
+!m8N2p?ho\f`))Fp>V4_rr3&.Sa-+G!qNe>bQ#'>rr@W<JaSQd"+A23@=S~>
+!rqu=p>u?Qf`))]s5pE>rr3AF[-mtfs7ZKdp;PS*s0q.j!.j9`k)SR+c1_1-J,~>
+!h?&@p?hoYf`)8Bp@d@-ec3"Hk5+cQm^0sVs+0ThmXafCmK52>S1/s~>
+!liB.p?ho\f`)8Co((Xsdf6bDk5+WMlE\:Ms+0ThmXafCmK7aW`aOA~>
+!quZ5p>u?Qf`)VdpAa9VhZ(R%mf3"\pAajdp;PS*s+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoYf`)V3mdBf!Mk$$gp?qYBp?qYBk*4`Gs+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\f`(r"rpBp?Kq4@_qX+INifVs<s+0ThmXafCmK7mWb$ff~>
+!rqu=p>u?Qf`(rArq6KOUpR5cq=XmXXQI_+J`_OGJ`ai3"3pQ>S:C~>
+!h?&@p?hoYf`(uB`W#9,eXYLkmK26lp<3JemXaeWm_\Ao0r1<gJ,~>
+!liB.p?ho\f`(u;`r>6)d[Ahal2oObp<3JemXaeWm_\AoH-4-8J,~>
+!quZ5p>u?Qf`)Sceb8G)hR)G=me6)Bme6)Bk+'ToJ`_OGJ`ai3"3(<6Ujr~>
+!i2>Hp?hoYf`),oUu(7rmf)>Kmf)>QmcNZgk+&Nrs+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\f`)W%S_iMgk2PO_k2PO_k2POWhOU[is+0ThmXafCmK7mWb$ff~>
+!rqu=p>u?Qf`)$'[-%AU!9X(E"6T$Y^!$G,k(2ZGk/-6_c1_1-J,~>
+!h?&@p?hoYf`)$HF2dh7#M$N$hPB#bp<N\hmXaeWm_\Ao0r1<gJ,~>
+!liB.p?ho\f`)'IFhZ`-iX+K$cF1=<R@0>kcMrI`JaS*W_X7MOb/Rk?~>
+!quZ5p>u?QfDbu<c0"HVrpBdKrpC*TmbYq-k,^it[*J]&k(2ZGk/-6_`W,Y-J,~>
+!i2>Hp?hoYfDbokC<cM0$-g/s`Qd8rp=8l_s+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\fDcW+D8t;dg>:Q?g>:Q?cG%$4_P*gOOk.kYJaS*WJaUDC"+A23@=S~>
+!rqu=p>u?QfDbp&Mq.Ra$/WqOe]gu@3@V>]s+0<`k(2[3jo`m%s."T~>
+!h?&@p?hoYf)GiJF0s3gh?)6Pc2Q5shY-C2eb7AiJaS*WJaUDC"#6UA.=_~>
+!liB.p?ho\f)HMVD6D1<f%S^/f%SQl`m2_pTuO+\NRlJVJaS*WJaUDC"*r&/@=S~>
+!quZ5p>u?Qf)GiZMoFQLjpU%re_\PK.5;r*.C@J%J`_OGJ`ai3"3(<6Ujr~>
+!i2>Hp?hoYec-#j>)T2i`QcB8^"(C+eHYa0p?qY!ma;(.mX\8e;Lq`u;YKM\3LlloJ,~>
+!m8N2p?ho\ec-Dr?&>Dh_T'I$^=(<Td[?N?Ko)tTM:0fOp?mK3JQ78$fN%Y5"+A23@=S~>
+!rqu=p>u?Qec,s#K;?3*e^_p`c2QQ+eP[hF#RD8%.BLqsp?$p(JPq%sfM_G*"3pQ>S:C~>
+!h?&@p?hoYeGg'IS6BZKHZNY"Ut+>Heb8G1s8Vcn`U;1Sp?mM3JcC<$f`1[5"#6UA.=_~>
+!liB.p?ho\eGg<LQ!%[@H#7+qU!hMWQ+i6GR?b(tL!nELp?mM3JcC<$f`1[5"*r&/@=S~>
+!quZ5p>u?QeGfXEXFl0)PlH@F[-$4C.4Gf>#S8+5.C@P'p?$r+JcC<$f`1[-"3(<6Ujr~>
+!i2>Hp?hoYdJjU)[&gskhI<"oc1^T'rr_u_`U;4TJaS*WJaUDC"$)mI.=_~>
+!m8N2p?ho\dJjp3[]7'mhI2h3OfjtGTr"HRZG(n<e,P!eJaS*W_X7MS`l__?~>
+!rqu=p>u?QdJjp;`P'OQk(Ba-.3K0=&/Yrq(bmJ@e,P!]J`_OG_WCsFpA^Y5~>
+!h?&@p?hoYbPq_%XNgJ4qYpZkm_/&<s+0ThmXafCmK52>S1/s~>
+!liB.p?ho\bPr+(FcE]#Y-,(5ZEC49\p_lRs+0ThmXafCmK7aW`aOA~>
+!quZ5p>u?QbPr+03@Q'f+;c4<+;bq<0e'KZs+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoYbPqY;[-%,_"8;/rk10K_mXaeWm_\Ao3LlloJ,~>
+!m8N2p?ho\bPqY+H*6qR"L>VEH-Xt?JaS*WJaUDC"+A23@=S~>
+!rqu=p>u?QbPqXo.4P!6!uNI9XO[?%k(2ZGk/-6_c1_1-J,~>
+!h?&@p?hoYb5VP*[-mYf!q*GXf)L<hJaS*W_X7L\Umrla~>
+!liB.p?ho\b5VOgFftV]s2+fM"2_3`b1?TDmXaeWm_\AoH-4-8J,~>
+!quZ5p>u?Qb5VIKpF-7g.3L&g[+>8.k(2ZGk/-6_`W,Y-J,~>
+!i2>Hp?hoYao;G)XQK6V!p6TXfDgEiJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\ao;IcEM^hWc2c#a\cS^Jk1BWamXaeWm_\AoIE'E<J,~>
+!rqu=p>u?Qao;@Br[@q(.5<:K+TEkje^shPk(2ZGk/-6_c1_1-J,~>
+!h?&@p?hoYaSu>(XQK6V!R8U8s+0ThmXafCmK52>S1/s~>
+!liB.p?ho\aSudnD5#8/g;:/$R?`o?[Z-^,s+0ThmXafCmK7aW`aOA~>
+!quZ5p>u?QaSu7Ir[A480e!q^&.f*i+=V'Ws+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoYa8Z5'UuqFO!Ucc8s+0ThmXafCmK5J>Ua^f~>
+!m8N2p?ho\a8ZXhBpmE3ZEC3mSY;1OWbL)bJaS*WJaUDC"+A23@=S~>
+!rqu=p>u?Qa8Z:D.3L'"rYPhF&.f*a(b+):J`_OGJ`ai3"3pQ>S:C~>
+!h?&@p?hoY`r?+sUuqFO!2S6HJaS*WJaUDC"#6UA.=_~>
+!liB.p?ho\`r?LfAX1iHWksITToH(XA_6s5mXaeWm_\AoH-4-8J,~>
+!quZ5p>u?Q`r?LL.3L>^(b#Fr&-s*i.G+TNk(2ZGk/-6_`W,Y-J,~>
+!i2>Hp?hoY`W$"rSDO&@!1_[@JaS*WJaUDC"$)mI.=_~>
+!m8N2p?ho\`W$@d@?IC[cBX*KQ)1<cfDgEiJaS*W_X7MS`l__?~>
+!rqu=p>u?Q`W$@J.3K0=.0onb#S7OrfDgEaJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoY`;]nqPhu9:!S+!ts+0ThmXafCmK52>S1/s~>
+!liB.p?ho\`;^4b?&>,Tg:FGXTnRL<s+0ThmXafCmK7aW`aOA~>
+!quZ5p>u?Q`;^4H.2WU50d%;E&0O9js+0<`k(2[3jo`U&p8!3~>
+!i2>Hp?hoY_uBegMr+C3!q)<'fDgEiJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\_uC(\=b2j+Q'n&&?,G4nJaS*WJaUDC"+A23@=S~>
+!rqu=p>u?Q_uC(F+;b@q#S77Q+KX2pJ`_OGJ`ai3"3pQ>S:C~>
+!h?&@p?hoY_Z'nlMnSias36eAf)L<hJaS*W_X7L\Umrla~>
+!liB.p?ho\_Z'nY<H4"`O`aflf)L<hJaS*W_X7MOb/Rk?~>
+!quZ5p>u?Q_Z'nC.3Jm-#T+\2f)L<`J`_OG_WCs>s7W7=~>
+!i2>Hp?hoY_>a`-XG_^hPh"=aJaS*WJaUDC"$)mI.=_~>
+!m8N2p?ho\_>a_rM,dAPA\Q^pJaS*WJaUDC"+A23@=S~>
+!rqu=p>u?Q_>aPd@f@eW3NUd2J`_OGJ`ai3"3pQ>S:C~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrSG5JPq/!!<;raJbJ[.lg=j0Umrla~>
+!liB.p?ho\NrSG5JQ7A'!<;raC\$oamdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:nfmMmmdff:mdff:mdff:mdff:mdff:mdfr:o'Z):o'Z):o'>]GH-4-8J,~>
+!quZ5p>u?QNrSG-JPq/!!<;rYJaW*slfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!`I9/r]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sE
+r]'sEr]'sEr]'sEr]'sEr]'sEr](*I3@W3=r]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sE
+r]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sE
+r]('H3B9D)3<2AE3<2AE3<2AE3<MPrbsD=h!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE
+!($TE!($TE!($TE!($TE!($TE!($TE!C?b^mV;I`p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBmNM;lp?qYBp?qYBp?qYBp?qYBp?qYBp?qABme6)Bme6)BlL"a7S>7Ta~>
+!m8N2p?ho\NrSG5!EI.O2ut;ENApqa`l'h:s8).uo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Yoho'Z):o'Z):o'Z):o'Z):o'Z):o'Z):mdff:mdff:mdfZ2"+A23
+@=S~>
+!rqu=p>u?QNrSG-!E-o93<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f5
+3<1f53<1f53<1f53<1f53<1f53<V&s3?Z<?3<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f5
+3<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f5
+3<1f23<1f53<1f53<1f53<Lur+N==?!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5
+!&=I5!&=I5!&=I5!&=I5!&=I5!\l_8qW;P\k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k2miTk3hC"k3hC"k3hC"k3hC"k3hC"k3hBomcNs"mcNs"mcrp:c1_1-J,~>
+!h?&@p?hoYbl@\C`W,8l!E/s0p&UEXNV3C;s2=U2s826ap4<8=s8DZWmK52>S1/s~>
+!liB.p?ho\bl@\C`W,8lIoZO:o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):nr<\;o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):npTrsmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff6o'Z):o'Z):o'Z):o'Z):NW8G;mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdffGqsFRWme6L.s8;m#qY'@Jmdf]3"*r&/@=S~>
+!quZ5p>u?Qbl@\C`W,8dIo?=/mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mYh,-mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mX=6ck3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hBomcNs"mcNs"mcNs"mcNs"MuVr-k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC3qr[qHrUt^?pAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds8N,ns8DZimd'!;`W,Y-
+J,~>
+!i2>Hp?hoYq>^9kg].9RqZ$HnoDegjiW&63!)gE.!1]#J!1^q+qX4CWr;ZfbGinGVmcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcN["k3hC"k3hC"k3hC"k3hC"k3hC"k3i-/"Rc!Wme5r6
+"$)mI.=_~>
+!m8N2p?ho\q>^9kg].9RqZ$HnoDegjiW&63!*-W1!0rNC!0tG$qX4CSs7UpAqXWq6io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io9+[k2PO_k2PO_k2PO_k2PO_k2PO_k2QEt#NFV"
+k3hg.o'5WFIE'E<J,~>
+!rqu=p>u?Qq>^9kg].9RqZ$HnoDegjiW&6+!)idq!;?El!;?El!;?El!;?El!;?El!;?El!;?El
+!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El"8;cpPl:U^pAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpA=jipAY'lpAY'lpAY'npA^BUrrDclrrDclrrDclrrDclrrDclrrDcl
+rrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrVoos8(mXmK`IRs7Ym;hUVV^!7h)*!7h)*
+!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*
+!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*s4.,*!7h)*!7h)*!7h)*!7h)*!7h)*qpbi+k3hC"lK/2n
+pA^Y5~>
+!h?&@p?hoYqZ$NprVlitg].9Rqu?Zrrr;uuq#C?oh>cg/!)gE.!0iHB!0kA#qsFU\mdB62Jc>f>
+k2-(!rq>[G"#6UA.=_~>
+!liB.p?ho\qZ$NprVlitg].9Rqu?Zrrr;uuq#C?oh>cg/!*-W1!0rNC!0tG$qX+RIk2P\&s8W)p
+@.sHjqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqYDE0qY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZk2+\Gg>:iWmdf]3"*r&/@=S~>
+!quZ5p>u?QqZ$NprVlitg].9Rqu?Zrrr;uuq#C?oh>cg'!)gE.!/lg9!/n_oqrRnHrn[_=pAb$`
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:KgZ!:Kj[!:Kj[!:Kj[!:Kj[!:Kj["n)*P
+hUTmLec,"&jo`U&p8!3~>
+!i2>Hp?hoYqu?Zrp](0lrr;uu!ri6#rVufrrr;os!<;utrr;uur;Zcsr;Zcs!<;rs!<;ut!ri6#
+rr;rtrr;uu!ri6#rVufrp]'RI!)gE.!1]#J!1^q+qsOLHrn`5+"97N?ec"@hmK5J>Ua^f~>
+!m8N2p?ho\qu?Zrp](0lrr;uu!ri6#rVufrrr;os!<;utrr;uur;Zcsr;Zcs!<;rs!<;ut!ri6#
+rr;rtrr;uu!ri6#rVufrp]'RI!*-W1!0rNC!0tG$qsFI@rRq8FrVq?Cs8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)clqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqYKpJf$aNN!:&k;"+A23
+@=S~>
+!rqu=p>u?Qqu?Zrp](0lrr;uu!ri6#rVufrrr;os!<;utrr;uur;Zcsr;Zcs!<;rs!<;ut!ri6#
+rr;rtrr;uu!ri6#rVufrp]'RA!)gE.!0iHB!0kA#qr[h,"Rc!`pA]m@#O^Hnc.1(he`l2uc1_1-
+J,~>
+!h?&@p?hoYqu?Zrq#C?os8W*!s8W&u%fZM/s8N'!s8N'!s8N'!rr36(s8N'!s8N'!r;Zcsr;Zcs
+!<<#u')qq3rr<'!rr<'!rr<'!!!*'!rW!0&!!*'!!!)Zklg=aN])MbpN;imB_Z0N$"lAD(e_^"N
+rs/Sde^`g=e_]TZ"#6UA.=_~>
+!liB.p?ho\qu?Zrq#C?os8W*!s8W&u%fZM/s8N'!s8N'!s8N'!rr36(s8N'!s8N'!r;Zcsr;Zcs
+!<<#u')qq3rr<'!rr<'!rr<'!!!*'!rW!0&!!*'!!!)Zklg=aQ])MbmN;im?_Z0N$"k),Ydamu?
+rs/8SdaI"+cJ%RO"*r&/@=S~>
+!quZ5p>u?Qqu?Zrq#C?os8W*!s8W&u%fZM/s8N'!s8N'!s8N'!rr36(s8N'!s8N'!r;Zcsr;Zcs
+!<<#u')qq3rr<'!rr<'!rr<'!!!*'!rW!0&!!*'!!!)ZklfJ7Hs7ZHl!;?El!;?El!;?El!;?El
+!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El"SVkRs7ZHl!;?El
+!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El
+!;?El!;?El!;?El!;?El!;?El!;?El!;?El"8;cppAY'lpAY'lpAY'lpAY'op5AtErr2ulrr2ul
+rr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr3#ms81p^c.1@h
+c0kH.!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j
+!;??j!;??j!;??j!;??j!;??j!;??j$23f;c-=ehc.27Jjo`U&p8!3~>
+!i2>Hp?hoYqu?Zrrr;oss8W*!s8W*!s8W*!s8W*!s8W*!s8W*!s8W*!qu?Zrs8W*!r;Zcsr;Zcs
+&H;_1s8N'!rr<'!rr<'!!!*#urr<?)!!*'!!!*'!rW)Wklg=aNr;ZZprVlitpAY*mec,W>r;Q`s
+P5bNP_Z0N$!R9d+eH#;orrN/frm_,-c->D:mK5J>Ua^f~>
+!m8N2p?ho\qu?Zrrr;oss8W*!s8W*!s8W*!s8W*!s8W*!s8W*!s8W*!qu?Zrs8W*!r;Zcsr;Zcs
+&H;_1s8N'!rr<'!rr<'!!!*#urr<?)!!*'!!!*'!rW)Wklg=aQr;ZZprVlitpAY*mec,W7r;Q`s
+P5bNI_Z0N$#0,BFcI2.WK)Z,Mk0D9#g;_:plg=k'`l__?~>
+!rqu=p>u?Qqu?Zrrr;oss8W*!s8W*!s8W*!s8W*!s8W*!s8W*!s8W*!qu?Zrs8W*!r;Zcsr;Zcs
+&H;_1s8N'!rr<'!rr<'!!!*#urr<?)!!*'!!!*'!rW)WklfJ1FrVllkquHcs"SViqs7ZHl!;?El
+"SViqs7ZHl!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El"8;cpPl:Ubp&P-mpAY'l
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpA=jipAY'lpAY'lpAY'npA^BUrrDclrrDclrrDclrrDcl
+rrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrVoos81pZ^"*,$#3P@IpAajd
+rq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquo
+rq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c#64Ds
+pAaR;rl"ui]uAjojo`m%s."T~>
+!h?&@p?hoYqu?Zrr;Zcss8Vrrs8W*!s8W*!s8Vrrs8W*!rr;lrs8W*!r;Zcsr;Zcs&H;_1s8N'!
+rr<'!rr<'!!!*#urr<9'!!*'!!!*#ur;cTllg=aNr;Q`srr;uu`W#q&r;Q`sP5bNH_Z0N$"i]?K
+c.265rs8Yme]lY,`P(F"mK52>S1/s~>
+!liB.p?ho\qu?Zrr;Zcss8Vrrs8W*!s8W*!s8Vrrs8W*!rr;lrs8W*!r;Zcsr;Zcs&H;_1s8N'!
+rr<'!rr<'!!!*#urr<9'!!*'!!!*#ur;cTllg>-\s8)clrrE)qrr<%KqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElOoP:XqYpQqqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElEVf_3s8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)TlqZ$ElqZ$ElqZ$ElqZ$DSs8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cmmK^J[d`0`#pA0IB
+$2XATcGn;d^:rUmmK7aW`aOA~>
+!quZ5p>u?Qqu?Zrr;Zcss8Vrrs8W*!s8W*!s8Vrrs8W*!rr;lrs8W*!r;Zcsr;Zcs&H;_1s8N'!
+rr<'!rr<'!!!*#urr<9'!!*'!!!*#ur;cTllfJ4Gs8DWk!<2]l!6+X4MuWbL!!&2U!K6urp&P-i
+jor-Bc+VBarUtL9pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdrUpKQ`P'OH[(Y>^jo`U&p8!3~>
+!i2>Hp?hoYqu?Zrr;Zcss8W*!qu?Zrs8W*!s8W*!qu?Zrs8W*!s8W*!s8W*!r;Zcsr;Zcs&H;_1
+s8N'!rr<'!rr<'!!!*#urr<9'!!*'!!!)rsrW)`nlg=aNr;Q`srVultpAY*mdf0<;r;Q`sP5bNP
+_Z0N$!OU__blR8+m/R(cq#:<oqu6Wrqu?QorVlitpAY*m`r?)5mf(H5hR'uQlg=j8S>7Ta~>
+!m8N2p?ho\qu?Zrr;Zcss8W*!qu?Zrs8W*!s8W*!qu?Zrs8W*!s8W*!s8W*!r;Zcsr;Zcs&H;_1
+s8N'!rr<'!rr<'!!!*#urr<9'!!*'!!!)rsrW)`nlg>0]s8)Hcp&Og_pA+ahJ+ia4qY'dZqY'dZ
+!;?9_qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZQ2g^SqXsp_qY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqJc0)
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4XZqY'dZqY'dZqY'dZqY'cNs8)HcpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4gdmK^&Kb/2<`
+o(MJIrrDij!!)om!!)omquH]l!!)`h!!((9$23rPb/2<PZF\oYmK7mWb$ff~>
+!rqu=p>u?Qqu?Zrr;Zcss8W*!qu?Zrs8W*!s8W*!qu?Zrs8W*!s8W*!s8W*!r;Zcsr;Zcs&H;_1
+s8N'!rr<'!rr<'!!!*#urr<9'!!*'!!!)rsrW)`nlfJFMs7YmSp&OO[pAY-mp&OO[p&OO[p&sd`
+p@dqRp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p'C)Ns7YmSp&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&jaVp?qqR!:Kj[!:Kj[!:Kj["-iiZmf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[s81p^Us6ll^#&bV
+!VYs\p&a[Umf)n]me6)Jp'C*[!!)`dme6)Jp&aX^mf)n]me-Y[p&a[Umed%bmf)n]!;>j[p&a[U
+mf)n]!;>j[p&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&jaV
+me6YJ#N!/-`Qb3cea)?"c1_1-J,~>
+!h?&@p?hoYqZ$Nprr;uus8W&ur;Zcss8W*!s8W&ur;Zcss8W*!s8W*!s8W*!qu?Zrrr;uus8W*!
+!<<#u#QFc(s8N'!s8E!-rr<'!rr<'!rr<'!rrE&urrDiolg>B`s7ZKdrrE)ms7ZHms7QHds7Z9h
+"SMihs7ZBk"TS2q!<<#u!WVll!!N>qrrE)u!#tt3rrE)ms7ZKds7ZKds-3QWs7ZHms7ZKds7ZBk
+"TS2q!<<#u!rquor;[,srrE)mrrE)mr;Zs"pAajb!!<2os8E"Es7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7Z0dpAajdpAajdpAajdpAaiNs7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKimK]iMc,J5qp@eFa!;??j
+!;??j#58)s!!*&mr;QilrrE&u#58)s!<<)mrr36(s7ZHm!<<)mr;Qcjr;Qcjr;Qcjr;Qcjr;Qcj
+r;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Zfj#NjRUc/,P8k3MF;0r1<gJ,~>
+!liB.p?ho\qZ$Nprr;uus8W&ur;Zcss8W*!s8W&ur;Zcss8W*!s8W*!s8W*!qu?Zrrr;uus8W*!
+!<<#u#QFc(s8N'!s8E!-rr<'!rr<'!rr<'!rrE&urrDiolg>Bcs75mSp&OgWp@@nWp@84Sp@A%[
+"S)Q`p@A.^"SVE[!;?Bl!VZ*_!!N#dp&Ogc!#tY&p&OgWp@@qJp@@qJp6#CGp@@nWp@@qJp@A.^
+"SVE[!;?Bl!qu3Yr;[,op&OgWp&OgWr;Zrno(MYQ!!;lbpAP&<p@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@eJo(MYJo(MYJo(MYJo(MX:s75mSp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@A7\mQ.2mb.c$To()MFp@@qJ
+p@@qJp@@qJp@@qJp@81`p@@qJp@@qJp&OgWp@@qJ!:ojSp@@nWp@@nW!)rI^o(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o((Y[^<4m#]&)c@"*r&/@=S~>
+!quZ5p>u?QqZ$Nprr;uus8W&ur;Zcss8W*!s8W&ur;Zcss8W*!s8W*!s8W*!qu?Zrrr;uus8W*!
+!<<#u#QFc(s8N'!s8E!-rr<'!rr<'!rr<'!rrE&urrDiolfJ4Gs8D?c!;u6e!:K7TrpKU_!U]se
+mem.bmK!=UrW)udr;cib!<DQe!<2Bd!;>g]MuWbD!!)oar;cib!<DQe!<2Eb!<;He!<2Bf!:K:R
+!<)?a!<2Ec!64F-MuU``!<;rY$Dbqc[)LS`k4\6:rpBj]me6YJ!qu'UrpC'cmJm7Tme6)BrpBj]
+!;?E[!qu$^rpC'cme-YKme-V\rpBj]me6YJ!qu'UrpBj]me6YJ!qu'UrpBj]me6YJ!qu'UrpBj]
+me6YJ!qu'UrpBj]me6YJ!qu'UrpBj]me6YJ%ef>ame6):e]"o7c(q`'lfJ;gs7W7=~>
+!i2>Hp?hoYq#C3krVufrs8W*!s8W*!rVufrs8W*!rr;lrs8W*!qZ$Hnrr;lrrr;uu!ri6#rr;rt
+rr;uus8W*!s8Vusp]'RI!E/srp&G*jp'1Tkp&Og[!!)uk&chY!!;?*d!;?*d!;?*d!;?*dqt:6p
+p@\Idp@\Lcp&G*dp&U]`rUp3kp\#1!p@\Idp@\L[p&G*dp&Og[!<2Zl!;lI"!;?*d!;?*dp@\L[
+p&G*5p&U]``:a32qsGDnhSmIYk3hs:s7ZKds7ZKds7ZKds7ZKds7ZKl!,qo2s7ZKds7QHds7ZKd
+rrE)ms7ZKd!;?Hdrr<&ms7ZKds7ZKds7QHds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKdp?q(f`Pp](^#&)C"$)mI.=_~>
+!m8N2p?ho\q#C3krVufrs8W*!s8W*!rVufrs8W*!rr;lrs8W*!qZ$Hnrr;lrrr;uu!ri6#rr;rt
+rr;uus8W*!s8Vusp]'RIGuan8mdfcGmdff:mJu\G!:oOX!:oRKmJu\G!:oOX!:oOX!:oOX!:oOX
+mdff:md^AKmJm7XmJu\GmJu\Gmdff:mdff:mZmhCmdfcGmdff:mdff:md^AKmJm7XmJu\G!!)HX
+!:oOXmdfcGmdff:md^AKmJm5Co'QMGnc87K!!)TXo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z)>:[[fAo'Z):o'Z):o'Z):ns07Gmdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:s823gQ.!O``np.Mo)8Xbnc/[enc/[enc/[g
+o)A^`nc/[-nd+[?`kK=<Q+Gi<mK7mWb$ff~>
+!rqu=p>u?Qq#C3krVufrs8W*!s8W*!rVufrs8W*!rr;lrs8W*!qZ$Hnrr;lrrr;uu!ri6#rr;rt
+rr;uus8W*!s8Vusp]'RA!E/ssmO72tmdB6*mJuD;!:JtL!:K";mJuD;!:JtL!:JtL!:JtL!:JtL
+mdB6:mL0*`mJm7TmJuD;mJuDKmJuDKmKD\?mZdbNmKDYPmdB6:mJuDKmMGrlmJm7TmJuD;!!)0L
+!:JtLmdB3;mdB6:mLTBdmJm7TmJuD;!:JtL!:K"KmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDK
+mJuDKmJuDHmJuDKmJuDKmJuDKmK;V>PlLaN!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!p8qNqrS*Ic+UKte`Q5drW)c^!!)oa!!)oa!!)ucrrDc\
+!!'q)#j0[N[(X_K[+4L)"3pQ>S:C~>
+!h?&@p?hoY]Dqm2f)P((Io?=7p?qVSp?qYBp&OgS!:KO\p?qYBp&OgS!:KO\p?qYB!:KO\p?qVS
+p?qYBp?hqKp&OgSp&OgS!:KRKp?qYBp?qYBp6>UFp?qVSp?qYBp?qYBp?hqKp&OgSp&OgS!:KRK
+!:KO\p?qVSp?qYBp?hqKp&OgSp&Odd!.F;/mJu\Kme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6):p?qYBp?qYBp?qYBp?qYBPlL1Fme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)KqsFWPe]kePhX't9!!2cnr:^'hrq?9jqt:!i
+r:U3mp@\LcpA+aip&P*cr;cij!<Dim!<;ck!<2Zm!;?Blrq6<lk4T&Bc+VBPPeH5FmK52>S1/s~>
+!liB.p?ho\]Dqm2f)P((IoZO6mcs3?mcs6*mJu\?!:&tPmcs6*mJu\?!:&tPmcs6*!:&tPmcs3?
+mcs6*mcjf;mJu\?mJu\?!:'";mcs6*mcs6*mZmh;mcs3?mcs6*mcs6*mcjf;mJu\?mJu\?!:'";
+!:&tPmcs3?mcs6*mcjf;mJu\?mJuYT!.F/#l2^,;lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s&mcs6*mcs6*mcs6*mcs6*Q2g.;lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s;qsF]Od`/l<g?Rtkmf*7fmK!1Qr;cibr;c`_
+!!)rb!s%cW!<2E_!!2KfrpK^brpBdemf!4dmem.bmK!=UrW)rc!!)6Ns69jC`k'1<Oh0E8mK7aW
+`aOA~>
+!quZ5p>u?Q]Dqm2f)P'u!E/Xijo>DZjothJjoFQ+!;ts`!9WDDk2l[BjoYVGjoGDC!!)oY!s%KG
+!<2*_!9WDDp#Z:5pAO+R!;GUX!9WDDroO:_k2l[CjoYVGjoGDC!!)oY!s%KG!<2*_!9O7]roO1\
+a6!D\p;H(ns81q'MoEB:^")9-mcNs"mcNs"mcNs"mcNs"mcNp;!9O:DmcNs"r;Zoek3i0J''AWE
+mcNp;mcNs"mJu\;!9W_3q>^Z\!9W_3r;Zugk3`6;rVuuek5>8_mcNp;mf!25mcNp;mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNZ^]sPJtMmV@,jo`U&p8!3~>
+!i2>Hp?hoY]Dqm2f)P((/Q2WBme6&Kme6)BmJu\K!;>g\me6)BmJu\K!;>g\me6)B!;>g\me6&K
+me6)I!$h4*!:KRK!!)]mp?qYBp?qYBp?qYBSH&<Np?hqKp?qYBp?qkZ(\[7sme6&Kme-YSme-YS
+mJu\KmJu\Kmem+jp?hqKp?hqKqZ(p8me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bp?qYBp?qYBp?qYBp?qYBp720Vme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bs823bK@Tt?!8d_CHM6e#me6)Bme6)Bme6)Bme6&Kme-YS
+me6&K!;>g\me-V\me-YSme6)BmJu\Kme6&Kme-YSmJm7\me6&Kme-YSmJm7\mJm7\mJm7\mJu\K
+me6)B!;>g\!;>g\me6&Kme6)Bme6)Bme6)Bme6)Bme6)Bme6)BrpC$R`P'7IK>$.-mK5J>Ua^f~>
+!m8N2p?ho\]Dqm2f)P((!EK0ul2Uh^l377Rl2^,7!;u*d!:&hLlKSBJl2q%Ol2^hK!!*#`r;cl_
+!!*#`rr<)b!;5UXQ2ggJ!!)l\r;cl_!!*#`!s%WO!<26c!:&hLrosI`rp'F^s69RarosLalMCS%
+l2d1M`9I@&qsFZBd_`T4g?.ef!s%WO!<)3_!<;<h!:&hL!:&hLqs".]r9=LelKSB7l2Uh_l4O*^
+l2^,7!!)<L!!)<L!!)<L!;l$d!:&hL!:&hLrosI`kNW?8g;:G<dY59hlg=k'`l__?~>
+!rqu=p>u?Q]Dqm2f)P'u!E/srjo>DZjothJjoFQ+!;ts`!9WDDk2l[BjoYVGjoGDC!!*#\r;cl[
+!!*#\rr<)^!;5ITPlL^E!!)lXr;cl[!!*#\!s%KG!<2*_!9WDDroO1\roX.Zs5j:]roO4]k5,/!
+joL_H`9%("qrS64c+UKte_]HFk2-+"!oE(rroO:=k2-+"']&iHjoFQ#k2$(<k2$*pjo>D<joGDC
+52PGY!9WG#k2$+#joFQ#!!)0<k2$+#joFQ#!!)0<!!)0D!!)0<!9WG#k2,5#k2$(<k2l[#k2$+#
+k2,7WroO:=k2-+"!oE(rroO^Ik2,7Wk2+Y%[(X_2[+4L)"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/srmJm7cmf*:emK3IWmK!1Q"p")Z!:K7TrU'afmd:)SmK3IWmK!7S!s%cW
+!<)?b!;5a\SH&QU!!)oa!!*#d!s%cW!<2Bg!:K7TrpBjgmd:)SmK3IWmK!7S!s%cW!<2Bg!:Bge
+_sRPqs2==*s823hK@S5[c/.mNr9aRIr9aRIr9adOmJu\C!!*#d%KPqZmJu\C!9W_;!:K:;rpBgf
+mcON:#QX;T!:K7TmcON:%KPqZ!:K7TmcNs*!:K7TrpBgfmcOK9!s%KO!<2Bj!:K7TmdB68mJuDI
+mJuDImJuDImKr%DhT`aYeUtQtlg=j0Umrla~>
+!liB.p?ho\NrSG5!EK0ujo>D[k5PG]joYVGjoG>A"p!fJ!9WDDrT41^k2l[CjoYVGjoGDC!s%KG
+!<)'Z!;5ITQ2ggF!!)oY!!*#\!s%KG!<2*_!9WDDroO:_k2l[CjoYVGjoGDC!s%KG!<2*_!9O7]
+_r^ubs2=%"s824+J^VQL`n'//k2PO_k2PO_k2PO_k2PO_k2PM'k2H@@DW]s@!9W;'!9W8@io]5#
+io]7_ioU7'io]7_!9W8@ioU7'io]7_!9W8@ioU7'io]5#ioU7'ioU7'io]7_iW/!#!9W;'!9W8@
+io]7_io]7_io]7_io]7_io]7_io]7_io]7[f#G;@dXf!dlg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/XjhC.LdhVRDO!!)0<!8ci<hVRDOh>l]p!8ci<hVRDO!8ci<hVRAphVJ83
+h?3i8h>l^;hYmKUhWFgo!9X:;"QnRtMt[/,"Qf^@hWFgo!!*#T(]`FL!9W.p!9W,<hWEYphW=gp
+hW=gph>mQ3$io/@!9W.p!9O7]hWFgo!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;
+!9X18!9X:;!9X:;!9X:;"6SHupAWnKk5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;k5O3;
+k5O3;k5O3;k5O3;k5O3;k5O3=k2-.8jp-7X]sPJthUV&N"9@<8!!*#T!!*#T!s%37!<1gT!;kUQ
+!;t[X!8cQ4hVJ81h?Eu:h>lEh!<(aV!8cQ4rn[VTqq_DThVJ83h?*c7h>lZo#L0rh]u>?*hWs;+
+`W,Y-J,~>
+!i2>Hp?hoYNrSG5!E/srmJm7dmf*:dmK<OXmJm7cmLB6bmJu\C!!)HT!!)HT!<2Bg!:K7TrpBjg
+md:)Rmf*:ZmK'-`rU'XcqsFFarpBjgmd:)SmL]HemJu\C!!)HT!:K7T!:K7TrpC*nmd:)CmJm7T
+mJt/m!Mob6mK!:amKI[g`P'7IroOd[k3hC"k3hC"k3hC"k3hC"qZ&b@mcFN3mcFN3mJu\;mJu\;
+mcNs"!9W_3mcFN3mJu\;!9W_3mcFN3mJu\;!9W_3mJu\;!9W_3!9W_3r;\24joFQ3jo>DL!:K";
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2-*V"4_J+hWsS33LlloJ,~>
+!m8N2p?ho\NrSG5!EK0ujo>D\k5PG\job\Hjo>D[jphCRjoFQ+!!)0D!!)0D!<2*_!9WDDroO:_
+k2l[Bk5PGRjoM%QrT4([qrRkYroO:_k2l[Cjq.UUjoFQ+!!)0D!9WDD!9WDDroOOfk2l[+jo>DD
+joE<]!M08/joGGYmKRg^_RdV8hX9D#!<1sX!<1s[!92u<ro*nXqr.SUr8In\io0stiW/o9"p!ZB
+!92u<rSdnZio0t;iW&uXir&lWiW&uXir8uZiW/-##i=.L]#)m<]&)c@"+A23@=S~>
+!rqu=p>u?QNrSG-HrC",hWEYphWEYp!9W/#!9W,<!9W/#h>lEp!9W,<!9W,<!9W,<hWEYphW=h#
+hW=h#h>lEphW=e<hWE\WhWE\WhWE\WhOOW.hWEYphWE\WhW=h#hW=h#h>lEph>lEp!9W,<!9W,<
+hW=e<hW=h#hW=h#h>lEp!!"_0joFQ#k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7_:Yt6jk2,7Wk2,7Wk2,7Wk+)J6hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Ws81prC<a,m^!5*ae_\j5e_\j5e_\j5e_\j5e_^0'
+4Or<=!7frV!7fp+hUUH_hUUK5hUMVVhUUK5!7fp+hUMVVhUUK5!7fp+hUMVVhUUH_hUMVVhUMVV
+hUVQ)/`,"Xe_\gV!8[_4e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j$]sP/kC:)OWjo`m%s."T~>
+!h?&@p?hoYNrSG5!E/srmed(`mJm7dmem+gmJm7T!<2Eb!<2Bd!<2Bf!:K:P!!2KfrU0[co^2aM
+s8DB_!!)Ha!!2KfrpBadrpKdd"7?0Wmf!1gmJu\CqZ-Zarr<)f!<2Eb!6=L.SH$Oq!<;ra"`r5=
+^!5F$jo>D[jo>D\jo>D\joYVGjoGDC!!)oY!!)u[rrE)]!s%KG!;ts`!9WDDk2l[BjoYVGjoGDC
+!s%KG!<2*_!9WDDrT=(ZjlQg)c+VBPF1p`%mK52>S1/s~>
+!liB.p?ho\NrSG5!EK0uk555Xjo>D\k5>8_jo>DD!<2-Z!<2*\!<2*^!9WG@!!23^rT=+[o]?1B
+s8D*W!!)0Y!!23^roO1\roX4\"6KUGk5G>_joFQ+qZ-ZYrr<)^!<2-Z!6=4&RK(4f!<;raB5Q):
+]#*%ThW!DOhW!DOhW!DOhW!DOhW!AlhW!DO!92kp!92kp!92i8hW!AlhW!DOhVnOphW!Al!92i8
+hVnOphW!DO!92i8hVnOphW!AlhVnOphVnOph>lElh>lEl!92kphYmL"hW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DKf###<dVZSPlg=k#b/Rk?~>
+!quZ5p>u?QNrSG-"]G'Nk2,7u!!hZCk2$*pk2-%:#Nc!dh>lEphYdE\k2,5#k2,5#k2,t8)Wh%^
+hWEYp!9W/#hWE\WhWE\WhWC'rhWE\WqZ$WQqZ%,g!9W/#!9W/#!!(jUhWFe;"6KUGhYR9Yk2$(<
+joFQ#k5>:*hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOk2,7Wk2,7W
+k2,7Wk2)?rhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhZ*K8B55E![(X`@e_\j5e_\j5e_\j5e_\j5e_\gVe_\j5!8c8_!8c8_!8c6+e_\gV
+e_\j5e_U;_e_\gV!8c6+e_U;_e_\j5!8c6+e_U;_e_\gVe_U;_e_U;_eH".VeH".V!8c8_ec#On
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5c+U3lc"aWBlfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5HrC"<me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme-YSme6)Bme6)Bme6)Bm\KmVme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6&K!;>jS
+me6)Bme6)Bme6)Bme6)B!!"_@p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYJ:[[rEp?qYBp?qYBp?qYBp8%`^me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bs823b@b(Iss5&4ehWE\WhWE\WhWE\WhWE\WhW=h#
+hWEYp!9W,<hW=e<hW=h#h>dQ<hWE\Wh>lEph>dQ<hW=h#h>dQ<hWEYphW=h#h>dQ<h>dQ<h>lEp
+h>lEp!9W/#!9W,<hWE\W!!(m<h>lEp!9W,<hWE\WhWE\WhWE\WhWE\WhWFjp#0"9phI=1Tlg=j8
+S>7Ta~>
+!m8N2p?ho\NrSG5!EK0Bl2UhUl2dUYjm)jGmcsfP_!1ros2=1&s823g@FE$(^=M$;hK[c2g>:Q?
+g>:Q?g>:Q?g>2hdg>:N`!8cE0g>2f0g>2hdg&M-0g>:Q?g&Tj`g&M-0g>2hdg&M-0g>:N`g>2hd
+g&M-0g&M-0g&Tj`g&Tj`!8cGd!8cE0g>:Q?!!(a0g&Tj`!8cE0g>:Q?g>:Q?g>:Q?g>:Q_h?_id
+^:M20@Ck=]mK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/s?jo>DQjoM"PjlZRCmcONL^ubZfs2=%"s81p_>0Xaf[*?kpeTf?hc.1(h
+c.1(hc.1(hc.)gEc.1&=!7f<oc.)doc.)gEbl@aoc.1(hblH#=bl@aoc.)gEbl@aoc.1&=c.)gE
+bl@aobl@aoblH#=blH#=!7f?E!7f<oc.1(h!!(9oblH#=!7f<oc.1(hc.1(hc.1(hc.1)<ec3no
+Zin(e>-uiGjo`m%s."T~>
+!h?&@p?hoYNrSG5@T*6op?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?hqKp?qYBp?qYBp?qYBp8%`Vp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBr;[E&me6)B
+me6)Bme6)Bme6)Br;\S?p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBmSEQEp?qYBp?qYBp?qYBp?naVme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bmf31P1h,"[^!5ErhWE\WhWE\WhWE\WhWE\WhW=e<hWE\W
+h>lEph>dQ<!9W/#!!(jUhWE\WhWF_9#Njn*h>lEphYdEZjo>D<!8ckpr;[/dhW=h#hW=h#hYR:(
+joFQ#k2$(<k2,5#k2$*pjoFQ#k2,7Wk2,7Wk2,7Wk2,7Wk2+@rc.-::k3MF;0r1<gJ,~>
+!liB.p?ho\O59m:lgA4^s6B%;mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*!:'";mcs6*mcs6*mcs56s6B%;mcs6*mcs6*mcs6*mcs6*mcs6*mcs`N&FSiO
+lL*s*lL*s*lL*s*lL+TN1$\2lmcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs(5mcs6*mcs6*mcs6*mcs6*U&XEGlL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s;qsH:Hd`/l8db<F3g>:Q?g>:Q?g>:Q?g>:Q?!!(a0
+g>:N`g>:N`!8[_4g>2f0g&Tj`g>:Q?qu?uYg>:N`g>:Q^!!h?\!87G,hV.o.$/XCm!8cGd!8cH,
+!%ct,hV-i?!!(m0h>lEd!8?90hV-i?hV-i?hV-i?hV-i?hV-]3_Rdb8?+SnYmK7aW`aOA~>
+!quZ5p>u?QO)k=$lfJ4Gp<)Lt!;#=RSG)1/r;c?Lr;aUp!M&l%joGGYjonr5]sPJtma_=;r7(cI
+rmh#K!S%2Lec,UMeH#KsquH]G!!*#Kr;ZuN!!(OLrmgrIrm^uKrm_&Me^aNs!S%2Kec,XKeHQ$(
+eH".M!:JABc+UKtc!%L2lfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!E/s0p&VQ#NV3C[s2=U2s823g;Vo[;`STI#k2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7WjoFQ#k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,8#hZ(Otc/)@3hWsS3
+3LlloJ,~>
+!m8N2p?ho\O59m:lgB7&s75UKmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdfeGs75UKmdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdfdoo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o()5>mdff:mdff:mdff:mddCXo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o)JUT"]a-n^;A<jg&M-5g'?3G^;e`(]&)c@"+A23
+@=S~>
+!rqu=p>u?QO)k=$lfJ4Gs8MEdk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5OcKk5OcKk5OcKk5OcOk3hZ5s8MEdk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk54QHk5OcKk5OcKk5OcNk3f&FrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdK
+rpBdKrpBdKrpBdKrpBdKrpBdKrpBjMmf31H##`^Z[(X`/Iau]nc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.)gEc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hs31b][(X^^[+4L)"3pQ>
+S:C~>
+!h?&@p?hoYNrSG5!E/s0p&V8pNV3CSs2=U2s823f;VosCc.2gU1Z%9Nk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk5G?Uk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7W!8ckpk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wc,J5i;SD5YmK52>
+S1/s~>
+!liB.p?ho\O59m:lg=dRs1@\"WrJ(H!NQ1<mK!:amQ=1ocGITLhV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-ic!)DD)hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV%t`hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hU]]`cIP\#hWsS3
+H-4-8J,~>
+!quZ5p>u?QO)k=$lfN[ps5rb3mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNr5s5rb3mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNqck3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k2u*omcNs"mcNs"mcNs"mcL>Fk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k5Y>@"\R%Y]tM\5ec#R%eGoU0eHa@4[)L9^[,1-2
+"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!E/s0p&VQ#NV3C[s2=U2s823j6/L/:`STJ6hWFgo!9X49!9X49!9X49!9X49
+!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X49
+!9X49$0L+$c-=eq6+u.@mK5J>Ua^f~>
+!m8N2p?ho\O59m:lg=dRs1@\"Y5aLL!NuI@mK!:amKZ/2cGm`Lg>7M:$/XCeb/V`\7(V7@mK7mW
+b$ff~>
+!rqu=p>u?QO)k=$lfN[ps6f%;k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hB-s6f%;k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hA[mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mdB6*k3hC"k3hC"k3hC"k3f&FmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mf31H#!pMQ]tM\8Iau]nc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hs3:SW"NAnW[+4L)
+"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/s0mK']pNU?hSs2==*s823h>0YpKe^`O5r8n"9r8n"9r8n"9r8n"9r8n"9
+r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9
+qW8%>e^`O$;SD5YmK52>S1/s~>
+!liB.p?ho\O59m:lg=dRs1@CoY5aLD!NuI@joGGYmKZb7f#l.`g=h&5g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?hW!8hc32_@9Y0*H
+mK7aW`aOA~>
+!quZ5p>u?QO)k=$lfN[ps5r2#hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE[js5r2#hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE[Ck2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2tO_hWE\WhWE\WhWE\WhWCX6k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk5Y>@"]E=a`Pp)QeHk$Vc,IrH9!mI@jo`U&p8!3~>
+!i2>Hp?hoYNrSG5Io>F1[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&iDk[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[!f$_XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(1[&gX9[&gX9[&gX9[&gX9XQHUkXL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,)/qsF]1XPVgae_]0\joF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9:joF9;joF9;joF9;joF9;joF9;joF9;joOo4rn[aY@_LpimK5J>Ua^f~>
+!m8N2p?ho\O59m:lgB7&ii9/]Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y$ii9/]Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\XQWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiE5%Y,\Y)Y,\Y)Y,\Y)Y,\>XWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WrMta#B?ctda$.hgA]rTg>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hW!N#k2+\;g9+_mhWsS3
+IE'E<J,~>
+!rqu=p>u?QO)k=$lfJ4GhRfQaSDK7$!M&#bU]CGljp,t'e]l(Pc-:smrn[n1c-=e7>.!/Pjo`m%
+s."T~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;!khLVrn[_,hVNtK$1@NTk2t2lMoFQ=mK52>S1/s~>
+!liB.p?ho\O59m:lg=aQJ_n<$_Z0N$#eE^Pf%/9tf%Pi7$0(C8hVQOOKtcF0mK7aW`aOA~>
+!quZ5p>u?QO)k=$lfJ1FJTJ_M_Z0Mq!jkS=rlkM`c-:sm$/Xh$e^_W2K>#h$jo`U&p8!3~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;#53sIXOZ1irn_n^hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WroOIRk2*I;C:)7NmK5J>Ua^f~>
+!m8N2p?ho\O59m:lg=aQJ_n<$_Z0N$#P*jBV9[ZGeqMfXhYuL=euhPXZHD=qmK7mWb$ff~>
+!rqu=p>u?QO)k=$lfJ1FJTJ_M_Z0MqC[R*QUrCU/c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(heJ?E[c.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@lK/2npA^Y5~>
+!h?&@p?hoYd/O+.rl##R`P'7(rP\fEhTl/emJp.9s+LFKmKWBuC,%.d1&NI#1&`U%1&`U%1&`U%
+1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%
+1&`U%1&`U%1&`U%1&`U%1&`U%1&WO$1&`U%1&`U%1&`U%1&`U%1&`U%1&WR$0a(C,[(Y>]mK52>
+S1/s~>
+!liB.p?ho\d,"cFrkABC#JRd`]"YnY^<bX9s6K(Q<Is#EhST<hmV;=$AMbqd/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t-mC2j/1<%t/1<%t/1<%t/1<%t/1<%t/1;nt-nI2T
+KsJGHlKdj?H-4-8J,~>
+!quZ5p>u?QcZ9>u]tLed[(WjF]`FX4cZ9*dlfJ1FJTJ_M_Z0Jp"7EO*0nCeQ.0VG(K<2c:lK/2f
+s7W7=~>
+!i2>Hp?hoYdJj:)XS2Sl#kn;ls7ZKdXR=F7lg=aNJcCE'qsOIW"7G<r`IY`%]`c=!k3hs/mK5J>
+Ua^f~>
+!m8N2p?ho\dG=rEV=OW^qXt$fm\S4Uh>mTAmJp7<hS\3es823go'Z)6hTE]d])K8D_TLa#o'>]G
+IE'E<J,~>
+!rqu=p>u?Qd;o@uV"X`d#kn;ls7ZKdP\SQd!<;BI!)eAh_fN]pqr[nGJ*,V,]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tLed[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[/[fG[(Wi[
+[(XH8k3hQt"3pQ>S:C~>
+!h?&@p?hoYdJj9]XR?&\q<e:6[*Sd<mK-;ds82ljs8E#irr<&Rs8)fdrrW9$rrDio!!)cn!!)rs
+!!*#uquHNl!!)?b!!)rs!!*#uquF>.qX/+lme6):hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhVKF<hWE\WhWE\WhWE\WhWE\WhWE\WhWE\Ok2,7Wk2,Oop?M&J0r1<gJ,~>
+!liB.p?ho\dG>//Y3PTOo()5:r9=@GetLII!<;BQ!`e+6quHHIrW)QH!!(d1qZ-0C!s%37!;PCN
+!;G=M!;t[R!<1jQ!;PCN!:/JA!;t[R!<1jQ!;YKgs8)-do'Yr2k(2Ceh>ud(l0\Y!b/Rk?~>
+!quZ5p>u?Qd;o@uXR?&\q<e:6;UBIbs6JeK;KHpW!;:L5!:t73!8DSl!:b+4!-<2]pi?E8pN$<7
+r,Vi<rc@u;pi?E8lZ3%+r,Vi<rc@u;q/aFQqW;P\k3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e^Yi"e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,hUUK5hUUcNmcrp:`W,Y-
+J,~>
+!i2>Hp?hoYdJj9][-mqe$L[WUmcNs"mcNB5ci<>!"&f1!!<3#u!;HKn!:g'h!8IMR!:9^c!;6?l
+!;HKn!;uj!!<<'!o`"mklMghar;Qj!s8N)prr<&5s+0UhmK5J>Ua^f~>
+!m8N2p?ho\dG=r$Y3Q#Ws6fpPs5jIDk2Os[d,"d&lg=jThVJ83hZ!TMh>dQGh>dQ1h>dQBh>dQK
+h>dQMh>dQRh?*c7h>m3)!!)<@!!)rR!s%37!;YIO!<(cks+0UhmK7mWb$ff~>
+!rqu=p>u?Qd;o@u[-mqe$L[WUmcNs"mcNA(cuT3elfJ:IF)q?\F8l77ErZ41ErZ3pErZ4,ErZ45
+ErZ47ErZ4<EruD`ErbiR!!);*!!)q<!s!C`!;U[9!<$uUs+0=`jo`m%s."T~>
+!h?&@p?hoYdJj<^XR>NUpAaRZjoaK&e[3[&lg=jQs8N)ts8N)orr<&hrrW9$rrCpU!!)Bc!!)]l
+!!)cn!!)rs!s&B$!;-9k!:'Ra!;uj!!<<'!q#:<o^]/lQf'WVpUmrla~>
+!liB.p?ho\dG>G2Wp]0?o'Yf.k2tOWg>^\Sd,"d&lg=jThVJ82hZ!TNh>dQGh?*c7h>lEh!!)BB
+!!)]K!!)cM!!)rR!s%37!;,+J!:&D@!;t[U!8cQ4ptbuNrnbNlJaV+W"*r&/@=S~>
+!quZ5p>u?Qd;oD!XR>NUpAaRZjoaK&ePab8!<;BI"&a2]!<%!=!;LU8!:b+4!-<2]hK&YsluN.,
+olC*5pN$<7r,Vr?F)q?RErZ4*ErZ4<EruD`ErbuV!!*">_Z,2Lf&d(Rs7W7=~>
+!i2>Hp?hoYdJjck[-mYMk3hs2mcNZghWE\%ci<>!"&f1!!;uis!<3#t!<<)u!!*&t!<2uu!<3!$
+!<<'!s8E#Urr<&qrrE-"rW)rtr;clt"T\T&!<<)t!<3!!!<<#uqu6Wrr;Qm"s8N'!pAY*mrVuis
+rr3!!s8E#nrr<&srr`?%rr<&ps8N)7s+0UhmK5J>Ua^f~>
+!m8N2p?ho\dG>G2Y3tl?hWjOolK7*_g>^hWd,"d&lg=jThVJ81h>dQThYmNThYmKThYdHRh>dQT
+h?3i8h>lF3!8lW5!;bOQ!8d\TrndSRs5!nZhVJ7hhYdHRh>mW5rW)iP!!)rR"9@<8!!)`L!!)uS
+rW)rS!<D!U!;PCN!;t[V!8cQ4!;YLO!<:oms+0UhmK7mWb$ff~>
+!rqu=p>u?Qd;ok.[-mYMk3hs2mcNZghWEZmcuT3elfJ:IF)q?ZErZ4>F8c1>F8c.>F8Z+<ErZ4>
+Es)JaEr^:\!8hht!;^a;!-A,>rcA#<s)S>DF)q>&F8Z+<Erc8^rW)h:!!)q<"9<La!!)_6!!)t=
+rW)q=!<@3?!;LU8!;pm@!-<2]!;U^9!<7,Ws+0=`jo`m%s."T~>
+!h?&@p?hoYdJjck[.a449%E@tk3hBoe`P_qci<>!"&f1!!;uj(!<<'!s8N'!s8N)rrrW9$rrE&u
+"p"]'!<<'!hZ!QUqZ$Qqs8NW1s8N'!s8N*!rrE*!!<<'!qu?Zrs8N'!qu6Wrr;Q`srr;rtq#:<o
+rr3?+s8N'!s8N'!s8N)orr<&srr<&us8E#prr<&7s+0UhmK52>S1/s~>
+!liB.p?ho\dG>G2Y4D;'7+UYgk2t[[f&GDSd,"d&lg=jThVJ81h?j8>h>lEh!!(m4!;kUT!8cQ4
+rn[hZhVJ7hh>lEh!!)lPrrE)U&-1SD!!(m4!8cQ4hVJ7hh>mH0rrE)U!!)oQ!!)rR!!*#TrW)`M
+!!*#T$NT&?!!(m4!!(m4!;PCN!;t[R!<1jS!;bOR!8cSLs+0UhmK7aW`aOA~>
+!quZ5p>u?Qd;ok.[.a449%E@tk3hBoe`P^dcuT3elfJ:IF)q?ZEs_ngEr^9&!!%(]!;gg>!-<2]
+rc88DF)q>&Erb'<!!)k:rrE(?&--cm!!%(]!-<2]F)q>&Erc)YrrE(?!!)n;!!)q<!!*">rW)_7
+!!*">$NP6h!!%(]!!%(]!;LU8!;pm<!<.'=!;^a<!-<4us+0=`jo`U&p8!3~>
+!i2>Hp?hoYdJs6[%efq0C>S[HmcNZghWEt-ci<>!"&f1!!;uj!!<3$!rr3'#s8N)rrrW9$rrE&u
+"p"]'!<<'!hZ*HQs8N'!rr3'#s8N)ursAc+rrE*!!<<'!!;uis!<2uu!;lcr!;uis!;ulr!;c]u
+!<<'!!<3!#!<<'!rr2ruq#:<or;Q`sr;Z`rr;Q`s_#JuRf'WW#S>7Ta~>
+!m8N2p?ho\dG>G2](5m0A_QS7k2PCSf&G\[d,"d&lg=jThVJ81h?*c7!!*#T!s%37!;kUT!8cQ4
+rn[hZhVJ7hh>lEhqZ-ZQ!!*#T!s%37!<1g^!8cQ4hVJ7hh>dQRh>dQTh>dQQh>dQRh>dQRhYmNO
+h?3i8h>dQTh?*c7h>mQ3!!)fN!!)rR!!)rRrW)lQ!W_*6_Z,2Tf'WWg`l__?~>
+!rqu=p>u?Qd;ok.^%VK5C>S[HmcNZghWErucuT3elfJ:IF)q?ZEruD`!!*">!s!C`!;gg>!-<2]
+rc88DF)q>&Erb'<qZ-Y;!!*">!s!C`!<.$H!-<2]F)q>&ErZ4<ErZ4>ErZ4;ErZ4<ErZ4<F8c19
+Es)JaErZ4>EruD`Erc2\!!)e8!!)q<!!)q<rW)k;!W[:__Z,2Lf&d(ZpA^Y5~>
+!h?&@p?hoYdJs6["8;cgk5OfIjoaK.k-WJ7lg=jQs8N)srrE-"qZ-Zr!!*#ur;clt!!*#u"p"]'
+!<<'!hZ!QUqYpNqrr3'#s8N)urrrK'rrE*!!<3#t!<2uu!<2uu!;lcr!;uis!;c`q!;lct!<<)r
+!<<'!!<2uu!;QQo!;uis!;c`q!<)ot!5SVcmage.0r1<gJ,~>
+!liB.p?ho\dG>G2^@qEok3hO"k2t[[g?R[gd,"d&lg=jThVJ81h>mW5qZ-ZQ!!*#Tr;clS!!*#T
+"p!N:!8cQ4hVJ54qVD2Prn[_WhVJ83h?Eu:h>lEh!<1jS!<1gT!<1gT!;kUQ!;t[R!;bRP!;kUS
+!8cT0!<:mU!<1gT!;PCN!;t[R!;bRP!<(aU!8cSLs+0UhmK7aW`aOA~>
+!quZ5p>u?Qd;oJ#^%VL"k5OfIjoaK.k#0QI!<;BI"&a2]!;pm=!-A#;s)S/?rcA#<s)S/?rc88D
+F)q>&Erb'<!!)k:!!*">!s!C`!<.$D!-<2]F)q?\F8c1=ErZ4>ErZ4;ErZ4<ErZ4:F8l7;Erl>_
+F8Gt;ErZ4>ErZ48ErZ4<ErZ4:F8l7=Erl>_F2Is.k18Ys`W,Y-J,~>
+!i2>Hp?hoYdJj6\c2%ADpAaj[s6d8?s6K(T;ZHasrVult!ri6#qu6`us8N)urrW9$rrE&u"p"]'
+!<<'!hZ!QUqYpNqrr3'#s8N)urrrK'rrE*!!;uls!<<'!!<2uu!;lcr!;uis!;ZWp!;ld!!<<'!
+!;lcr!<2uu!;QQo!;uis!;ZWp!<)ot!5SX3mXb*&p?V,K3LlloJ,~>
+!m8N2p?ho\dG=r)b4bi7s8)]fs7-6bk+0lU!<;BQ"'+47!<(dS!!;!W!;kUT!8cQ4rn[_WhVJ83
+h?Eu:h>lEh!8cQ4!;bOP!<1gW!8cQ4rn[hZhVJ7hh>mK1rrE)U!!*#T!!)oQ!!)rR!!)iO!!)oQ
+"9@<8!!)oQ!!*#T!!)fN!!)rR!!)iO!!)uS!W_*6_Z0N$C\$oamdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:nfmMmmdff:mdff:mdff:mdff:mdff:mdfr:o'Z):o'Z):
+o'>]GIE'E<J,~>
+!rqu=p>u?Qd;o=tc2%ADpAaj[s6`e3Erc7+jo\M&Erc/[rr<+A!!)n;!s!C`!<.$A!-<2]rc88D
+F)q>&Erb'<!!)k:!!*">!s!C`!<.$D!-<2]F)q?ZF8l7?ErZ4>ErZ4;ErZ4<ErZ49ErZ4;Es)Ja
+ErZ4;ErZ4>ErZ48ErZ4<ErZ49ErZ4=Erl>_F2ItSk(2skmd'!;c1_1-J,~>
+!h?&@p?hoYdJj9ec0##nrV$0h!Tpc8s6K(T;ZHasrr;uurr2ruqu6`us8N)urs\u.rrE*!!!*'!
+!<<'!hZ!QUqYpNqrr3E-s8N*!rr<'!rrE*!!;lcu!<<'!rr2ruqu?Zrrr;uus8N'!rVultqu6Wr
+rr2ruqu6Wrrr2ruq#C?orr;uus8N'!rVultrr;uu_#O9!CA.)hme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6):+nk?tme6)Bme6)Bme6)Bme6)Bme6)BmdBf:p?qYBp?qY>
+mK52>S1/s~>
+!liB.p?ho\dG>&,cJIjSmf)bYpA4XbrrM8Qd,"d&lg=jThVJ83hZ!TTh>dQQh?*c7h>mQ3%058A
+!8cQ4!8cQ4hVJ7hh>dQPh>dQTh@0JAh>lEh!!(m4!8cQ4qq_DThVJ83h>dQQhZ!TThZ!TUh>dQS
+hZ!TQh>dQTh>dQQh>dQTh>dQNhZ!TThZ!TUh>dQShZ!TThZ!TUhST<hmV;=\o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):mNM/ho'Z):o'Z):o'Z):o'Z):o'Z):o'Yr:
+mdff:mdff:lL"b"b/Rk?~>
+!quZ5p>u?Qd;o@uc0##nrV$0h!Tm;,Erc7+jo\M&Erc2\rrE%>!!)n;!s!C`!<.$K!-<2]F)q<]
+F)q>&Erb'<!!)k:!!*">%01Hj!-<2]!-<2]F)q?YEruD`Erc2\!!)n;rrE%>rrE(?!!)t=rrDq;
+!!*">!!)n;!!*">!!)e8rrE%>rrE(?!!)t=rrE%>rrE(?_Z0JpC@:6Pk3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBo+n"L\k3hC"k3hC"k3hC"k3hC"k3hC"k2u*omcNs"
+mcNs&jo`U&p8!3~>
+!i2>Hp?hoYf)Ga<roP$R[)L#/c.1)$pAaRCk3hZfSDNDjhWEtNs6K(S;ZHdp!;ulq!<<'#!<<)r
+!!*&u!!rT)s8N*!rr<&Vs7u]rrrE&u!!*#urr<B*!<<'!s8N*!s8;rsrr<&urr<&qs82lrs8)fl
+rr<&us8;rtrr<&urr<&ns82lrs8)fprr<&6s826ap4<8=s8DZWmK5J>Ua^f~>
+!m8N2p?ho\f%pDPrlPnoS\iChb0J;lo(MA.io]COM8IF6`n&uHs6K(S<SlU1!;t^P!<:mW!8cT0
+!!(mT!!qE]hVJ7hh>dQ5hYI3Qh>mQ3!!*#Trr<A^!8cQ4hVJ7hhYdHRh>dQTh>dQPhY[BQhYR<K
+h>dQThYdHSh>dQTh>dQMhY[BQhYR<Oh>dQThST<imK<%JpA0@?r;Qrsp?qM>o'>]GIE'E<J,~>
+!rqu=p>u?QeoUh;s)S`d`Pp*He]m7Ms6f%3mdAV'cuT3elfJ7HF*%6Zr,_f:s)S5AF*%3Y!-A,>
+#]fueEr^9&!!(ntq>^P;!<.$>!<.'>!"!]HF)q>&Er^9&r;ch<!!*">!!)k:quH_;qZ-G5!!*">
+r;ck=!!*">!!)b7quH_;qZ-S9!!*">_Z0Mqs6fjZIfK-ApAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAb0ds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKm!VZQlpAOFFjo`m%s."T~>
+!h?&@p?hoYf`)!GXS_,fhWE\WhVPs6hTb3NqrS%<k2+Xaf)P((!)fZnrrCFG!!)Tiq>fs`!!'b5
+qX4CWr;ZfbGinGVmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcN["k3hC"k3hC"k3hC"
+k3hC"k3hC"k3i-/"Rc!Wme5r6"#6UA.=_~>
+!liB.p?ho\f\Q\\U#u:4&`2O(iniP+k1[u?k2PCWio]8"h>u&ifA6N-lg=aQV;D4Pd,"a&o%s3C
+mbRpDrSGEkqX4CSs7UpAqXWq6io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io9+[
+k2PO_k2PO_k2PO_k2PO_k2PO_k2QEt#NFV"k3hg.o'5WFH-4-8J,~>
+!quZ5p>u?QfQ.(.Hi)q5hWE\WhVPs6hTb3NqrS%<k2+Wtf5grllfJ1FV/uY:cuT0enoOX-mW/@.
+rH#jUqW@hG#PRTcp?peoec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+G*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+G&eHFakmcNs&jo`U&p8!3~>
+!i2>Hp?hoYf`(uZ^&7m2pAb-c"on;YXIRQ7rsJK"k1/o"pAaR;^"<;MmJp.`s8;rCrr<%as823e
+p?qA2p4<5FmcNC)k5P)?mK5J>Ua^f~>
+!m8N2p?ho\f\Qb%](Z!srUq#tp@@qJii89ds8)Tcp?'fkp@@qBetq$U!<;BQ!*,uSr;b."!!(O*
+_Z0K##3+e)lMCP\rq^$rqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'd^,51m,qY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*lg=k'`l__?~>
+!rqu=p>u?QfQ.(&^&7m2pAb-c"on;YXIRQ7rsJK"k1/o"pAaR;>1dlrs6JeI;Q+[8!7#Wc!7Z),
+s81pYmf)&Ek4\iPp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OOZp&OO[p&OO[p&OO[
+p&OO[p&OO[p''mXmbZL=rRLo8lfJ;opA^Y5~>
+!h?&@p?hoYf`(uB^&@['mK_nBk3hB=Mq.e""7F-uc2R/2joD4/s6K(Q;M"k$s826ak5O4grr`;`
+hUVS]l0\X.Umrla~>
+!liB.p?ho\f\QXg])D4"mf2PQk3Ds."0.4'pAXUhm_YC3mcrrok)n<Q!<;BQ!*+U,_qr91qsFI@
+rRq8FrVq?Cs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqYKpJf$aNN!:&k;"*r&/@=S~>
+!quZ5p>u?QfQ.'s^&@['mK_nBk3hB5Mq.e""7F-uc2R/2joA<3Erc7+joA;1F2N(9s81sVeHG=6
+s7ZJIp':$Bc-=e`e^`pH"3(<6Ujr~>
+!i2>Hp?hoYf`)&D^%UmnpAaOrk3hBohX7b8c2[5*me4W,V!dC-hX72ks6K(Q;M"k$s823fhWEtN
+hY)O##QNr:e`P`=hWjM23LlloJ,~>
+!m8N2p?ho\f\R^4[dr_SmdBB*k2t[_hWh8'cM$\smde5tV<[("hWg6Uh>mTAmJp7<hS\3es823f
+db<F'f(+Cl#PR$&db`^'g?S).IE'E<J,~>
+!rqu=p>u?QfQ.-u^%UmnpAaOrk3hBohX7J0c2[5*me4W,V!dC-hX4:oErc7+joA;1F2N(9s81p^
+c.1@hc0kH.!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j
+!;??j!;??j!;??j!;??j!;??j!;??j!;??j$23f;c-=ehc.27Jjo`m%s."T~>
+!h?&@p?hoYf`)2H^%Um^p?qYQk5X9Mm^.nsp?qABhS%d1`TH%6m\JJ7lg=aNJcCE'qsFL0k5Nm2
+p4<5Es6fm:"5_;Ik3MF;0r1<gJ,~>
+!liB.p?ho\f\R^4](5.So'Yr.k2P7Og?Pu#cLU8go%(P3Oi$,3g?OgQh>mTAmJp7<s+LFLmKU\b
+da$;/qL\_Qp?'ZGdb;^`ip6"7H-4-8J,~>
+!quZ5p>u?QfQ.:$^%Um^p?qYQk5X9Mm];>kp?qABhS%d1`TH%6mS_\Y!<;BI!)eCJK`Cr3!PR%_
+`<PJmp@eO[s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp'1Qjs7ZK\hYtIre\/rYlfJ;gs7W7=~>
+!i2>Hp?hoYf`*%h^&RfohX8q^mcNB_eb6A7ec5(*p8$7=P^DQLhY*bss6K(Q;M"k$s823f`ST.i
+eaA"g#lj>Cc.1sq^#nYK"$)mI.=_~>
+!m8N2p?ho\f\R^4])(jWf':]Kk2P7Of']i'cMHhknt"A.Q$MBCf'\[Qh>mTAmJp7<s+LFLmK^J[
+d`0`#pA0IB$2XATcGn;d^:rUmmK7mWb$ff~>
+!rqu=p>u?QfQ/-D^&RfohX8q^mcNB_eb6)/ec5(*p8$7=P^DQLhY'k"Erc7+joA;1s+LFLjor-B
+c+VBarUtL9pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdrUpKQ`P'OH[(Y>^jo`m%s."T~>
+!h?&@p?hoYf`*%``W)`dC3,$amcNZ^eaC,8hZ*<CeWd0'P]PC*hX72ks6K(Q;M"k$s823b[,1f,
+!Uf[Ns82ljrr<&as82lqrr<&mrr<&HrrMi]rlkQ%[(Y>^mK52>S1/s~>
+!liB.p?ho\f\R^4_YTgSBlS^\k2P7KddFE'f)"h&cBYR#NHN\#f'\[Qh>mTAmJp7<s+LFLmK^&K
+b/2<`o(MVMquHHe!!)<\quH]l!!)`h!!(ID$23rPb/2<PZF\oYmK7aW`aOA~>
+!quZ5p>u?QfQ/-<`W)`dC3,$amcNZ^eaBf/hZ*<CeWd0'P]PC*hX4:oErc7+joA;1s+LFLjoqR*
+`P&tArpBg\mf)n]me6)Jp&jaVme6PYrq6E]p?qqR!q,a^rq6E]p?qqR!q,dMrq6E]p?qqR!Uf[Z
+!!i5cp@\LSp?qqR#k%ESp@\LSp?qqR!q,dMrq6E]p?qqR!q,dMrq6E]p?qqR!q,dMrq6E]p?qqR
+"7GmNpAXIbhS$VAc(q_slfJ;gs7W7=~>
+!i2>Hp?hoYf`*%hc2WEKC4i>Ek3hBgec3=QhZ*<L^"&X"S@uo(hZ'D's6K(Q;M"k$s823hXPV4@
+e`QT!r;Qcjr;QcjrVm*&pAb-m!<;cjrs&2srrE*!pAFpjpAFpjpAFprpAb-ms8Vcm!<2uupAFpj
+pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFsjp'9a1`Qd8@^#nYK"$)mI.=_~>
+!m8N2p?ho\f\R^8b5-O7Bn;i3k2tOWf(QD;gAga?]$?RdQ+"QdhY*)ah>mTAmJp7<s+LFLmR<u#
+b.c$To()MFp@@qJp@@qJp@@qJp@84Sp@81`p@@qJp@@qJp@84Sp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@84Sp@81`8G;WJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo((Y[^<4m#]&)c@"+A23@=S~>
+!rqu=p>u?QfQ/-Dc2WEKC4i>Ek3hBgec3"HhZ*<L^"&X"S@uo(hZ$L+Erc7+joA;1s+LFLjpIp/
+`O*V7mcO62pAXI]p?qYRmLJsYp?hqKp?hn\mdBf:pAXI]p?hq[mK3+MpAXI]p?qYRmK3+MpAXI]
+p?hq[mf*7epAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]
+p?qYRmLJsYp?qYBma]:``Qb3chWs;+c1_1-J,~>
+!h?&@p?hoYf`))Mec5@*r9jUI'AhmO]q"6bs7Z0:c-=5Xmb[+"Ut>Y4mJp.9s+LFLmRE`'`Pp*a
+me6ASpAajdpAajdpAajdpAY-mpAagd!<;cmpAajdpAY-mpAajdpAajd!<;cmpAajdpAajdpAY-m
+pAagd!([(_s7ZKds7ZKdrrE)ms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKdp?q(f`Pp](^#&)C"#6UA.=_~>
+!liB.p?ho\f\R^8cN!ItlK[g&lK7*_hY+CKhZ*<Cm`rht_U@T'k44Yeh>mTAmJp7<s+LFLmKSs)
+_S4%HmdTcI!<)Kg!;Q*b!;Q*b!;,g^!<)Kg!;>s`!7(-@mbYst_U=^\hWsS3H-4-8J,~>
+!quZ5p>u?QfQ.1)ec5@*r9jUI'AhmO[%-:Ys7Z0:c-=5Xmb[+";V6$js6JeI;M"k$s81p_Pg-nK
+^")97mJm7cmf*:^mJm7^mJm7ZmJm7cmf*:\mJm74mKht*]sPJtPdK!,jo`U&p8!3~>
+!i2>Hp?hoYf`(uRebK.KpAajd]r^AkrrDclrrAkHs6K(Q;M"k$s823fPh"$lc/.p_!!)rj!!*#l
+rW)rk!!*#lrW)ulrW)ulrW)fg!!)rj!s&&g!<2]g!!2cnrq?9jrq6?mpAP'lpAG!jp&P0erW)rk
+!!)Q_#Nj:Ec./&lk3MF;3LlloJ,~>
+!m8N2p?ho\f\QXsf)5RHqYp0ns0AZ]s8)clrVm&tp@e@ZOkALjs6K(Q<It1's823hOj_7\`nK_C
+na6AWr9aObrpKacrpBadrpKacs6fjds6fjdqX+=`r9aXemd:)SmeQnamK!7Sr;cib!<DQe!<;Kc
+!<2Be!:KgdrpBadoBuYD#MR2/`mU!\hWsS3IE'E<J,~>
+!rqu=p>u?QfQ.(&ebK.KpAajd[&iEbrrDclrr>sLErc7+joA;1s+LFLjroZ%]sPK'k2u*omcNs"
+mcNs"mcNs"mcFN3mcNs"!9W_3rW!/bmcFN3mcOKK!TrhL!!2NMrW!VomcNs"mcFN3mcNs"!9W\L
+mcNs6!!M]imcNs9!!MHPjoFQC!!26Mr;Zu_mcFN3rW!o"mcFN3mcNs"mcNs"mcNs"mcNZ^]sPJt
+MmV@,jo`m%s."T~>
+!h?&@p?hoYf`)/WhVRDWmdC&IrVm8=[+4$qk3h[2pAajbrrAkHs6K(Q;M"k$s823bK@Tt?!8d_C
+HM6e#me6)Bme6)Bme6)B!;>jSme-YSmJu\K!!)H\!;>g\me-V\me-YSmJu\K!!)H\me6)B!;>jS
+me-YSmJu\K!!)H\me-YSmJu\K!!)H\!!)H\!!)H\!;>jSme6&Kme-V\me-YSme-YSme6)Bme6)B
+me6)BrpC$R`P'7IK>$.-mK52>S1/s~>
+!liB.p?ho\f\R^<f%T-Ck3DC&o(MqVs8TO1f%T-ClK[g*p@e@_s8%l1h>mTAmJp7<s+LFLmKSBn
+_RdV<k4%X9!;u+$!:&hLlKS?LlKSB7l2^,7!!)<L!:&hLlKS?Lqs".]r9=LelKSB7l2Uh_l4O*^
+l2^,7!!)<L!!)<L!!)<L!;l$d!:&hL!:&hLrosI`o'-MCg;:G<dY59hlg=k#b/Rk?~>
+!quZ5p>u?QfQ.7+hVRDWmdC&IrVuo)$.[npk3h[2pAajbrr>sLErc7+joA;1s+LFLjpHI[]sPK'
+hWE\WhYuX=hWE\ojsJsIhW=h#hWE\W!9W,<hW=e<hW=h#joF9#!!)0D!9W,<k2lXDhYuX=hW=h;
+jriOC!9WDDhW=e<k2tO_!9WDDhW=e<k2lXDhW=e<hW=h;jpp81h>l^#!!(m<!9W/#!<2*^hWE\o
+jpp81hWE\WhUT<H^!1o2ea)?"`W,Y-J,~>
+!i2>Hp?hoYf`(uRk5F`JpA4dj]uB.4mf3"WrrAkHs6K(Q;M"k$s823hK@S5[c/.mNr9aRIr9aRI
+rU'[dk5F]M!9O7]rpBsjmd:)C!!*#d$39MV!:BgemcNp;rpD8umd:)CmcNs*!:K7Tmd:)CmcNs*
+!:K7Tmd:)CmcNp;md:);md:)CmcON:!s%cO!<2Bg!9W\LrpBdKr9aRIr9amRmbZ4%c..H[k3MF;
+3LlloJ,~>
+!m8N2p?ho\f\QUrroOCLmdfrFqY^@#]"[%`k3h[.pA4X`rrA26h>mTAmJp7<s+LFLmPTRD`k'1@
+io9+[k2PO_k2PO_k2PO_k2HC#k2PO_!9*tYk2PM'k2HC#!!)0@joFQ'!9*tY=Q\W*!9W;'io]5#
+io]7_iW/!#!9W8@io]7_iW/!#!9W8@io]7_!9W8@io]5#io]7_ioU7'iW/!#iW/!#!9W;'io]7_
+io]7_io]7_io8P/]#N0L]&)c@"+A23@=S~>
+!rqu=p>u?QfQ.(.k5F`JpA4dj[)M2+mf3"Wrr>sLErc7+joA;1s+LFLjp-7X]sPJthUV/Q!!)rR
+!s%0X!<1gZ!8cQ4h>dQTh?Eu:h>lC4!<1gT!;kUQ!;t[X!8cQ4hVJ81h?Eu:h>lEh!<(aV!8cQ4
+rn[VTqq_DThVJ83h?*c7h>m'%#L0rh]u>?*hWs;+c1_1-J,~>
+!h?&@p?hoYf`*%hc,IrHc-=e`e^`O,hVOd(c,IrHc-=e`e^`O,hUSFRs6K(Q;M"k$s823fF5FmL
+`SUUV(@L>Qk3hC"k3hC"k3hC"!:K";k3`6;qZ$`\mJu\P!!DBO!:K^a/`uK`mcNp;mcNs"mJu\;
+!9W\LmcNs"mJu\;!9W\LmcNs"!9W\LmcNp;mcNs9!#t(g!:K";!!)-]k3hC"k3hC"k3hC"k3hC"
+k2-*V"4_J+hWsS30r1<gJ,~>
+!liB.p?ho\f\QXob5TE\b5]cedf7nug(9[P`koa8b0&#TdaH^tg<tu5h>mTAmJp7<s+LFLmKRg^
+_RdV8hXKM)!;tgW!93kUs5F%Ziqi`UiW0&=qZ-NQ!!)rV"p!ZB!92u<r8In\io0stiW/r:!s%??
+!<1sX!<2!V!<;$Y!<2!X!!2'Zn_si2f###8dWN.Xlg=k#b/Rk?~>
+!quZ5p>u?QfQ/-Dc,IrHc-=e`e^`O,hVOKmc,IrHc-=e`e^`O,hUPNVErc7+joA;1s+LFLjr\?_
+['[Nke_\j5e_\j5e_\j5e_\j5e_U;_e_\j5!8dSQ"4c6.hYR9Te_U;_qZ&4uhUUK5h>lE_hUUH_
+hUMVVh>lE_hUUH_hUMVVh>lE_hUMVVh>lE_h>lE_hYdEue_U;_e_U9+eH".Ve_\j5e_\j5e_\j5
+e_\j$]sP/kC:)OWjo`U&p8!3~>
+!i2>Hp?hoYf`(s6o;qu!o;hrBfDk1)!)eCJK`Cr;"`r5=^!5F&jo>D[k5PD_jo>DYjoYVG!!)oY
+!s%H`!;GUU!<)'[!<;0`!9WDDr8n1`k2l[+joGAB!s%KG!<2*_!9WDDroO:_k2l[Bk5GAMjp0bf
+^!5)K^#nYK"$)mI.=_~>
+!m8N2p?ho\f\QVJo9B?IU%FTNOh03%!<;BQ!*+UMK`Cr;Ec'7E]#*%ThW!DOhW!DOhW!DOhW!DO
+h>lElhVnM8h>dQ8hW!DOh>lC4!92kphW!Alh>dQ8hW!DOhW!DOh>lElhVnM8hVnOph>lElhW!Al
+hVnOph>lElhVnOph>lElh>lEl!92kp!92i8hW!DOrW!ephW!DOhW!DOhW!DOhW!DKf###<dVZSP
+lg=k'`l__?~>
+!rqu=p>u?QfQ.%%o1K$\o1B!lfQ.&mlfJ1FJcCE'qrVp6`P&Xlc/."-e_\j5e_\j5e_\j5e_\gV
+e_\j5!!(OL!8c8_e_\gVeGoU+e_\j5eH","!8c8_e_\j5e_\gVe_\j5!!(R+!8c6+e_\j5eH".V
+!8c6+e_\j5!8c6+e_\gVe_U;_e_U;_eH".Ve_^9*(uEg"e_\j5e_\j5e_\j5e_\QaXM)kn[,1-2
+"3pQ>S:C~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;!FjUY`W+eDk2,7Wk2,7Wk2,7Wk2,7WjoFQ#jo>D<k2$*pk2,7W
+joFQ#!8ckpk2,5#k2$*pk2,7Wk2,7WjoFQ#jo>D<k2$*pjo>D<k2,5#k2$*pjo>D<jo>D<joFQ#
+joFQ#!8ckp!8ci<k2,7W!!)0<k2,7Wk2,7Wk2,7Wk2,8#h?Ls4`SP(;hWsS30r1<gJ,~>
+!liB.p?ho\O59m:lg=aQJcCE'qsFYsd_`T0f%U,[GhV$.hV-i?hV-i?hV-fdhV-fd!8?;`!8?;`
+hV-fdhV%t`hV-i?h>lEd!8?;`hV-i?hV-fdhV-fd!8?;`!8?90!8?;`h>lEd!8?90!8?90!8?90
+hV-fdhV%t`hV%t`h>lEdhV%r0hV-i?hV-i?hV-i?hV.tc#hmkD]#)m(]&)c@"*r&/@=S~>
+!quZ5p>u?QO)k=$lfJ1FJcCE'qrS)dc+UKkc-?7<Gg4d`e]lXhe]lXhe]lVEe]lVE!6s'=!6s'=
+e]lVEe]e*=e]lXheH".E!6s'=e]lXhe]lVEe]lVE!6s'=!6s$o!6s'=eH".E!6s$o!6s$o!6s$o
+e]lVEe]e*=e]e*=eH".Ee]e'oe]lXhe]lXhe]lXhe]n*Ds3:SN"MN&`[+4L)"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;(Lkq>^!5ErhWE\WhWE\WhWE\WhWE\WhY[?VhWE\WhYdEXk2$*p
+k2-%:"m4YA!9W/:!!VNAk2,7Wqu?uYk2,5#k2,8!!!h?\!9O:DhWFb:$/Xh$!8ckp!8cl8!$U2!
+hWE\W!!(m<hWE\WhWE\WhWE\WhWE\WhT`aYeRH5Slg=j8S>7Ta~>
+!m8N2p?ho\O59m:lg=aQJcCE'qsG8+d`/l8db<F3g>:Q?g>:Q?g>:Q?g>:Q]!!M$4g>:Q^!!V65
+!8?;`r;[#Xg&M-0gAM!ThV-i?hV.l-#MS%gh>lEdhYdEZg&M-0!8cGdr;[/XhV%t`hV%t`hYR9r
+g&Tj`g>2f0g>:Q?g>:Q?g>:Q?g>:Q?g=jul]#N0(]&)c@"+A23@=S~>
+!rqu=p>u?QO)k=$lfJ1FJcCE'qrS&cc+UKtc0s3\!;tCG!<:RL!<1OI!<:UL!<:UJ!;k=E!<(FJ
+!<1OI!!LgP!7_)KeboLIeGoUKeH,a$eb]=IeH#QurrDN<#L0rh^!0`fhWs;+c1_1-J,~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;##a=&`Pp]jIcfMLhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\Wh>lEphWE\WhWE\WhWE\WhWE\Ws5*dp"O5e$^#&)C"#6UA.=_~>
+!liB.p?ho\O59m:lg=aQJcCE'qsFVff#GG@dZiGc!:JPGf##/@elB<<lg=k#b/Rk?~>
+!quZ5p>u?QO)k=$lfJ1FJcCE'qrS)\c+UKtc-:^fc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1&=c.1(hc.1(hc.1(hc.1(hc.2j=#/.CWbu1q!lfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;"]F4-`Qcs4jpg20hWE\WhWE\WhWE\Wp],3ohWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhW=h#hWE\WhWE\WhWE\WhWE\WhWE\>`RWgC^#nYK"$)mI.=_~>
+!m8N2p?ho\O59m:lg=aQJcCE'qsG4nf$;.Pdb`^7g>:Q?g>:Q?g>:Q?g>;T)DVj+(g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?!8cGdg>:Q?g>:Q?g>:Q?g>:Q?f#GSPekE[3lg=k'`l__?~>
+!rqu=p>u?QO)k=$lfJ1FJcCE'qrS&Sc,IB0c1'9Y!3XiP!:JABc+UL'bt>A"lfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;#smFuc,JPrk2,8"h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9
+h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h?i?$hTa<q
+hEej3lg=j0Umrla~>
+!liB.p?ho\O59m:lg=aQJcCE'qsF\Wf$;:Pdb<Q2g'QWif#l"Xg-iO/lg=k#b/Rk?~>
+!quZ5p>u?QO)k=$lfJ1FJcCE'qrS)Kc,IB0c-:^fc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.2j=s1JQSeNpRmlfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;#?oC/c.1A$hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9
+hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYQ@>hUU05bu27;
+lg=j8S>7Ta~>
+!m8N2p?ho\O59m:lg=aQJcCE'qsF\hb1=_Xdb<E)hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hVR8Gs3:bub"TD'lg=k'`l__?~>
+!rqu=p>u?QO)k=$lfJ1FJcCE'qrS&[`QcB@c%4CNhTa<ac,E;^hWs;+c1_1-J,~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;hYuX<mcON*"0>tFk3MF;0r1<gJ,~>
+!liB.p?ho\O59m:lg=aQJcCE'qsF]/WnPnHcIU_KhKmo4g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:]?hV-i?hV-i?hV-i?hV-i?hV-i?hV-iGiX"]'f$`9T?+SnYmK7aW`aOA~>
+!quZ5p>u?QO)k=$lfJ1FJcCE'qrS-)Ut*`/`QcY]ec+D1e]l@hUft.^lfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;!khLVrn[_,hVNtK$1@NTk2t2lMoFQ=mK5J>Ua^f~>
+!m8N2p?ho\O59m:lg=aQJcCE'qsFa$9Zkr;daH_#L#*-qmcNB_c:ir+hWsS3IE'E<J,~>
+!rqu=p>u?QO)k=$lfJ1FJcCE'qrRse9#^eS!l`F/L"-Ldk2+Y=`Cbcrea)?"c1_1-J,~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;#53sIXOZ1irn_n^hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WroOIRk2*I;C:)7NmK52>S1/s~>
+!liB.p?ho\O59m:lg=aQJcCE'qsF^[NC9Vgf%S]/g&U"/iWdu:885BPk3MF;H-4-8J,~>
+!quZ5p>u?QO)k=$lfJ1FJcCE'qrV\^Mb9eac.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1>[c.1(hc.1(hc.1(hc.1(hc.1(hc.1)<ec4J0c(ms@XMsJe"3(<6Ujr~>
+!i2>Hp?hoYi;`fWg&M'Pg]-U-!)eCJK`Co:#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r@.b$"B'lZ^#&&B"$)mI.=_~>
+!m8N2p?ho\i84J6g"u`/gti&2lg=aQJcCE'qX/+h[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-n$8j-nHbt-nHbt-nHbt-nHbt-nHbt-nHbp/1<&+<J@`mg?S"l"+A23
+@=S~>
+!rqu=p>u?Qi,enuflR/ngiEJqlfJ1FJcCE'qW7nJZskb@.K1b"0iEY*^")E1"3pQ>S:C~>
+!h?&@p?hoYr;Zcsrr;uurr;uunc/UhqZ$Emk5YG]oDegjli6;=!)eCJK`Cr;rq6H^k0:kr^&G\J
+`QdQ5p?V,K0r1<gJ,~>
+!liB.p?ho\r8.GRrndYTrndYTn_X9GqVM)Lk2-+<oA9KIm+qaBlg=aQJcCE'qsF[ZmdfZ"b//_@
+rji6Lb22FSlg=k#b/Rk?~>
+!quZ5p>u?Qr,_l<rcA)>rcA)>nT4^1qK)N6k&^P&o5jp3luN1,lfJ1FJcCE'qr[nGJ*,V,]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tLed[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[
+[/[fG[(Wi[[(XH8k3hQt"3(<6Ujr~>
+!i2>Hp?hoYqu6Wrrr;uurr2runGiLgqu?ZrrVlitk5YG]p](6nkPsl9!)eCJK`Co:CA.)hmdAro
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\O+m.YDhWE\WhWE\WhWE\WhWE\W
+hWE\WhVRDOk2,7WmdBf6mK5J>Ua^f~>
+!m8N2p?ho\qq_;QrndYTrn[VTnD=0Fqqh>QrS@MSk2-+<pYPoMkhZ=>lg=aQJcCE'qX+LWmdBB&
+J_p=]!Tr\3mK7mWb$ff~>
+!rqu=p>u?Qqf;`;rcA)>rc8&>n8nU0qfDc;rGqr=k&^P&pN-?7k]6b(lfJ1FJcCE'qW;P\k3hBo
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^Yi"e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j,hUUK5hUUcNmcrp:c1_1-J,~>
+!h?&@p?hoYqu?Zrs8W&us8N'!rr;rtrr;os!<;rsr;Zcsq>^Eorr;`nrr;lrs8W*!rr;oss8W#t
+!ri6#rr;rtrr;uu!ri6#q>]dK!)eCJK`?Vkf'WVpUmrla~>
+!liB.p?ho\qqh>Qs5*_Ts5!_UrndVSrndSR!8dVRr8.GRq;2)NrndDMrndPQs5*bUrndSRs5*\S
+!o<nWrndVSrndYT!o<nWqVD5Plg=aQJcCE'JaV+W"*r&/@=S~>
+!quZ5p>u?QqfDc;s)\/>s)S/?rcA&=rcA#<!-A&<r,_l<q/cN8rc@i7rc@u;s)\2?rcA#<s)\,=
+!cn>ArcA&=rcA)>!cn>AqJuZ:lfJ1FJcCE'J`bPG"3(<6Ujr~>
+!i2>Hp?hoYqu?Zrs8W&u%K?D.s8N'!rr<'!rr<&us8N'#rr<&ss8N)qs8N'%rr<'!s8Duus8E!$
+rr<'!s8E!>rr<'!!!*'!!!*'!!!*'!!!*'!!!*'!!!*$!!<<)u!!<0#!;c`]mJp.9s+LE'mage.
+3LlloJ,~>
+!m8N2p?ho\qqh>Qs5*_T%Gh'bhVJ54h>dQ4h>dQThZ!QWh>dQRhZ!TPhZ!QYh>dQ4hYmKThYmKX
+h>dQ4hYmKrh>dQ4!!(m4!!(m4!!(m4!!(m4!!(m4!!(jU!8cT3!!;!W!;kUQs6K(Q<It1's+0Uh
+mK7mWb$ff~>
+!rqu=p>u?QqfDc;s)\/>%<DLLF)q<]ErZ2]ErZ4>F8l4AErZ4<F8l7:F8l4CErZ2]F8c.>F8c.B
+ErZ2]F8c.\ErZ2]!!%(]!!%(]!!%(]!!%(]!!%(]!!%'?!-<5\!!73A!;gg;s6JeI;M"k$s+0=`
+jo`m%s."T~>
+!h?&@p?hoYqu?Zr!<;ut"oeQ&rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'Irr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!!!*'!!!*'!!!*'!!!*$!!<3#u!!`H'!<<'!!;c`]mJp.9s+LE'mage.
+0r1<gJ,~>
+!liB.p?ho\qqh>Q!8dYS"l94Zh>dQThZ!Q_h>dQ4h>dQ4h>dQRhZ!TQhZ!TThZ!R(h>dQ4h>dQ4
+h>dQ4h>dQ4h>dQ4!!(m4!!(m4!!(m4!!(m4!!(jU!<1jT!!_9[!8cQ4!;kUQs6K(Q<It1's+0Uh
+mK7aW`aOA~>
+!quZ5p>u?QqfDc;!-A)="`jYDErZ4>F8l4IErZ2]ErZ2]ErZ4<F8l7;F8l7>F8l4gErZ2]ErZ2]
+ErZ2]ErZ2]ErZ2]!!%(]!!%(]!!%(]!!%(]!!%'?!<.'>!![KE!-<2]!;gg;s6JeI;M"k$s+0=`
+jo`U&p8!3~>
+!i2>Hp?hoYqYpp'rrE*!!<3'!rr<&us8N'+rr<'!rr<'!rr<&ss8N)rs8N)us8N'8rr<'!rr<'!
+rr<'!rr<'!rr<'!!!*'!qZ-ZrrrE*!rr<-#!!*#urr<9'!!*'!!!)lqlg=aNJcCE'JaV+W"$)mI
+.=_~>
+!m8N2p?ho\qVDS[h>lEh!8[_4h>dQThZ!Q_h>dQ4h>dQ4h>dQRhZ!TQhZ!TThZ!Qlh>dQ4h>dQ4
+h>dQ4h>dQ4h>dQ4!!(m4qZ-ZQrrE)Urr<,W!!*#Trr<8[!!(m4!!)oQ!<;BQ!*+UMK`?Vkf'WWg
+`l__?~>
+!rqu=p>u?QqK!#EEr^9&!-8-]ErZ4>F8l4IErZ2]ErZ2]ErZ4<F8l7;F8l7>F8l4VErZ2]ErZ2]
+ErZ2]ErZ2]ErZ2]!!%(]qZ-Y;rrE(?rr<+A!!*">rr<7E!!%(]!!)n;!<;BI!)eCJK`?Vcf&d(Z
+pA^Y5~>
+!h?&@p?hoYqZ$Nps8W&us8W*!rr;uu$NC)+s8N'!s8N'!r;Zcsqu?Zrrr;uu)?0[:s8N'!s8N'!
+s8N'!s8N'!rr<'!rr<&rs8N*!s8N'#rr<&us8N''rr<'!rr<&qs6K(Q;M"k$s+0UhmK52>S1/s~>
+!liB.p?ho\qVM2Os5*_Ts5*bUrndYT$Jka_hVJ54hVJ54r8.GRqqh>QrndYT);Y>nhVJ54hVJ54
+hVJ54hVJ54h>dQ4h>dQQhZ!TUhZ!QWh>dQThZ!Q[h>dQ4h>dQQh>mTAmJp7<s+LE'mage.H-4-8
+J,~>
+!quZ5p>u?QqK)W9s)\/>s)\2?rcA)>$?H1IF)q<]F)q<]r,_l<qfDc;rcA)>)05cXF)q<]F)q<]
+F)q<]F)q<]ErZ2]ErZ4;F8l7?F8l4AErZ4>F8l4EErZ2]ErZ4;Erc7+joA;1s+LE'k18Ys`W,Y-
+J,~>
+!i2>Hp?hoYqZ$Nps8W&us8W&u$i^2,s8N'!s8N'!s8E#qs8N)ts8;p2rr<'!rr<'!rr<'!rr<'!
+rr<'!rW!*$!!*'!rW)lrrrE*!rr<'!rW!<*!!*'!!!*'!!!)lqlg=aNJcCE'JaV+W"$)mI.=_~>
+!m8N2p?ho\qVM2Os5*_Ts5*_T$f1j`hVJ54hVJ54hYmNPhZ!TShYdEfh>dQ4h>dQ4h>dQ4h>dQ4
+h>dQ4rW!)X!!(m4rW)lQrrE)Urr<&UrW!;^!!(m4!!(m4!!)oQ!<;BQ!*+UMK`?Vkf'WWg`l__?~>
+!rqu=p>u?QqK)W9s)\/>s)\/>$Zc:JF)q<]F)q<]F8c1:F8l7=F8Z(PErZ2]ErZ2]ErZ2]ErZ2]
+ErZ2]rW!(B!!%(]rW)k;rrE(?rr<%?rW!:H!!%(]!!%(]!!)n;!<;BI!)eCJK`?Vcf&d(ZpA^Y5~>
+!h?&@p?hoYqZ$Qqrr;uur;Z`rrr;uurr;lrqZ$Ems8W&urr;uus8W*!s8W*!s8Vuss8W*!rVufr
+rr;uu!ri6#rr;rtrr;uus8W*!qZ#mL!)eCJK`Cr;JbJ[.lg=j0Umrla~>
+!liB.p?ho\qVM5PrndYTr8.DQrndYTrndPQqVM)Ls5*_TrndYTs5*bUs5*bUs5*YRs5*bUrSIJQ
+rndYT!o<nWrndVSrndYTs5*bUqq_>Qlg=aQJcCE'qsJ7jmdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdfommdff:mdff:mdff:mdff:mdff:mdff:o'Z):o'Z):o'Z)7
+mK7aW`aOA~>
+!quZ5p>u?QqK)Z:rcA)>r,_i;rcA)>rc@u;qK)N6s)\/>rcA)>s)\2?s)\2?s)\)<s)\2?rH%o;
+rcA)>!cn>ArcA&=rcA)>s)\2?qf;c;lfJ1FJcCE'qrWIto'Yi+"3(<6Ujr~>
+!i2>Hp?hoY^&S*4eGnk&!)eCJK`Co:CA.)hme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6):+nk?tme6)Bme6)Bme6)Bme6)Bme6)BmdBf:p?qYBp?qY>mK5J>Ua^f~>
+!m8N2p?ho\^#&bhe_U<+lg=aQJcCE'qX/+hmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:md;7hmdff:mdff:mdff:mdff:mdff:mdff6o'Z):o'Z):o'5WFIE'E<J,~>
+!rqu=p>u?Q]lX2ReT1`jlfJ1FJcCE'qW;P\k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k2miTk3hC"k3hC"k3hC"k3hC"k3hC"k3hBomcNs"mcNs"mcrp:c1_1-J,~>
+!h?&@p?hoY^&S*4eGnk&!)eCJK`Cr;s7V$Dq#C<dlg=j0Umrla~>
+!liB.p?ho\^#&bhe_U<+lg=aQJcCE'qsFRWme6L.s8;m#qY'@Jmdf]3"*r&/@=S~>
+!quZ5p>u?Q]lX2ReT1`jlfJ1FJcCE'qr[qHrUt^?pAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds8N,ns8DZimd'!;`W,Y-J,~>
+!i2>Hp?hoYNrSG5!)eCJK`Co:s7ZBjs6b-omcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"qrS%Lp@dqJlL"a7S>7Ta~>
+!m8N2p?ho\O59m:lg=aQJcCE'qX4CSs7UpAqXWq6io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io9+[k2PO_k2PO_k2PO_k2PO_k2PO_k2QEt#NFV"k3hg.o'5WFIE'E<J,~>
+!rqu=p>u?QO)k=$lfJ1FJcCE'qW@hG#PRTcp?peoec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+G*ec+D*ec+D*ec+D*ec+D*ec+D*ec+G&eHFakmcNs&jo`m%s."T~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;"SV9Ok4XB+!q,4-rT=+Qlg=j0Umrla~>
+!liB.p?ho\O59m:lg=aQJcCE'qX+RIk2P\&s8W)p@.sHjqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqYDE0qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZk2+\Gg>:iWmdf]3"*r&/@=S~>
+!quZ5p>u?QO)k=$lfJ1FJcCE'qrRnHrn[_=pAb$`!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:KgZ!:Kj[!:Kj[!:Kj[!:Kj[!:Kj["n)*PhUTmLec,"&jo`U&p8!3~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;s5s=;Jc>iPk2+YehWaG13LlloJ,~>
+!m8N2p?ho\O59m:lg=aQJcCE'qsFI@rRq8FrVq?Cs8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)clqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqYKpJf$aNN!:&k;"+A23@=S~>
+!rqu=p>u?QO)k=$lfJ1FJcCE'qr[h,"Rc!`pA]m@#O^Hnc.1(he`l2uc1_1-J,~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;"lAD(e_^"Nrs/Sde^`g=e_]TZ"#6UA.=_~>
+!liB.p?ho\O59m:lg=aQJcCE'qsFX9g=k!+nq$fGp>46GhV-9/lL"b"b/Rk?~>
+!quZ5p>u?QO)k=$lfJ1FJcCE'qrS(,e^_phmeZq`pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpj
+pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpsp?pJUc.1@h
+eaDbc"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;!R9d+eH#;orrN/frm_,-c->D:mK5J>Ua^f~>
+!m8N2p?ho\NrSG5!*+UMK`Cr;#0,BFcI2.WK)Z,Mk0D9#g;_:plg=k'`l__?~>
+!rqu=p>u?QNrSG-!)eCJK`Cr3!PR%_`<PJmp@eO[s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'1Qjs7ZK\hYtIre\/rYlfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;"i]?Kc.265rs8Yme]lY,`P(F"mK52>S1/s~>
+!liB.p?ho\NrSG5!*+UMK`Cr;#JSp?`mX/GqLnkTqY&po`mWST^>eJH"*r&/@=S~>
+!quZ5p>u?QNrSG-!)eCJK`Cr3"glh)^!5^<p3?W2s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKkp'9Hn^!5*7^#&);"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;!OU__blR8+g&M'PrVultk5PD]r;Q`seGfRCmf(H5hR'uQlg=j8
+S>7Ta~>
+!m8N2p?ho\NrSG5!*+UMK`Cr;#I;q'_TM$3p=fBC!<)co!9X+X!;uZn!7goPp@@@g_TLH8]&)c@
+"+A23@=S~>
+!rqu=p>u?QNrSG-!)eCJK`Cr3"f0D^]tN;%mK*%Lrq6E]p?qqR!q,dMrq6E]p?qqR!q,dMrq6E]
+p?qqR%ds&Y!!)`\p?hn\p?qYBrq6E]p?qqR!q,dMrq6E]p?qqR!q,a^rq6E]p&P*c!q,dMrq6E]
+p?qqR!q,dMrq6E]p?qqR!q,dMrq6E]p?qqR"7GmNpAXIbhS$VAc(q_slfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;#HZe,`RX,EpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAY*l!!)`l
+s8N'!pAFpjpAFpjpAFpjpAFq!pAb-ms8VfmrrE*!pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFsj
+p'9a1`Qd8@^#nYK"#6UA.=_~>
+!liB.p?ho\NrSG5!*+UMK`Cr;2PnjE^<5='o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJ!!)T`o(E%`=7Z(Up@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ!:ojSp@84Sp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJo%qO'b0m,thWsS3H-4-8J,~>
+!quZ5p>u?QNrSG-!)eCJK`Cr3$Dbqc[)LS`k4\6:rpBj]me6YJ!qu'UrpBj]me6YJ!qu'UrpBj]
+me6YJ%ef>a!!)H\me-V\me6)BrpBj]me6YJ!qu'UrpBj]me6YJ!qu$^rpBj]mK!7S!qu'UrpBj]
+me6YJ!qu'UrpBj]me6YJ!qu'UrpBj]me6YJ%ef>ame6):e]"o7c(q`'lfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;2OrXC`QdQ5p@eO[s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKd!!*&ms7QEm=9&!opAajdpAajdpAajdpAajdpAajdpAajd!<;cmpAY-mpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAaj[mcMd5`SR,uhWsS33LlloJ,~>
+!m8N2p?ho\NrSG5!*+UMK`Cr;#*mWR^;f$tg%,.CrUTsgk4/KPr:0gfeFEn5hT!:HdZqE#lg=k'
+`l__?~>
+!rqu=p>u?QNrSG-!)eCJK`Cr3#*dBG[(Y#Pg$\k?rU0[ck3`3Lr9aObeF!V)e\/?'c'5TclfJ;o
+pA^Y5~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;"dIQ^^!5Edp'1Tk!;?*dp&P*cr;clkrrE&l!W_rfrW)fg!!)rj
+"p"Aj!;6Bmg%G[5c+VBPPeH5FmK52>S1/s~>
+!liB.p?ho\NrSG5!*+UMK`Cr;#EdHS]#NIhlItY2!:BjTmJuYTrpK^bs6fmerpBgfmdC&SqX+=`
+r9aahmd:)C!!(dAs69jC`k'1<Oh0E8mK7aW`aOA~>
+!quZ5p>u?QNrSG-!)eCJK`Cr33K(ki[(Y#Pk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"!:BjTjoFNDk3hC1!"&)U!!)HLmJu\;rW#=JmcNs"mcFN3mcNs"!9W\LmJm7LmcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNZ^]sPJtMmV@,jo`U&p8!3~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;!JAr%`;ncomX"Tpp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYB!:BjTp&Oddp?hn\p?hn\p?hqKp?hqK!:KO\!:KRKp?qVSp?qYBp&OgS!!)]m!:KRK
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBpAXIbk/G$QhLiMulg=j8S>7Ta~>
+!m8N2p?ho\NrSG5!*+UMK`Cr;#)1LB]#*1`g$01Ml2^,7!9sRLl2UhLl2UhLl2^hK"p!oglKS?L
+qs".]r9=LelKS?Ll2Uh=l3QP+_RdV4Kt?.,mK7mWb$ff~>
+!rqu=p>u?QNrSG-!)eCJK`Cr3$@C%2[(Y#Hk2,7WroO:=k2-+"!oE(rroO:=k2-+"!oE(rroO:=
+k2-+"+Pu8;!9O:<joFNDk2$(<k2lXDk2$+#k2$*p!9WDD!8d_;!oE&>roO^IjoFQ+!!)-]!9WG#
+k2-+"!oE(rroO:=k2-+"!oE(rroO:=k2-+"%c6@)k2,7We\/?'c$QhJlfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;#D:RO^!5F%k5=WIk5=WIk5=WIk5=WIk5=WIk5=WIk5OcU!:BjT
+mJuYTk3`6KmLJ@Zmd:)CjoFfL!:K";!<2Bpk3hX;mdB6*mJu\C!<2Bf!:K"ImJuDImJuDImJuDI
+mJuDImJuDImKr%DhT`aYeUtQtlg=j0Umrla~>
+!liB.p?ho\NrSG5!*+UMK`Cr;7tK+.]#N=\io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_!9O:DiW.s<ioU7'io]5#ioU7'iW.s<!(Q,1joFQ'k2PO_!93/#k2HC#joFQ'joFQ'
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_imu,\`mTFLhWsS3H-4-8J,~>
+!quZ5p>u?QNrSG-!)eCJK`Cr3#CF_/[(X`@e_8je!8[_4h>lC4hVJ82h?a2=h>lEh!8[\Urn[VT
+qq_;Qr8%MUhVJ83h>dQ0h?V<=[(XG*[,1-2"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;"`rP>]uAk-jui(omcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"!9W\L!9W\LmcFN3mcNp;mcFKLmJu\P!'B?2k3hC"!:K";k3`6;joFQ3joFQ3k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2-*V"4_J+hWsS33LlloJ,~>
+!m8N2p?ho\NrSG5!*+UMK`Cr;#'JA2]#*%Tg#<>=io0q<io0stiW/r:#6<cC!!)!Yiqi`QiW&uV
+iWB2?iW/u;!!(d5#i=.L]#)m<]&)c@"+A23@=S~>
+!rqu=p>u?QNrSG-!)eCJK`Cr37;C)S[(X`7hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5!7fp+!7fp+hUMVVhUUH_hUMT+h>lF0!(,5me_\j5!8c8_e_U;_eH".VeH".Ve_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e]ke7[*<?mea)?"c1_1-J,~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;"`r5=^!5EdjpD+Njo>DDjoFQ+!<)$[!<2*a!9O:D!!)cU!!)rZ
+!s%KG!<2*\!8?Q?hT`aYeT8Fdlg=j0Umrla~>
+!liB.p?ho\NrSG5!*+UMK`Cr;7r?\o]#*%ThW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DO!92i8!92i8hVnOphW!AlhW!Alh>lC4!(Pu)ini\Oini\O!8c_lina[liW.upiW.up
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\OhU]QT`mS_8hWsS3H-4-8J,~>
+!quZ5p>u?QNrSG-!)eCJK`Cr37r$#V[(X`@e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5!8c6+!8c6+e_U;_e_\gVe_\gVeH","!(PhqhUUK5hUUK5!7frVhUMVVh>lE_h>lE_
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hT`a8^!1<!hWs;+`W,Y-J,~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;!FjUY`W+eDk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7W!8ci<!8ci<k2$(<k2$(<k2,5#!8ckp!8ckpk2,7Wk2,5#!8ckp!!)0<!8ci<!8ckp
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,8#h?Ls4`SP(;hWsS33LlloJ,~>
+!m8N2p?ho\NrSG5!*+UMK`Cr;#%>rs]"ZbLrn_nRhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?!8?90!8?90hV%r0hV%r0hV-fd!8?;`!8?;`hV-i?hV-fd!8?;`!!(m0!8?90!8?;`
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?rn[q7f"S`4dUB`Dlg=k'`l__?~>
+!rqu=p>u?QNrSG-!)eCJK`Cr3#$T9b['\*&rmc8<e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXh!6s$o!6s$oe]e'oe]e'oe]lVE!6s'=!6s'=e]lXhe]lVE!6s'=!!(Qo!6s$o!6s'=
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhrmh%ns0MpBc!%L)lfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;3F^O`^!5ErhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\W!9W/#hWEYphWE\n!"%fEk2$(<k2,7Wr;[&ahWE\WhWF_9!p8A%r;\M-k2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wc+VBP@_LpimK52>S1/s~>
+!liB.p?ho\NrSG5!*+UMK`Cr;3F1(Q]#)nLg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?!8cGdg>:N`g>:Q^!"%N9hV%r0hV-i?r;[&Yg>:Q?g>;`-!oDYfr;\M)hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-]3_Rdb8?+SnYmK7aW`aOA~>
+!quZ5p>u?QNrSG-!)eCJK`Cr3"^90a[(X`:eGoUHeGoUKeboLHec,XJeboLEebfFHeboL$eHa@4
+[(X^f[,1-2"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!)eCJK`Cr;##a=&`Pp]jIcfMLhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Wh>lEphWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Ws5*dp"O5e$^#&)C"$)mI.=_~>
+!m8N2p?ho\NrSG5!*+UMK`Cr;"]a-n^;A="g&M-(g'?3G^;e`(]&)c@"+A23@=S~>
+!rqu=p>u?QNrSG-!)eCJK`Cr3##`^Z[(X`/Iau]nc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hblH#=c.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hs31b][(X^^[+4L)"3pQ>S:C~>
+!h?&@p?hoYNrSG5!)eCJK`Cr;"]F4-`Qcs4k"":jhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWFS52!+f#hWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\>`RWgC^#nYK"#6UA.=_~>
+!liB.p?ho\NrSG5!*+UMK`Cr;:e]Hc_T($\g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>;T)1u85hg>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:E#_Tp_+]&)c@"*r&/@=S~>
+!quZ5p>u?QNrSG-!)eCJK`Cr3"\R%Y]tM\!ebB+FeH"1N#L0rh`Q_#^hWs;+`W,Y-J,~>
+!i2>Hp?hoYNrSG5JcCB&qsFbVhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9k5='9k5='9k5='9
+k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='Bk2+t>c.1Z:
+^#&)C"$)mI.=_~>
+!m8N2p?ho\NrSG5JcCB&qsF\Wf$;:Pdb<Q2g'QWif#l"Xg-iO/lg=k'`l__?~>
+!rqu=p>u?QNrSG-JcCB&qrS)Kc,IB0c-:^fc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.2j=s1JQSeNpRmlfJ;opA^Y5~>
+!h?&@p?hoYNrO[uJaV^h#?oC/c.1A$hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9
+hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYQ@>hUU05bu27;lg=j0
+Umrla~>
+!liB.p?ho\NrO[uJaV^h#?Aptb0&/dg4.u5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-iCinFFX"P1^h]&)c@"*r&/@=S~>
+!quZ5p>u?QNrO[mJ`c.X"]E=a`Pp)QeHk$Vc,IrH9!mI@jo`U&p8!3~>
+!i2>Hp?hoYNrO[uJaV^h#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYlR:hYuX;hYuX;hYuX;hYuX;hYuX;hYuX<mcON*"0>tFk3MF;3LlloJ,~>
+!m8N2p?ho\NrO[uJaV^h#B?ctda$.hgA]rTg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hW!N#k2+\;g9+_mhWsS3IE'E<J,~>
+!rqu=p>u?QNrO[mJ`c.X#BQ]kc,IZHc%X^Ih?VTUc./Un[,1-2"3pQ>S:C~>
+!h?&@p?hoYNrO[uJaV^h!khLVrn[_,hVNtK$1@NTk2t2lMoFQ=mK52>S1/s~>
+!liB.p?ho\NrO[uJaV^h#eE^Pf%/9tf%Pi7$0(C8hVQOOKtcF0mK7aW`aOA~>
+!quZ5p>u?QNrO[mJ`c.X!jkS=rlkM`c-:sm$/Xh$e^_W2K>#h$jo`U&p8!3~>
+!i2>Hp?hoYNrO[uJaV^h#53sIXOZ1irn_n^hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WroOIRk2*I;C:)7NmK5J>Ua^f~>
+!m8N2p?ho\NrO[uJaV^h#P*jBV9[ZGeqMfXhYuL=euhPXZHD=qmK7mWb$ff~>
+!rqu=p>u?QNrO[mJ`c.XC[R*QUrCU/c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(heJ?E[c.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@lK/2npA^Y5~>
+!h?&@p?hoYNrO[uJaV[g#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r@.b$"B'lZ^#&&B"#6UA.=_~>
+!liB.p?ho\NrO[uJaV[gC@\fE1b:%+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbp+tP,n-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&Xlg=k#b/Rk?~>
+!quZ5p>u?QNrO[mJ`c+W"7EO*0nCeQ.0VG(K<2c:lK/2fs7W7=~>
+!i2>Hp?hoYNrO[uJaV^hrq6H^k0:kr^&G\J`QdQ5p?V,K3LlloJ,~>
+!m8N2p?ho\NrO[uJaV^h#4h3QlJB\#J\(il"N&=<lLO9/"+A23@=S~>
+!rqu=p>u?QNrO[mJ`c.XrpG9uhSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJd[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(WjH]a;'Z[(Wi[`STbFlfJ;opA^Y5~>
+!h?&@p?hoYNrO[uJaV[gCA.)hmdArohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\O+m.YDhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOk2,7WmdBf6mK52>S1/s~>
+!liB.p?ho\NrO[uJaV[g"S2!KlK3ZSr8%J:lKR^=H-4-8J,~>
+!quZ5p>u?QNrO[mJ`c+WC@:6Pk2t4Ne_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j,+l:c+e_\j5e_\j5e_\j5e_\j5e_\j5e^`O,hUUK5k2u*sjo`U&p8!3~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrRl%quHKZ!!)*J!!)oaquH]`!!)`\!!%T<JaTi3"$)mI.=_~>
+!m8N2p?ho\NrRl%quHKZ!!)*J!!)oaquH]`!!)`\!!%T<JaTi3"+A23@=S~>
+!rqu=p>u?QNrRkrquHKR!!)*B!!)oYquH]X!!)`T!!%T4J`a9#"3pQ>S:C~>
+!h?&@p?hoYNrRo&!!)TX!!)*J!!)oa!!*#drr@W<JaT9#"#6UA.=_~>
+!liB.p?ho\NrRo&!!)TX!!)*J!!)oa!!*#drr@W<JaT9#"*r&/@=S~>
+!quZ5p>u?QNrRns!!)TP!!)*B!!)oY!!*#\rr@W4J``]h"3(<6Ujr~>
+!i2>Hp?hoYNrRo&!!)TX!!)TX!!)ZZ!!)oa!!)ucrrDc\!!%T<JaT`0"$)mI.=_~>
+!m8N2p?ho\NrRo&!!)TX!!)TX!!)ZZ!!)oa!!)ucrrDc\!!%T<JaT`0"+A23@=S~>
+!rqu=p>u?QNrRns!!)TP!!)TP!!)ZR!!)oY!!)u[rrDcT!!%T4J`a/u"3pQ>S:C~>
+!h?&@p?hoYNrRo&rrDl_rW)rc!!*#drW)obq>gQ`rW)obr;c`_!!)rb!s%cW!<2E_!!2KfrpK^b
+rpBdemf!4dmem.bmK!=UrW)rc!!%T<JaV"T"#6UA.=_~>
+!liB.p?ho\NrRo&rrDl_rW)rc!!*#drW)obq>gQ`rW)obr;c`_!!)rb!s%cW!<2E_!!2KfrpK^b
+rpBdemf!4dmem.bmK!=UrW)rc!!%T<JaV"T"*r&/@=S~>
+!quZ5p>u?QNrRnsrrDlWrW)r[!!*#\rW)oZq>gQXrW)oZr;c`W!!)rZ!s%KG!<2-W!!23^roX.Z
+roO4]k5GA\k5>;ZjoGJErW)r[!!%T4J`bGD"3(<6Ujr~>
+!i2>Hp?hoYNrRl%rW)la&ch@f!!)HT!:K7Tmd:&Tmd:&TrU(-qmd:)CmJm7TmJm7TmK!.P!!)rb
+#6=2[!:K7T!<)<u!:K7Tmd:&Tmd:&Tmd:&Tmd:)PmKWa[mJm7TmK!7S!!%T<q!N_,o(MD;"$)mI
+.=_~>
+!m8N2p?ho\NrRl%rW)la&ch@f!!)HT!:K7Tmd:&Tmd:&TrU(-qmd:)CmJm7TmJm7TmK!.P!!)rb
+#6=2[!:K7T!<)<u!:K7Tmd:&Tmd:&Tmd:&Tmd:)PmKWa[mJm7TmK!7S!!%T<q!Mqgmdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdfommdff:mdff:mdff:mdff:mdff:
+mdff:o'Z):o'Z):o'Z)7mK7mWb$ff~>
+!rqu=p>u?QNrRkrrW)lY&ch(V!!)0D!9WDDk2lXDk2lXDrT4Rik2l[+jo>DDjo>DDjoG;@!!)rZ
+#6<oK!9WDD!<)$m!9WDDk2lXDk2lXDk2lXDk2l[@jp(nKjo>DDjoGDC!!%T4pu[.qo'Yi+"3pQ>
+S:C~>
+!h?&@p?hoYNrSG5q,6tTrW)udrrE&d"p")Z!:BgerpBjgmd:)QmK3IW!!*#d!s%cW!<2Bd!;l0a
+!;u6h!:K7Tmd:)QmKN[ZmJu\C!<)<f!:K7TrpBadqsFOdmd:)SmK3IWmK!(NL/J$OqX/+lme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bmd;7lme6)Bme6)Bme6)Bme6)B
+me6)Bme6):p?qYBp?qYBp?M&J0r1<gJ,~>
+!liB.p?ho\NrSG5q,R1WrW)udrrE&d"p")Z!:BgerpBjgmd:)QmK3IW!!*#d!s%cW!<2Bd!;l0a
+!;u6h!:K7Tmd:)QmKN[ZmJu\C!<)<f!:K7TrpBadqsFOdmd:)SmK3IWmK!(NL/e6RqX/+hmdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:md;7hmdff:mdff:mdff:mdff:
+mdff:mdff6o'Z):o'Z):o'5WFH-4-8J,~>
+!quZ5p>u?QNrSG-q,6tLrW)u\rrE&\"p!fJ!9O7]roO:_k2l[AjoYVG!!*#\!s%KG!<2*\!;kmY
+!;ts`!9WDDk2l[AjothJjoFQ+!<)$^!9WDDroO1\qrRt\k2l[CjoYVGjoG5>L/J$OqW;P\k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2miTk3hC"k3hC"k3hC"k3hC"
+k3hC"k3hBomcNs"mcNs"mcrp:`W,Y-J,~>
+!i2>Hp?hoYNrSG5!)i[np$Vh[!:K^as6]mfme["amJm7bmK!=UqZ-Za!!*#d!!)oa!!)rb"p")Z
+!:K7Tr9aahmd:)CmK!4R!s%cW!<2Bd!<2Eb!<;He!<2Ed!!2Kfq<j%<!E/spmf3!3s7lWmp?V,K
+3LlloJ,~>
+!m8N2p?ho\NrSG5!*/mqp$Vh[!:K^as6]mfme["amJm7bmK!=UqZ-Za!!*#d!!)oa!!)rb"p")Z
+!:K7Tr9aahmd:)CmK!4R!s%cW!<2Bd!<2Eb!<;He!<2Ed!!2Kfq<j%<!EK0smK<%JpA0@?r;Qrs
+p?qM>o'>]GIE'E<J,~>
+!rqu=p>u?QNrSG-!)i[np#c8S!9X.Ys5j=^k5,/Yjo>DZjoGJEqZ-ZY!!*#\!!)oY!!)rZ"p!fJ
+!9WDDr8n1`k2l[+joGAB!s%KG!<2*\!<2-Z!<;0]!<2-\!!23^q<!J4!E/spk5XlJp4!&8s7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmpAajdpAajdpAajdpAajdpAajdpAajd
+rrMinrV$3XlfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!E/scmK3IW!!)oa!s%`h!;l0a!;u6e!:BgeqsFFarpBadqsFFarU0[cs6]sh
+md:)QmKN[ZmJu\C!<)<f!:K7TrpBjgmd:)SmK3IWmK!4RrW%N;s6]ncs8)0`pAFsjmWdm^k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBomcNs"mcNs"mcNs"mcNs"mcNs"mcNs7jok,G
+p?qY>mK52>S1/s~>
+!liB.p?ho\NrSG5!EK0fmK3IW!!)oa!s%`h!;l0a!;u6e!:BgeqsFFarpBadqsFFarU0[cs6]sh
+md:)QmKN[ZmJu\C!<)<f!:K7TrpBjgmd:)SmK3IWmK!4RrW%N;s6]nfs8)0`o)JE4s8)<Ok2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PC_io]7_io]7_io]7_io]7_io]7_io]8#
+h?W&sio]\"mdfZ2"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/scjoYVG!!)oY!s%H`!;kmY!;ts]!9O7]qrRkYroO1\qrRkYrT=+[s5jC`
+k2l[AjothJjoFQ+!<)$^!9WDDroO:_k2l[CjoYVGjoGABrW%N3s5j>[s8(mXmK`IRs7Ym;hUVV^
+!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*
+!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*s4.,*!7h)*!7h)*!7h)*!7h)*!7h)*qpbi+
+k3hC"lK/2fs7W7=~>
+!i2>Hp?hoYNrSG5!E/simJm7cmf*:emJm7amK3IWmK!.PrrE#c!s%cW!;l0e!:K7T!;l0a!<2Ed
+!<2Bh!:K7T!<)<q!:K7Tmd:&Tmd:&Tmd:)SmK3IWmK!7S!s%cW!<)?c!.jS;mK$5cqsFU\mdB62
+Jc>f>k2-(!rq>[G"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK0lmJm7cmf*:emJm7amK3IWmK!.PrrE#c!s%cW!;l0e!:K7T!;l0a!<2Ed
+!<2Bh!:K7T!<)<q!:K7Tmd:&Tmd:&Tmd:)SmK3IWmK!7S!s%cW!<)?c!.jS;mK$>fqX+RIk2P\&
+s8W)p@.sHjqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqYDE0qY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZk2+\Gg>:iWmdf]3"+A23@=S~>
+!rqu=p>u?QNrSG-!E/sijo>D[k5PG]jo>DYjoYVGjoG;@rrE#[!s%KG!;km]!9WDD!;kmY!<2-\
+!<2*`!9WDD!<)$i!9WDDk2lXDk2lXDk2l[CjoYVGjoGDC!s%KG!<)'[!.j;3joJB[qrRnHrn[_=
+pAb$`!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:KgZ!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+"n)*PhUTmLec,"&jo`m%s."T~>
+!h?&@p?hoYNrSG5!E/sime["_mem.cmJm7dmem.bmem+gmJm7Tmem.bmf*7fmK!.PquH]`!!*#d
+r;Zug!!)EerpK^brpBadrpBgfmdBrP!U]sdmf*9<mf)VT;ZHX^s5s=;Jc>iPk2+YehWaG10r1<g
+J,~>
+!liB.p?ho\NrSG5!EK0lme["_mem.cmJm7dmem.bmem+gmJm7Tmem.bmf*7fmK!.PquH]`!!*#d
+r;Zug!!)EerpK^brpBadrpBgfmdBrP!U]sdmf*9<mf)VT<WDsa!8d\.!;?BkIes*@s8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)TlqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$Egp?'rSrRq8:
+lL"b"b/Rk?~>
+!quZ5p>u?QNrSG-!E/sik5,/Wk5>;[jo>D\k5>;Zk5>8_jo>DDk5>;Zk5PD^joG;@quH]X!!*#\
+r;Zu_!!)-]roX.ZroO1\roO7^k2uO@!TjC\k5PF4k5OKD;ZHXVr7(r<pAajdL@tl?hTa<qc.1A/
+jo`U&p8!3~>
+!i2>Hp?hoYNrSG5!E/rVmJm6<meuPS;ZHX^"lAD(e_^"Nrs/Sde^`g=e_]TZ"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK/YmJm6<meuPS<WDsa"k),Ydamu?rs/8SdaI"+cJ%RO"+A23@=S~>
+!rqu=p>u?QNrSG-!E/rVjo>C4k5FEC;ZHXV"jPTJc->\QrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrsADe
+e]l@he]lY4lfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!E/sjme?dUmJm6<meuPS;ZHX^!R9d+eH#;orrN/frm_,-c->D:mK52>S1/s~>
+!liB.p?ho\NrSG5!EK0mme?dUmJm6<meuPS<WDsa#0,BFcI2.WK)Z,Mk0D9#g;_:plg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/sjk4eqMjo>C4k5FEC;ZHXV!PR%_`<PJmp@eO[s8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'1Qjs7ZK\hYtIre\/rYlfJ;g
+s7W7=~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZHX^"i]?Kc.265rs8Yme]lY,`P(F"mK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK/NmYC32<WDsa#JSp?`mX/GqLnkTqY&po`mWST^>eJH"+A23@=S~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZHXV"glh)^!5^<p3?W2s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKkp'9Hn^!5*7^#&);"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZHX^!OU__blR8+irB#YrVultk5Y>Zao;D8mf(H5hR'uQlg=j0
+Umrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<WDsa#I;q'_TM$3p>c#L!<)co!9X.U!6Y-Ep@@@g_TLH8]&)c@
+"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZHXV"f0D^]tN;%mK*%Lrq6E]p?qqR!q,dMrq6E]p?qqR!q,dM
+rq??l!:Kj[rr<&erq6E]p?qqR!q,dMrq6E]p?qqR"Rc!Op@eCas7QN^p?qqR!q,dMrq6E]p?qqR
+!q,dMrq6E]p?qqR!q,dMrq6E]p?qqR!q,dMrq6H^p?qYRmK_U^]uA6l[+4L)"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZHX^#HZe,`RX,EpAFpjpAFpjpAFpjpAFpjpAFplp&G*lrrVlo
+!<2uupAFpjpAFpjpAFpjpAFpj!<3#u!!)`jrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+s8Vctk1.GqhQ4EQlg=j8S>7Ta~>
+!m8N2p?ho\NrSG5!EK/NmYC32<WDsa:8QC]^<5='o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MVS!;?!Wnc/[`o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(E(Wo(E%`5P"O=p@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJo%qO'b0m,thWsS3IE'E<J,~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZHXV$Dbqc[)LS`k4\6:rpBj]me6YJ!qu'UrpBj]me6YJ!qu'U
+rpKdd!;?E[rr<&mrpBj]me6YJ!qu'UrpBj]me6YJ%ef>amd:)Kme-V\me6)BrpBj]me6YJ!qu'U
+rpBj]me6YJ!qu'UrpBj]me6YJ!qu'UrpBj]me6YJ%ef>ame6):e]"o7c(q`'lfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZHX^:Rp:\`QdQ5p@eO[s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZHm!;?Hdrr<&ms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7QHds7ZHm!'^,VpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAaj[mcMd5`SR,uhWsS30r1<gJ,~>
+!liB.p?ho\NrSG5!EK/NmYC32<WDsa#*mWR^;f$tiq!*LrUTsgk4/KPrUTsgbOPr,hT!:HdZqE#
+lg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZHXV#*dBG[(Y#PipQgHrU0[ck3`3LrU0[cbO,Yue\/?'c'5Tc
+lfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZHX^"dIQ^^!5Emp'1Tk!;?*dp&P*cr;clkrrE&l!W_rfrW)fg
+!!)rj!!*#lr;clk!!*#l!!*#l!s&#ppAP'Op'9a)^!5)l^#nYK"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK/NmYC32<WDsa#EdHS]#NIhlJq:;!:BjTmJuYTrpK^bs6fmerpBgfmdC&S
+qX+=`r9aObrpK^bs6]jerpBadrpBjgmJu\S!9ESJl3H%_]#N0\]&)c@"+A23@=S~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZHXV0T3o`[(Y#Pk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3h@3joFQ3!:BjTk3i0J$0LXU!9W_3!9W_K!"eS\mcNs"mJu\;mcNp;mcNs9!"J)Y!:K";!:K";
+!:BjTrW";5k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2t4-[(X_B[,1-2"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZHX^!JAr%`;ncomX"Tpp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qVSp&OgS!:BjTp&G*\p&G*\p&OgSp&Oddp?hn\p?qYBp?hqKp?qYB!:KO\!:KO\!:Bgep?hn\
+p?hqK!!)`\!:KRKp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBpAXIbk/G$QhLiMulg=j0Umrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<WDsa#)1LB]#*1`ip%-Vl2^,7!9sRLl2UhLl2UhLl2^hK"p!og
+lKS?Lqs".]r9>+!lKS?LlKS?Ll2UhLl2UhLl2^)L!:&hLj6?p4g;:G<dY59hlg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZHXV$@C%2[(Y#Hk2,7WroO:=k2-+"!oE(rroO:=k2-+"!oE(r
+roQTKjoFQ+!8[_4jo>D<jo>DDjoFQ#joFNDk2$(<k2,7Wk2l[#k2,7_!8ci<!9WDD!8[\Uk2$(<
+k2l[#!!)0D!8ckproO:=k2-+"!oE(rroO:=k2-+"%c6@)k2,7We\/?'c$QhJlfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZHX^#D:RO^!5F%k5=WIk5=WIk5=WIk5=WIk5=WUjoFfLmd:)C
+!:K7Tk5OcT!:JtLmd:)C!!*#d!<D9[mJm7bmM#ZhmJu\Ck3`6;mJuALmJuYTk3`6KmJm7bmJuDI
+mJuDImJuDImJuDImKr%DhT`aYeUtQtlg=j8S>7Ta~>
+!m8N2p?ho\NrSG5!EK/NmYC32<WDsa5(V/%]#N=\io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]5#iW/!#!9O:DiW/!#ioU7'iW/!#!9O7]:ZCNr!93/#k2PM'k2PO_joFQ'!93/#joFQ'!9+"<
+!9+"<joFQ'joFQ'k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_imu,\`mTFLhWsS3IE'E<J,~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZHXV#CF_/[(X`@e`5Kn!8[_4h>lC4hVJ82h?a2=h>lEh!8[\U
+rn[VTqq_;Qr8%MUhVJ82h@'D@h>lC4h>lC4hVJ83h>dQ8h?V<=[(XG*[,1-2"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/s,mX\9j;?5kSmK$5cqsFW/hSm1IhYuXnmcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mJu\;!!)HL!9W\LmcNs"!9W\L!9O:DqZ'%Pk3hC"joFQ3k3h@3k3`6;k3h@3k3`6;
+!:BjT!:JtLk3h@3k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBgrl"uiF1pGrmK52>S1/s~>
+!liB.p?ho\NrSG5!EK0/mX\Bm<<21VmK$>fqsFZ2d_`T4f&#EG$39)F!!)$<!92u<rSe%^io0q<
+iW/!8!;kaU!;tgY!92u<rSe4cio0st!9+"<!92u<ro*nXj5L@$f###8dWN.Xlg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/s,k(-Fb;YT;S;ZHXV4DN-J[(X`7hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUH_hUMT+hUMVVh>lE_hUMVVh>dQ+!7grH9A\4Ue_\gVe_\j5eH".V!8c8_eH".V!8[_4
+!8[_4eH".VeH".Ve_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e]ke7[*<?mea)?"`W,Y-J,~>
+!i2>Hp?hoYNrSG5!E/s,mJp.9s4mVSk4n?F;ZHX^"`r5=^!5EmjpD+Njo>DDjoFQ+!<)$[!<2*a
+!9O:D!!)cU!!)u[rrE)]!!)u[$ioGP!9O:D!9O:DjoGDC!!)$@#N!_=c.-mKk3MF;3LlloJ,~>
+!m8N2p?ho\NrSG5!EK0/mJp7<s4mVSk4n?F<WDsa:MnP"]#*%ThW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!AlhVnM8hVnOph>lElhVnOphVnOp!9*tYhW!DOhW!DOhVnOphW!Al!']E!!8c_l
+iW.up!8[_4!8[_4iW.upiW.upini\Oini\Oini\Oini\Oini\Oini\Oini\OhU]QT`mS_8hWsS3
+IE'E<J,~>
+!rqu=p>u?QNrSG-!E/s,joA;1s4mYKjoJB[qrU[h`P&Xlc/."-e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5eH".V!!(R+!8c6+e_\j5!8c8_!8[_4!!(R+e_\j5e_\j5!8c8_eGoS5hUMVVhUUH_
+hUMVV!7_)"!7fp+hUUH_hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK-]r\olC:)j`jo`m%
+s."T~>
+!h?&@p?hoYNrSG5!E/s,mJp.9s4mVSk4n?F;ZHX^!FjUY`W+eDk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,5#k2$(<k2$*pjo>D<jo>D<k2$(<k2,5#k2,7Wk2,7Wk2$*pk2$(<k2,5#!8ci<
+!8ci<!8ckp!!)0<!8ckp!8ckpk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,8#h?Ls4`SP(;hWsS3
+0r1<gJ,~>
+!liB.p?ho\NrSG5!EK0/mJp7<s4mVSk4n?F<WDsa#%>rs]"ZbLrn_nRhV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-fdhV%r0hV%t`h>dQ0h>dQ0hV%r0hV-fdhV-i?hV-i?hV%t`hV%r0hV-fd!8?90
+!8?90!8?;`!!(m0!8?;`!8?;`hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?rn[q7f"S`4dUB`Dlg=k#
+b/Rk?~>
+!quZ5p>u?QNrSG-!E/s,joA;1s4mYKjoJB[qrS)dc+UKkc-?7<Gg4d`e]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXheH".E!!(Qo!6s$o!6s$o!6s'=!!(QoeH".Ee]lXhe]lXh!6s'=!!(QoeGoToeGoTo
+eGoToe]e'oe]e*=e]e*=e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]n*Ds3:SN"MN&`[+4L)"3(<6
+Ujr~>
+!i2>Hp?hoYNrSG5!E/s,mJp/<rr<%QrrD3VmK$5cqsH.Ie]kePhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\Wh>lEphWE\W!9W/#r;[/\k2,5#!8ckpk5>8`hWE\WhWF_9"QnS'hWFb:2r<]R
+joFQ#joFQ#joFQ#joFQ#k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2+@rc.-::k3MF;3Lllo
+J,~>
+!m8N2p?ho\NrSG5!EK0/mJp8?rr<%QrrD3VmK$>fqsH.Dd`/l8db<F3g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g&Tj`g>:Q?!8cGdr;[/XhV-fd!8?;`hYdEXg>:Q?g>;`-"Q%khg>;c.2qm-B
+h>lEdh>lEdh>lEdh>lEdhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?g=!jL`mS/(hWsS3IE'E<
+J,~>
+!rqu=p>u?QNrSG-!E/s,joA<4rr<%Qs7bXV;ZHXV"^90a[(X`CeGoUHeGoUKeboLHec,XJeboLF
+ebfFFeboLHeGoUKeGoUKeGoUKeGoU/eHa@4[(X^f[,1-2"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/s,mJp/<rr<%QrrD3VmK$5cqsFYdhTa$YhVN_DhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWFjps2>,chGV&D
+lg=j0Umrla~>
+!liB.p?ho\NrSG5!EK0/mJp8?rr<%QrrD3VmK$>fqsFVff#GG@dXg*Xg=F-T`n"/$hWsS3H-4-8
+J,~>
+!quZ5p>u?QNrSG-!E/s,joA<4rr<%Qs7bXV;ZHXV##`^Z[(X`/Iau]nc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hs31b][(X^^[+4L)
+"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!E/slmf*:cmJm7.mJp/<rr<%QrrD3VmK$5cqsFVchUTTiec+\MhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WpAeRWk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wc,J5i;SD5Y
+mK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK0omf*:cmJm7.mJp8?rr<%QrrD3VmK$>fqsG_'f$;.Pdb`^7g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?pAeRShV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i;`kp$P9Y0*H
+mK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/slk5PG[jo>D&joA<4rr<%Qs7bXV;ZHXV"\R%Y]tM\Meb9'CeHa@4[)L9^
+[,1-2"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/slmf*:cmJm7.mK-;ds82ljs8E#irr<&trr<%QrrD3VmK$5cqsFbVhUTli
+hVRDOk5O3;k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9
+k5='9k5='9k5='9k5='9k5='9k5='9k5='Bk2+t>c.1Z:^#&)C"#6UA.=_~>
+!liB.p?ho\NrSG5!EK0omf*:cmJm7.mK-Dgs82ljs8E#irr<&trr<%QrrD3VmK$>fqsF\Wf$;:P
+db<Q2g'QWif#l"Xg-iO/lg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/slk5PG[jo>D&joSH\s82ljs8E#irr<&trr<%Qs7bXV;ZHXV#!pMQ]tM\8
+Iau]nc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hs3:SW"NAnW[+4L)"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!E/slmf!4cmJm7.mK6AerrE&urrDfn!!)Qh!!)ut!!%`Q!9X(E!E/spmKZq?
+hTaU$hVS1m!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9
+!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dS7#N""]hT\s3k3MF;3LlloJ,~>
+!m8N2p?ho\NrSG5!EK0omf!4cmJm7.mK6JhrrE&urrDfn!!)Qh!!)ut!!%`Q!9X(E!EK0smKZb7
+f#l.`g=h&5g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?hW!8hc32_@9Y0*HmK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/slk5GA[jo>D&jo\N]rrE&urrDfn!!)Qh!!)ut!!%`QpZ;KSs81p^;T6o"
+`Q`ta#i<hN`Qc@o[,1-2"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/slmK*CV!<2Bf!:K:R!<2Be!:Kgd!:KgdrpKacrpBadjR*+Js8N)ts8N)o
+rr<&hrriE&rrE'!L&V/8q!J/\s823hF0+6Te^`O5r8n"9roO4;roO4;roO4;roO4;roO4;roO4;
+roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;
+roO4;roO4;rT4+:roO4;roO4;roO4;roO4;roO4;roO7Lk5O3>XCAm*lg=j0Umrla~>
+!liB.p?ho\NrSG5!EK0omK*CV!<2Bf!:K:R!<2Be!:Kgd!:KgdrpKacrpBadjR*+Ms8N)ts8N)o
+rr<&hrriE&rrE'!L&V/8q!J/_s823hEN7a@cHb"prn_tThV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-iCg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?io17+hU^-/Y$JWqlg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/sljoPPF!<2*^!9WGB!<2*]!9X7\!9X7\roX1[roO1\jQ6PBs8N)ts8N)o
+rr<&hrriE&rrE'!L&^o0!E/spjp,t'e]l(Pc-:smrn[n1c-=e7>.!/Pjo`U&p8!3~>
+!i2>Hp?hoYNrSG5!E/slmKN[Z!!)HT!;l0s!:K7T!:K7T!:K7Tmd:)CmJm7GmK6AerrDus!!*#u
+rW)uurVurur;cis!!*#u"9AK%!<;utL&V/8q!J/\s823c]i*,Sh?)6ahM((ume6)2k1*@f`STqK
+"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK0omKN[Z!!)HT!;l0s!:K7T!:K7T!:K7Tmd:)CmJm7GmK6JhrrDus!!*#u
+rW)uurVurur;cis!!*#u"9AK%!<;utL&V/8q!J/_s823i\kL8tf$`!tg4eAiipPschTefK^>A2D
+"+A23@=S~>
+!rqu=p>u?QNrSG-!E/sljothJ!!)0D!;kmk!9WDD!9WDD!9WDDk2l[+jo>D?jo\N]rrDus!!*#u
+rW)uurVurur;cis!!*#u"9AK%!<;utL&^o0!E/spjoVn^`W"*``QcY]eHt*phUU/q8qXh-lfJ;o
+pA^Y5~>
+!h?&@p?hoYNrSG5!E/slmKN[ZmJu\C!;l0d!:K7TrpBadrpBjgmJm7dmJm7GmK6AerrDus$3:,+
+!<<'!!<<'!qu6`us8N)urs/W)rrE*!!<3%QrrD3VmK$5cqsF[^Mb:)$hWFgoGimlFhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEtWk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2-+"#O^a2Zq>)?
+c0F^!0r1<gJ,~>
+!liB.p?ho\NrSG5!EK0omKN[ZmJu\C!;l0d!:K7TrpBadrpBjgmJm7dmJm7GmK6JhrrDus$3:,+
+!<<'!!<<'!qu6`us8N)urs/W)rrE*!!<3%QrrD3VmK$>fqsF^[NC9Vgf%S]/g&U"/iWdu:885BP
+k3MF;H-4-8J,~>
+!quZ5p>u?QNrSG-!E/sljothJjoFQ+!;km\!9WDDroO1\roO:_jo>D\jo>D?jo\N]rrDus$3:,+
+!<<'!!<<'!qu6`us8N)urs/W)rrE*!!<3%Qs7bXV;ZHXVC[R*QUrCU/c.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(heJ?E[c.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@
+lK/2fs7W7=~>
+!i2>Hp?hoYNrSG5!E/slmJm7dmK*CV!<2Eb!<;He!<2Bd!<2Be!:K^aiU-eGs8N)srrW9$!!*#u
+!s&B$!;lcu!<<'!rr36(s8N*!rrE'!L&V/8q!J/\s8)-fp:Y2q.4I"L.0)+%.0)+%.0)+%.0)+%
+.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%
+.0)+%.0)+%.0)+%.0)+%.0)+$.0)+%.0)+%.0)+%.0)+%.0)+%.0)+$.K;+*;M2?ihWjM23Lllo
+J,~>
+!m8N2p?ho\NrSG5!EK0omJm7dmK*CV!<2Eb!<;He!<2Bd!<2Be!:K^aiU-eJs8N)srrW9$!!*#u
+!s&B$!;lcu!<<'!rr36(s8N*!rrE'!L&V/8q!J/_s8).uo!W*d/1<%t/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1;nj/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t-nHbt1f]78^=ql<
+mK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/sljo>D\joPPF!<2-Z!<;0]!<2*\!<2*]!9X.YiT:5?s8N)srrW9$!!*#u
+!s&B$!;lcu!<<'!rr36(s8N*!rrE'!L&^o0!E/sojob%Y@PNE_r[A"*;M2'ae`u9!c1_1-J,~>
+!h?&@p?hoYNrSG5!E/slmJm7dmf!4dmJm7dmK3IWmK!7S!!*#d!s%`h!8[&F;ZHasr;Qcts8)fr
+rr<&us8;rtrr<&urs/W)rrE*!!<3%QrrD3VmK$5cqsOIW"7G<r`IY`%]`c=!k3hs/mK52>S1/s~>
+!liB.p?ho\NrSG5!EK0omJm7dmf!4dmJm7dmK3IWmK!7S!!*#d!s%`h!8[&F<WE(!r;Qcts8)fr
+rr<&us8;rtrr<&urs/W)rrE*!!<3%QrrD3VmK$>fqsF[ZmdfZ"b//_@rji6Lb22FSlg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/sljo>D\k5GA\jo>D\joYVGjoGDC!!*#\!s%H`!8Zc>;ZHasr;Qcts8)fr
+rr<&us8;rtrr<&urs/W)rrE*!!<3%Qs7bXV;ZHXVrpG9uhSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJd[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(WjH]a;'Z[(Wi[`STbFlfJ;g
+s7W7=~>
+!i2>Hp?hoYNrSG5!E/slmJm7cmf*:emJm7dmK3IWmK!7S!!*#d!s%cW!8[&F;ZHasrVult!ri6#
+qu6`us8N)urrW9$rrE&u#QXo)!<<'!rr@cQ!9X(E!E/somV;I`p?qA*k2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WhBD%<k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2+tWhWE\WhX9h*
+lL"a7S>7Ta~>
+!m8N2p?ho\NrSG5!EK0omJm7cmf*:emJm7dmK3IWmK!7S!!*#d!s%cW!8[&F<WE(!rVult!ri6#
+qu6`us8N)urrW9$rrE&u#QXo)!<<'!rr@cQ!9X(E!EK0rmKE+KmcrqchYc42k3D4!"+A23@=S~>
+!rqu=p>u?QNrSG-!E/sljo>D[k5PG]jo>D\joYVGjoGDC!!*#\!s%KG!8Zc>;ZHasrVult!ri6#
+qu6`us8N)urrW9$rrE&u#QXo)!<<'!rr@cQpZ;KSs8(kmmcNs"k1/>=hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUU."hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5e_\j5e_\j=k3hNs
+"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/slmJm7cmf*:emeZtbmK!7S!!*#d!!*#dr;clc!!)*J"&f1!!<3#u!<2uu
+!;lcu!<<'!rr3K/s8N*!rr<'!rrE*!!<3%QrrD3VmK$5cJaV+W"#6UA.=_~>
+!liB.p?ho\NrSG5!EK0omJm7cmf*:emeZtbmK!7S!!*#d!!*#dr;clc!!)*J"',C$!<3#u!<2uu
+!;lcu!<<'!rr3K/s8N*!rr<'!rrE*!!<3%QrrD3VmK$>fJaV+W"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/sljo>D[k5PG]k5,,ZjoGDC!!*#\!!*#\r;cl[!!)*B"&f1!!<3#u!<2uu
+!;lcu!<<'!rr3K/s8N*!rr<'!rrE*!!<3%Qs7bXV;ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/s,mK-;ds82lps8;rtrrN3#s8)crs8E!&rrE*!!<<)u!/:FQk4n?F;ZD=9
+f'WW#S>7Ta~>
+!m8N2p?ho\NrSG5!EK0/mK-Dgs82lps8;rtrrN3#s8)crs8E!&rrE*!!<<)u!/:FQk4n?F<W@X<
+f'WWg`l__?~>
+!rqu=p>u?QNrSG-!E/s,joSH\s82lps8;rtrrN3#s8)crs8E!&rrE*!!<<)u!/:IIjoJB[J`bPG
+"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/smme?e(mJp/<rr<%QrrD3VmK$5cJaV+W"#6UA.=_~>
+!liB.p?ho\NrSG5!EK0pme?e(mJp8?rr<%QrrD3VmK$>fJaV+W"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/smk4equjoA<4rr<%Qs7bXV;ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/s,mJp/<rr<%QrrD3VmK$5cJaV+W"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK0/mJp8?rr<%QrrD3VmK$>fJaV+W"+A23@=S~>
+!rqu=p>u?QNrSG-!E/s,joA<4rr<%Qs7bXV;ZD=1f&d(ZpA^Y5~>
+!h?&@p?hoYNrSG5!E/s,mJp/<rr<%QrrD3VmK$5cJaV+W"#6UA.=_~>
+!liB.p?ho\NrSG5!EK0/mJp8?rr<%QrrD3VmK$>fJaV+W"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/s,joA<4rr<%Qs7bXV;ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/s,mJp.9s4mVSk4n?F;ZD=9f'WW#S>7Ta~>
+!m8N2p?ho\NrSG5!EK0/mJp7<s4mVSk4n?F<W@X<f'WWg`l__?~>
+!rqu=p>u?QNrSG-!E/s,joA;1s4mYKjoJB[J`bPG"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/s,mXaNSk4n?F;ZHX^JbJ[.lg=j0Umrla~>
+!liB.p?ho\NrSG5!EK0/mXaNSk4n?F<WDsaC\$oamdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:nfmMmmdff:mdff:mdff:mdff:mdff:mdfr:o'Z):o'Z):o'>]GH-4-8
+J,~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZHXVJaW*slfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZHU]CA.)hme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6):+nk?tme6)Bme6)Bme6)Bme6)Bme6)BmdBf:p?qYBp?qY>mK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK/NmYC32<WDp`C@^f`mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff6+nG'lmdff:mdff:mdff:mdff:mdff:mdBZ6o'Z):o'Z)6mK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZHUUC@:6Pk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hBo+n"L\k3hC"k3hC"k3hC"k3hC"k3hC"k2u*omcNs"mcNs&jo`m%s."T~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZHX^s7V$Dq#C<dlg=j0Umrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<WDsa"7kmRqLS\Errr8mmdff:lg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZHXVs6fjZIfK-ApAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAb0ds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKm!VZQlpAOFFjo`U&p8!3~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZHU]s7ZBjs6b-omcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"qrS%Lp@dqJlL"a7S>7Ta~>
+!m8N2p?ho\NrSG5!EK/NmYC32<WDp`s763`IfK98lK7*gio]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7[k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_s5""?hW!\co'Z)6mK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZHUUs6^-cmf3"KhVQf^h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*hZ).*h>l+*h>l+*h>l+*h>l+*h>l+*hYYh+hWF7gmcrp:c1_1-J,~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZHX^"SV9Ok4XB+!q,4-rT=+Qlg=j0Umrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<WDp`#3+e)lMCP\rq^$rqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'd^,51m,qY'dZqY'dZqY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*lg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZHXV!:KjC!p94Vqt:$Xrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6N`p?pefc2H2lmd'!;`W,Y-J,~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZHX^s5s=;Jc>iPk2+YehWaG13LlloJ,~>
+!m8N2p?ho\NrSG5!EK/NmYC32<WDsa!8d\.!;?BkIes*@s8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)TlqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$Egp?'rSrRq8:lL"b&`l__?~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZHXVr7(r<pAajdL@tl?hTa<qc.1A/jo`m%s."T~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZHX^"lAD(e_^"Nrs/Sde^`g=e_]TZ"#6UA.=_~>
+!liB.p?ho\NrSG5!EK/NmYC32<WDsa"k),Ydamu?rs/8SdaI"+cJ%RO"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZHXV"jPTJc->\QrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrsADee]l@h
+e]lY4lfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!E/s,mXb)cpA"%V;ZHX^!R9d+eH#;orrN/frm_,-c->D:mK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK0/mVDC]o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o("j0o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)>mdff:
+mdff:mdg/@!EK0smKU\bda$;/qL\_Qp?'ZGdb;^`ip6"7IE'E<J,~>
+!rqu=p>u?QNrSG-!E/s,k(2sSmeGoF;ZHXV!PR%_`<PJmp@eO[s8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'1Qjs7ZK\hYtIre\/rYlfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!E/s+mV;I`p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBmQ("/p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qABme6)B
+me6)Bp[/&[s823f`ST.ieaA"g#lj>Cc.1sq^#nYK"#6UA.=_~>
+!liB.p?ho\NrSG5!EK0.mV;=\o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):mQ'k+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Yr:mdff:
+mdff:p[/&^s823h^=q#Tdd$Q&K`;ATp>XB;db;FLip6"7H-4-8J,~>
+!quZ5p>u?QNrSG-!E/s+k%a>HmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"juMklmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcN["k3hC"
+k3hC"pZ;KSs81p^[+3F7c0"uuGlRL;pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAb*b#N!G5c.027hWs;+`W,Y-J,~>
+!i2>Hp?hoYNrSG5!E/s,mf3!3s5<qUpA"%V;ZHX^!OU__blR8+o`+dghuETSrVlitpAY*mc2Rh<
+mf(H5hR'uQlg=j8S>7Ta~>
+!m8N2p?ho\NrSG5!EK0/mK<%JpA0@?jSoD[p?qM>o(_VR<WDsa#I;q'_TM$3p@\:Z!8mYN!<)`o
+!;?6h!7(EIp@@@g_TLH8]&)c@"+A23@=S~>
+!rqu=p>u?QNrSG-!E/s,k5XlJp1=9ts7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKm1A:bAs7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds8VfmrV$3X
+puVTTs81p^Us6ll^#&bV!VYs\p&a[Umf)qW!!;T^mf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n^
+me6)BquH`i!q$'Vrq6E]p?qqR!q$'Vrq6E]p?qqR!q,dMrq6E]p?qqR!q,dMrq6E]p?qqR!q,dM
+rq6E]p?qqR"7GmNpAXIbhS$VAc(q_slfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!E/s+mf3"Ys8VLqk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k2n;ak3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3i-/"Rc!Wme6DC
+!E/spmK]iMc,J5qp@eFa!;??j!VQNlrrDcjrrDcjrrDcjrrDcjrrDcjrrDckrs&Pts8N'!s7ZBj
+!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??js7Q][e]#eiXM*c^mK52>S1/s~>
+!liB.p?ho\NrSG5!EK0.mf2kXp1F@$o'5Ask2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_i]6/\k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2P7Sini\W
+mdff:p[/&^s824MV:*N#b22^[p@@qJp@@qJp@@qJ!:ojSp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJ!:ojS!!#^do(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYFhTERTd\XP3lg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/s+k5XiSp?qtSmbZgNrn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*
+rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*
+rnd\*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rndP&"Q&;/k3i!+
+!E/spjpIp/`O*V7mcO62pAXI]p?qYRmK*CVpAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYR
+mLJsYp?hqKp?hn\mdBf:pAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYR
+mK3+MpAXI]p?qYRmLJsYp?qYBma]:``Qb3chWs;+`W,Y-J,~>
+!i2>Hp?hoYNrSG5!E/s,mKE7OmcO4os69ObmcNC)k5P)LmK$5cqsHe@hSmIYk3hs:s7ZKds7ZKd
+s7ZHms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd!;?Hds7ZHms7ZKd!!#[lpAajdpAajd
+pAY-mpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdp@dq:
+c,IZYSA!eFmK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK0.mKV\5ip-C?s8Mk&pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZqE"?HpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LFhU^Q;
+hW!tko(_VR<WDsa#*mWR^;f$to^Vt^iUQsKqsj^erUTsgp@81`b45i+hT!:HdZqE#lg=k'`l__?~>
+!rqu=p>u?QNrSG-!E/s,joFiKh?)j5s82Kimf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+meuhZmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n`me6)*e]n'CrpKRD
+!E/spjp%'p]sPK'k4J'A!9*>G!;l0a!<)?c!;>g\!6X^8k1./P^!2eKea)?"c1_1-J,~>
+!h?&@p?hoYNrSG5!E/s,mf2GKhLY^jrrV?>ec"@umK$5cqsFWPe]kePhXgF@!;cBh!<2Zq!;6Ed
+!!)ukr;cij!<Dil!;uNj!;uNm!;?*drq?0g!VQNmpAG!jp&P0erW)ulr;cij!<Dim!<2Zl!:BIb
+k0:TaeWdc0lg=j0Umrla~>
+!liB.p?ho\NrSG5!EK0/mJu,Bg&UjFs'bd(qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$Eg2#mFPqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqYKpJf$aNN
+!:'=H!EK0smK\m&`k'1DlK\'1!!)l`!!*#d"T[rjmJm7cmem.bmK!=Ur;cc`!!)rb!s%cW!<2E_
+!!2KfrpK^brpBdemf!4dmem.bmK!=UrW)rc!!)KUs69jC`k'1<Oh0E8mK7aW`aOA~>
+!quZ5p>u?QNrSG-!E/s,k5<a4me6\Ss+0n3p':$Bc-=e`e^aBU!E/spjsc5-]sPK'k2u*omcNs"
+mcNs"mcFN3mcNs"mcFN3mcFN3!9O7]mcNs"r;Zugk3`6;r;[GlmcNs"!9W_3mcFN3mJu\;meQnd
+mJu\;mem+gk3h@3k5G>]k3i0J"Qo.7!9X7\+6N"R!9W_3mcNs"mcNs"mcNs"mcNs"k1./P^!2JB
+hWs;+`W,Y-J,~>
+!i2>Hp?hoYNrSG5!E/s,mKMJ0k1/>^JcFs6#3OIdk2+YFp[/&[s823bK@Tt?!8d_CHM6e#me6)B
+me6)B!;>jSme6)B!!)Eeme-V\mJm7\mJm7\mJm7\mJm7\mJu\Kme6)B!;>jSme-YSmJu\K!!)H\
+me-YSmJu\K!!)H\!!)H\!!)H\!;>jSme6&Kme-V\me-YSme-YSme6)Bme6)Bme6)Bme6)BrpC$R
+`P'7IK>$.-mK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK0/mKM%mg="RCJcG!7#PR$&db`^'g@t"9<WDsa#)1LB]#*1`o]cDVqWe(\
+([;"cl2UhL!!)<L!!)<L!!)<L!!)<L!;l$]!;u*e!:&hLlKS?LrTY!qlKSB7l2UhLl2UhLl2UhL
+l2^_H#6=&S!!)<L!<26`!:K+Xk1[\`_U=.LhWsS3IE'E<J,~>
+!rqu=p>u?QNrSG-!E/s,jos#[e]lA,qYpQhr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcj
+r;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcj
+r;R)sma]S,e^_ppmeGoF;ZHXV$@C%2[(Y#Hk2,7WroO:=k2-+"!W_B>roRJBjo>DD!8ci<!9O7]
+k2$(<k2$(<k2lXDk2$+#k2,7WjoFQ#k2,5#k2$*pjo>D<k2,5#k2$*pjo>D<jo>DDjo>D<joFQ#
+k2,7_!8ci<!9WDDk2,5#k2,7WroO:=k2-+"%c6@)k2,7We\/?'c$QhJlfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!E/s,mK(Sprm_#BJcFs6!:Kj:"5_;Ik4n?F;ZHX^#D:RO^!5F%k5=WIk5=WI
+k5,/Xmf!4dmLK<cmcFN;mJu\;md:)CmK!7S!W_ZNrU'[dk5F]Q!9W\Lmd:);rU'mjk3`6;mJuDK
+mK3IWjoGDK!<D9[mL0*`mJu\CjoFi;!:K"ImJuDImJuDImKr%DhT`aYeUtQtlg=j0Umrla~>
+!liB.p?ho\NrSG5!EK0/mKU\bda$;/qLS\3rs8>\cHakl`ld<9mK$>fqsG,Kd`/l<f&G]Oio]7_
+io]7_io]7t!!;<Bk5G?uk2HC#k2HC#joFQ'k2HC#joFQ'joFQ'k2PO_!93/#k2HC#joFQ'!93/#
+k2HC#joFQ'!93/#joFQ'!93/#!93/#k2PM'k2HC#k2HC#joFQ'k2PO_k2PO_k2PO_k2PO_k2PCO
+`k'1<J\'_(mK7aW`aOA~>
+!quZ5p>u?QNrSG-!E/s,joN0Grl#*(me6ASpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquo
+rq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquo
+rq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6QrpAajdmb[r^
+"4b*(hY?46;ZHXV#CF_/[(X`@eb.er!<1jS!<:mU!<1gW!8cQ4rS@VVhVJ83h>dQQh>dQRh?Eu:
+h>lEh!;t[X!8cQ4hVJ82h?*c7h>mQ3!!)oQ!s%37!<1gW!8cQ4m+qul]sPJlHaMYqjo`U&p8!3~>
+!i2>Hp?hoYNrSG5!E/s,mKLSde]lY4JcFs6#O^-ee`Oiak4n?F;ZHX^"`rP>]uAk-k$%38mcNs"
+mcNs"mJu\;mcNs"mcFKLmcNp;mcNp;mcFN3mcNp;mcFN3mcFN3mcNs"mJu\;mcNp;mcFN3mJu\;
+mcNp;mcFN3mJu\;mcFN3mJu\;mJu\;mem,-k3`6;k3`3LjoFQ3k3hC"k3hC"k3hC"k3hC"k3hBg
+rl"uiF1pGrmK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK0/mK^J[d`0`#pA0@?m/ICgp>XB;db;FLiqVpB<WDsa#'JA2]#*%To\oiN
+q;VDSro*nXro+"[io0t:iWB2?iW/u;!!)oU!!)rV"p!ZB!92u<r8In\io0stiW/r:!s%??!<1sX
+!<2!V!<;$Y!<2!X!!2'ZmG\E.f###8dWN.Xlg=k'`l__?~>
+!rqu=p>u?QNrSG-!E/s,jor-Bc+VBarUta@pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAagts7ZKds7ZKds7ZKds7ZKds8DWrhSm1Q
+e[3$HpuVTTs81qgC<a,m^!5*ae_\j5e_\j5e_\j5!8c8_e_\j5eGoU+e_U;_e_U;_eH".Ve_U;_
+eH".VeH".Ve_\j5!8c8_e_U;_eH".V!8c8_e_U;_eH".V!8c8_eH".V!8c8_!8c8_r;\1ph>lE_
+h>dQ+!7frVhUUK5hUUK5hUUK5hUUK5hUTla['\(m[+4L)"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/slmJm7(mK']OrlkK3p@SC^!:g'k!<<'!q#:<op\t3nr;Q`srr;lrq#:<o
+li-qbr;Q`srr;lrj8T/Rmf(H5hR'uQq!J/\s823fF4JOKc//'S!!)iWrW)u\!!*#\!s%KG!<)$^
+!9WDDroO1\qrRkYrT=+[s5jC`k2l[AjothJjoFQ+!<)$^!9WDDroO:_k2l[CjoYVGjoGABrW)<I
+#N!_=c.-mKk3MF;0r1<gJ,~>
+!liB.p?ho\NrSG5!EK0omJm7(mK^&Kb/2<`o(MbQqZ-0_!s&2o!;QBj!;H<i!;uZn!<2im!;QBj
+!:0I]!;uZn!<2im!9Et_p@@@g_TLH8]&*5M!EK0smMp)l`k'%<hVR8Kini\Oini\Oina[lini\O
+ini\o!)DP1!8c_l!8c]8ini\O!8c]8iniYpini\Oina[liniYp!8c]8ina[lini\O!8c]8ina[l
+iniYpina[lina[liW.upiW.up!8c_lir/otini\Oini\Oini\Oini\Oini\OhU]QT`mS_8hWsS3
+H-4-8J,~>
+!quZ5p>u?QNrSG-!E/sljo>CujoqR*`P&tArpBg\mf)n]me6)JpA4gkme6)Jp&a[Umf)ncme6)B
+!;>g\mf)ncme6)Bp&OOSmf)nhme6)B!;>jSme-YSme6PY!VYs\p'C*[me-YSme6)Jp&a[Umf)n]
+me6)Jp'gB_mJutSme6&Kp@dqP!!;T^mf)n]me6)Jp&a[Umf)n]me6)Jp&jaVme6YJ#N!/-`Qb3c
+ebJ8-;ZHXV*,<I+[(X`@e_\j5e_\j5e_\j5eH".Ve_\j5e_^9*:>XM$e_\gVe_U;_e_\gVe_U;_
+e_U;_e_\j5eH".Ve_U9+e_U;_eH".Ve_\gVe_U;_eH".Ve_U;_eH".VeH".V!8c8_!8c6+e_\j5
+rW!qpe_\j5e_\j5e_\j5e_\j5e_\j5c+U3lc"aWBlfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!E/slmJm7(mK]iMc,J5qp@eFa!;??j!VQNlrrDcjrrDcjrrDckrrE,nr;Qcj
+r;Q`sr;QcjrVllupAP!n!;?Emrr2ulr;Qcjrr3$"s7ZBj!;??j!;??j!;?El!W`8orr3'#s7QHk
+rrDclrrN3#pAFpjpAFpjpAFpjpAFsjp'9a1`Qd8@^#o+X!E/spmK$eIrl+ooIcfMLhWE\WhWE\W
+hW=h#hWE\WhW=h#h>lEp!9W,<!9W,<!9W,<!9W,<hWEYphWE\WhW=h#hW=e<hWEYphW=e<hWE\W
+!9W,<hW=e<hW=e<hW=h#hW=h#h>lEph>lEp!9W/#h>dQ<hW=h#h>lEp!9W/#hWE\WhWE\Ws5!t!
+]uAi;^#&)C"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK0omJm7(mK]T:b.c$To(%;(o(MYJo(MYJo(MVSo(MYJo(MYJo(MYJo(MYJ
+o(MYJnc87So(MYJo(MYJo(E(Wo(MYJo(MYJnc87So(MVSo(E(Wo(MYJo(MYJo(MYJ!;?!Wo(MYJ
+o(MYJo(MYJo(MYJo(MYJ!;?!Wo(E(Wnc87So(MYJo(E(Wo(MVqp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@e2b.c$HV7POYmK$>fqsFYsd_`T0f%U,[GhV$.hV-i?hV-fdhV-i?hV-fdhV%t`h>lEd!!(m0
+!!(m0!!(m0!8?;`!8?;`hV-fdhV-fd!8?;`!8?90!8?;`h>lEd!8?90!8?90!8?90hV-fdhV%t`
+hV%t`h>lEdhV%r0hV-fdhV%t`h>lEdhV-i?hV.tc#hmkD]#)m(]&)c@"+A23@=S~>
+!rqu=p>u?QNrSG-!E/sljo>CujpIp/`O*V7mcO62pAXI]p?qYRmK*CVpAXI]p?qYRmK3+MpAXIc
+p?qYB!:KRKpAXIcp?qYBmJutKpAXIip?qYB!:KRKp?hqKp&OgcmK3+MpAXIcp?qVSmdBf:pAXI]
+p?qYRmK3+MpAXIip?qVSmdBf:p&OOK!:KR[mKiOSp&OOKp?qYRmK3+MpAXI]p?qYRmLJsYp?qYB
+ma]:``Qb3chY?46;ZHXV#$T9b['\*&rmc8<e]lXhe]lXheH".Ee]lXheH".E!6s$oe]e'oe]e'o
+e]e'oe]e*=e]e*=e]lXheH".EeGoToe]e*=eGoToe]lVEe]e*=eGoToeGoToeH".EeH".E!6s'=
+!6s$oe]lXh!!(QoeH".E!6s$oe]lXhe]lXhrmh%ns0MpBc!%L)lfJ;opA^Y5~>
+!h?&@p?hoYNrSG5!E/slmJm7(mKf?>`Pp*ame6@(s7ZKds7ZKds7ZHms7ZKds7ZKds7ZKds7ZKd
+s7ZKdrrE)ms7ZKds7ZKds7QHds7ZKds7ZKdrrE)ms7ZHms7QHds7ZKds7ZKds7ZKd!;?Hds7ZKd
+s7ZKds7ZKds7ZKds7ZKd!;?Hds7QHdrrE)ms7ZKds7ZHms7ZKd*WPj5pAajdpAajdpAajdpAajd
+p@dq:c,IZYSA!eSmK$5cqsG,,e]kePhWE\WhWE\WhWE\WhWE\i!!M0@!!(mS!!DB?k2-%:%HcO0
+!9W/#!!(m<hWE\m!!hBChW=h#hWFb:#MoF\joFQ#k5>8dhWEYphWEYphWF\8-/JXYk2,5#!8ckp
+!8ci<k2$*pk2,7Wk2,7Wk2,7Wc+VBP@_LpimK52>S1/s~>
+!liB.p?ho\NrSG5!EK0omJm7(mKSs)_S4%Hme$&M!:97V!;5m_!;H$a!;uBi!:o[\o^Vt^lLFoT
+r:0pio'ueUnc/[Rnd+[?`kK=<Q+GiImK$>fqsG,'d`/l8db<F3g>:Q?g>:Q?g>:QY!!M$4!!(aO
+!!D*3hV.o.%Gogq!8cGd!!(a0g>:Q]!!h67g>2hdg>;c.#MK.Xh>lEdhYdE\g>:N`g>:N`g>;],
+-/&@QhV-fd!8?;`!8?90hV%t`hV-i?hV-i?hV-]3_Rdb8?+SnYmK7aW`aOA~>
+!quZ5p>u?QNrSG-!E/sljo>Cujp%'p]sPK'k4J'A!:9+R!;5a[!;Gm]!;u6e!:K7To^2\ZlL"WP
+r9aXemd:)MmJm7NmKht*]sPJtPdK!9joJB[qrS&cc+UKtc1BK\!<:UL!!(RJ!<(IH!<1LK!<1OK
+!;tCF!<(FJ!<1OI!!LgP!7_)KeboLIeGoUKeH,a$eb]=IeH#QurrE&K"p!3(!7fU"p!j;l]sPJt
+>.!/Pjo`U&p8!3~>
+!i2>Hp?hoYNrSG5!E/slmJm7amem.bmK!=UrW)rcr;clc!!*#d!W_ZVr;cfar;cibrW)rc!!)l`
+"dIQ^^!5F*p&G*hp&P0erW)rkr;clk"T\8i!;?-b!<2Zm!;?Blqt:!ir:U6np@\Idp@\IdrV$3j
+rq6?mpAP'ep&G*jp&kBhp&G*gpAY-bpA"^ep'9a)^!5)l^#o+X!E/spmKQSGc,IZYhL=VDk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7WjoFQ#k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k5X<<`<=HB;SCrQmK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK0omJm7amem.bmK!=UrW)rcr;clc!!*#d!W_ZVr;cfar;cibrW)rc!!)l`
+#EdHS]#NIhlLjQF!;c*a!:KgdrpK^bs6^$jmd:)Cmem.bmK!=UrW)i`!!)rb"9@lX!!)`\!!)uc
+rW)rc!<DQe!;Ps^!;u6f!:K7T!;Z'_!;,^T!<;Kel3H%_]#N0\]&*5M!EK0smKHVA`kK=<jk9\7
+[FtT\lIlKo_S4%@<P%&QmK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/sljo>DYk5>;ZjoGJErW)r[r;cl[!!*#\!W_BFr;cfYr;ciZrW)r[!!)lX
+*K.nM[(Y#Pk3hC"k3hC"k3hC"joFQ3k3hC"joFQC!!;<Nk5>8bmcFN3mJu\;r;Zugk3`6;rW")/
+k3hC"joFQ3k3h@3k3`3Lk3hC"k3hC"k3h@3k3hC"rW!)hk3`6;rW"G9k3hC"k3hC"!:K";k3`6;
+jo>DLk3hC"k3h@3!:K";k3hC"k3hC"k3i$F$g-m>k1./P^!2JBhY?46;ZHXV##`^Z[(X`/Iau]n
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(h!7f?Ec.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hblH#=c.1(hc.1(hc.1(hc.1(h
+c.1(hs31b][(X^^[+4L)"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/slmJm7]mL]HemJm7TmJu\C!!)HT!:K7TrpBadqsFpomd:&Tmd:)CmJu\C
+!!)c]!JAr%`;ncomR$X8p?qYBp?qYBp&OgSp?qYBp&G*\p&OgS!!)`\!:KO\p?hqKp&OgSp?qYB
+!!)`\!:KRKp?qVSp?qYBp&OgSpAP%Bp?qYBp?qYBp&OgSp&OgS!!)`\!!)`\!:KRKp?qYBp?hqK
+p?qYB!:KRKrW!Z#p?qYBp?hqKp?qYBp?qYBp?qYBq#CEgrpC$R`P'7IK>$.:mK$5cqsFVchUTTi
+ec+\;hWE\WhWE\WhWFV6F5H'9k2,7W!8ckpk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WjoFQ#k2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2+A%e_X3;k3MF;0r1<gJ,~>
+!liB.p?ho\NrSG5!EK0omJm7]mL]HemJm7TmJu\C!!)HT!:K7TrpBadqsFpomd:&Tmd:)CmJu\C
+!!)c]#)1LB]#*1`o]cDVqWe(\s6:-qlKS?LlKSB7l2^,7!:&hLqs+1]s69Raqs".]r9=7^rp'I_
+q!%hZrosjklKS?LlKS?LlKSBEl2Uh^l2Uh`lM^e[l2UhVlM1GZl3QP+_RdV4Kt?.9mK$>fqsG(j
+f$;.Pdb`^7g>:Q?g>:Q?g>;W*F5#L)hV-i?!8?;`hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?h>lEdhV-i?hV-i?hV-i?
+hV-i?hV-i?hU]]`cIP\#hWsS3H-4-8J,~>
+!quZ5p>u?QNrSG-!E/sljo>DUjq.UUjo>DDjoFQ+!!)0D!9WDDroO1\qrS@gk2lXDk2l[+joFQ+
+!!)cU$@C%2[(Y#Hk2,7WroO:=k2-+"!W_B>roPrljo>DDjoFQ#!!)0<!8ci<k2$*pjoFQ#k2,7_
+!!)0<!9WG#k2,5#k2,7WjoFQ#k5G>_k2,7WroO:=joGDC%KPYJ!!)0<!!)0D!8ckproOXGk2$+#
+k2,7W!9WG#rW)u\#i=_#k2l[#k2-+"!oE(rroO4;q#CfbhWE\F]sPJtHaM>ujoJB[qrS&Sc,IB0
+c1KQ^!;b4G!4C>W!:&)>c+UL'bt>A"lfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!E/slmJm7]mK3IWmK!7S!s%cW!<2Bg!:K7TrpBadqsFOdmd:)SmK3IW!!*#d
+!!)c]#D:RO^!5F%k5=WIk5=WIk5,/YmM,`imcFN;mJu\;mJu\C!9W\Lmd:&Tr9aObrpBgfmcOK9
+!<D9\mK!=MrU0XbrU'pQmd:)CmJm7dmK3IOmK!7S!!)rb!9X:K!W_ZNrpBgfmcON:rW)la!!)rb
+!9X4I!p8q=qZ-W`$0L[4c+VBPK>$FBmK$5cqsFbVhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9
+k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9k5='9
+k5='Bk2+t>c.1Z:^#&)C"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK0omJm7]mK3IWmK!7S!s%cW!<2Bg!:K7TrpBadqsFOdmd:)SmK3IW!!*#d
+!!)c]'7nTO]#N=\io]7_io]7_io]7_iqi^3k2HC#k2HC#joFQ'joFQ'!93,@k2H@@k2PO_joFQ'
+joFQ'k2PO_!93/#k2HC#k2PO_rW"J.k2PO_k2HC#jo>D@k2HC#joFQ'joFQ'k2PO_k2PM'k2PO_
+joFQ'k2PP&!#+MSk2PM'k2PO_k2PO_k2PO_k2Q7<%-HR3io8P/]#N0L]&*5M!EK0smKZ/2cGm`L
+g>7M:$/XCeb/V`\7(V7@mK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/sljo>DUjoYVGjoGDC!s%KG!<2*_!9WDDroO1\qrRt\k2l[CjoYVG!!*#\
+!!)cU#CF_/[(X`@eb.er!<:mU!<1gW!8cQ4rn[t^hVJ7hh>lEh!!)rR!!*#T!!)oQ!!)rR!!)rR
+rW)fO"9@<8!!*#T!s%37!<1gT!;PCN!;t[R!;t^Q!;t[R!;#(E!;t[Yc+UKt`I"uKpuVTTs81p_
+6-[B^^!4fNe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lYEc2YH[`RR8]ea)?"c1_1-J,~>
+!h?&@p?hoYNrSG5!E/slmJm7`mem.cmJm7dmK3IWmK!7S!s%cW!<2Bd!<2Eb!<;He!<2Be!:K^a
+p[/3+hSm1IhYuXbmcNs"mcNs"mcNp;mcNs"mcNp;mcNp;mcFN3mcFN3mJu\;!9W_3rW";-mcFN3
+mcFN3mcNs"mJu\;mcNp;mcNs"mcNp;!9W_3mcNp;mcOBH1[aB*k3h@3k3hC"k3hC"joFQ3k3h@3
+k3hC"k3h@3!:K";joFQ3k3hC"k3hC"k3hC"k5>8amcNs"mcNC*`<4Y3^#&PP!E/spmKZq?hTaU$
+hVS1m!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9
+!8dY9!8dY9!8dY9!8dY9!8dY9!8dS7#N""]hT\s3k3MF;0r1<gJ,~>
+!liB.p?ho\NrSG5!EK0omJm7`mem.cmJm7dmK3IWmK!7S!s%cW!<2Bd!<2Eb!<;He!<2Be!:K^a
+p[/6.d_`T4f&$&Y!!)lT!!*#X!s%??!<1s^!92u<io0t;ir/rWiW&uXiW&uUiW&uViW&uTir9#U
+iW9,>iqi`UiW&uXiW&uRiW&uViW&uTir9#WiW&uLir&lTiX"Dl_RdV4Fh6H)mK$>fqsF\hb1=_X
+db<E)hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hVR8Gs3:bub"TD'lg=k#b/Rk?~>
+!quZ5p>u?QNrSG-!E/sljo>DXk5>;[jo>D\joYVGjoGDC!s%KG!<2*\!<2-Z!<;0]!<2*]!9X.Y
+pZ=/Ec*Xjkc.1\$hUUK5hUUK5hUUH_hUUK5hUUH_hUUH_hUMVVhUMVVh>lE_!7frVrW":qhUMVV
+hUMVVhUUK5h>lE_hUUH_hUUK5hUUH_!7frVhUUH_hUVK'1Z$X^e_\gVe_\j5e_\j5eH".Ve_\gV
+e_\j5e_\gV!8c8_eH".Ve_\j5e_\j5e_\j5eboIWhUUK5hUTla['\(m[+4s6!E/spjonZ%c,IZH
+J^k%_c-=5P`CdMolfJ;gs7W7=~>
+!i2>Hp?hoYNrSG5!E/slmJm7amJm7dmK3IWmK!7S!s%cW!<2Bg!:K7TrpBjgmd:)SmK3IWmK!7S
+!s%`h!;#U^F4JOKc//'S!!)lX!!*#\!s%KG!<2*b!9WDDk2l[Ak5PG]jo>D\jo>DYjo>DZjo>DW
+jo>DYjob\Hjo>DYjo>D\jo>DVjo>DZjo>DWjo>D[jo>DOk5PGXjp0bf^!5)K^#o+X!E/spmK[g7
+hVQf5hVS1m!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d\:!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!Uf+Lh?0ig^#nYK"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK0omJm7amJm7dmK3IWmK!7S!s%cW!<2Bg!:K7TrpBjgmd:)SmK3IWmK!7S
+!s%`h!;#V`D:6G8_UdT#ini\Oini\Oini\O!8c_lini\O!8c_l!8c]8iniYpina[liW.upiniYp
+!8c]8iniYpini\Oina[lini\O!8c_lini\OiW.upini\O!8c]8!(l&,hW!DO!92kp!92kphW!DO
+hVnOphW!DO!92kphW!DOh>lElhVnOphW!DOhW!DOhW!DOhW!Al!92kphW!DKf###<dVZSPq!J/_
+s823hEN7a@cHb"prn_tThV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-iCg>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?io17+hU^-/Y$JWqlg=k'`l__?~>
+!rqu=p>u?QNrSG-!E/sljo>DYjo>D\joYVGjoGDC!s%KG!<2*_!9WDDroO:_k2l[CjoYVGjoGDC
+!s%H`!;#>XC;mln^!5EahUUK5hUUK5hUUK5!7frVhUUK5!7frV!7fp+hUUH_hUMVVh>lE_hUUH_
+!7fp+hUUH_hUUK5hUMVVhUUK5!7frVhUUK5h>lE_hUUK5!7fp+!(k_te_\j5!8c8_!8c8_e_\j5
+e_U;_e_\j5!8c8_e_\j5eH".Ve_U;_e_\j5e_\j5e_\j5e_\gV!8c8_e_\j5c+U3lc"aWBpuVTT
+s81p`F/7@2`Pp*HL"61Z#M%)DeYHBUhWs;+c1_1-J,~>
+!h?&@p?hoYNrSG5!E/slmJm7amJm7dmK3IWmK!7S&HM7e!:K7T!:K7Tmd:&Tmd:)SmKrs^mJu\C
+!!)HT!;#UZ@b(Iss5&4ehWE\WhWE\WhWE\W!9W/#hWE\W!9W/#!9W,<hW=e<hW=h#h>lEphWE\W
+!9W,<hWEYphWE\WhW=e<hWEYp!9W,<hWE\W!!(m<hWE\W!9W/#!9W/#hWEYphWEYphWE\WhWE\W
+h>dQ<hW=e<hW=h#hWEYp!9W/#!!".uk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WhSm1IhI=1Tq!J/\
+s823c]i*,Sh?)6ahM((ume6)2k1*@f`STqK"#6UA.=_~>
+!liB.p?ho\NrSG5!EK0omJm7amJm7dmK3IWmK!7S&HM7e!:K7T!:K7Tmd:&Tmd:)SmKrs^mJu\C
+!!)HT!;#U_@FE$(^=M$;hL!u5g>:Q?g>:Q?!8cGdg>:Q?!8cGd!8cE0g>2f0g>2hdg&Tj`g>:Q?
+!8cE0g>:N`g>:Q?g>2f0g>:N`!8cE0g>:Q?!!(a0g>:Q?!8cGd!8cGdg>:N`g>:N`g>:Q?g>:Q?
+g&M-0g>2f0g>2hdg>:N`!8cGd!!!_ehV-i?hV-i?hV-i?hV-i?hV-i?rn[q7f"S`4dUB`Dq!J/_
+s823i\kL8tf$`!tg4eAiipPschTefK^>A2D"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/sljo>DYjo>D\joYVGjoGDC&HLtU!9WDD!9WDDk2lXDk2l[CjpD+NjoFQ+
+!!)0D!;#=W>0Xaf[*?kpeU,Qkc.1(hc.1(h!7f?Ec.1(h!7f?E!7f<oc.)doc.)gEblH#=c.1(h
+!7f<oc.1&=c.1(hc.)doc.1&=!7f<oc.1(h!!(9oc.1(h!7f?E!7f?Ec.1&=c.1&=c.1(hc.1(h
+bl@aoc.)doc.)gEc.1&=!7f?E!!!_Xe]lXhe]lXhe]lXhe]lXhe]lXhrmh%ns0MpBc!%L)puVTT
+s81p[ZqA=:blYl/c%X[ShWE\Fe\t.5^")H2"3(<6Ujr~>
+!i2>Hp?hoYNrSG5!E/slmeZtameZtbmK!7S!!*#drr</h!:K:S!!DWhmdBrPs6fme!U]semem.c
+mJm7`mLs'[c+VBYk2,7Wk2,7Wk2,7Wk2,q7']&iHk2$*pk2$(<joFQ#!8ci<k2-%:%d)X1!9W/#
+!9W/#hWE\Wqu?f\hWF\8$f:%&k2,7WjoFQ#k5>8khW=h#hW=h#hWE\WhWE\WhY[?ThWE\l!%-jb
+k2$*pk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2+@rc.-::k4n?F;ZHX^#53sIXOZ1irn_n^hWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WroOIR
+k2*I;C:)7NmK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK0omeZtameZtbmK!7S!!*#drr</h!:K:S!!DWhmdBrPs6fme!U]semem.c
+mJm7`mLrmS`k'%8g=kE;hV-i?hV-i?hV.f+'\WQ@hV%t`hV%r0h>lEd!8?90hV.o.%c5pr!8cGd
+!8cGdg>:Q?qu?fTg>;],$ejIkhV-i?h>lEdhYdEcg>2hdg>2hdg>:Q?g>:Q?gACpPg>:Q\!%-RV
+hV%t`hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?g=!jL`mS/(hY?L><WDsa#P*jBV9[ZGeqMfXhYuL=
+euhPXZHD=qmK7mWb$ff~>
+!rqu=p>u?QNrSG-!E/slk5,,Yk5,,ZjoGDC!!*#\rr</`!9WGC!!D?`k2uO@s5s=]!TjC]k5>;[
+jo>DXjonr5]sPJto@<[;!S%2LeGoUKec,UUeH".M!7fU"e^aTurm^uKrm^uKqUPKDrmglGq:,HF
+rmgrIs4%)Lrm^uKpXT0ArmglGrRClJkLBg^]sPJt>.!/]joJB[qrV\^Mb9eac.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1>[c.1(hc.1(hc.1(hc.1(hc.1(hc.1)<ec4J0
+c(ms@XMsJe"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/sTmf*:Tmf*:VmV#MTc,IZYhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\W!!(m<hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEYphWE\W
+hWE\WhWE\WhWE\k!&i]rhWE\WhWE\WhWE\WhWE\Wh>lEphWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hVQ5jc/)@3hY?L>;ZHU]#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r@%_$r[@h%r[@h%r[@h%r[@h%r[@h%r@.b$"B'lZ^#&&B"#6UA.=_~>
+!liB.p?ho\NrSG5!EK0Wmf*:Tmf*:VmKHVA`kK=<iS+;3d+SI"o%Np?mb.X@k1U'k_S4%@<P%&^
+mK$>fqX/+h[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$8j-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbp/1<&+<J@`mg?S"l"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/sTk5PGLk5PGNk%IZ;]sPJtc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(h!!(9oc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1&=c.1(h
+c.1(hc.1(hc.1)8!&i*Pc.1(hc.1(hc.1(hc.1(hblH#=c.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c-<r/^!0H^ebJ8-;ZHUU"7EO*0nCeQ.0VG(K<2c:lK/2fs7W7=~>
+!i2>Hp?hoYNrSG5!E/smmeQqSmem.Tmem.SmKHMFe]#e`roP*Tk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk5>:0hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEYp
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhTa$ihGV&Lq!J/\s826`p&jaFc,G7Irk/HRc0"Hflg=j8S>7Ta~>
+!m8N2p?ho\NrSG5!EK0pmeQqSmem.Tmem.SmNP?UcGITLhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hYdG(g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:N`
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?f#GSPekE[3q!J/_s823go'Z)6hTE]d])K8D_TLa#o'>]GIE'E<J,~>
+!rqu=p>u?QNrSG-!E/smk5#)Kk5>;Lk5>;KjonB%`P&t0jOO2/cIDmp^"!A4]sPc'9!mIMjoJB[
+qr[nGJ*,V,]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tLed[(Wi[[(Wi[
+[(Wi[[(Wi[[(Wi[[/[fG[(Wi[[(XH8k3hQt"3pQ>S:C~>
+!h?&@p?hoYNrSG5!E/s,mKl29e]l(ihWE\Wrn[Y;r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9
+r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9
+r8%G9r8%bBhVQN%e_WU*hY?L>;ZHU]CA.)hmdArohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\O+m.YDhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOk2,7WmdBf6mK52>S1/s~>
+!liB.p?ho\NrSG5!EK0/mKZ/2cGm`Lg>7D7m+Md&g=FEdcIt[thY?L><WDp`"S2!KlK3ZSr8%J:
+lKR^=H-4-8J,~>
+!quZ5p>u?QNrSG-!E/s,jp",r`P&t0c%"9ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]f2dc.1(hc.1(hc.1(hc.1(hc.1(hc.1(`
+]tMD86+#2;joJB[qW;P\k3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e^Yi"e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,hUUK5hUUcNmcrp:`W,Y-J,~>
+!i2>Hp?hoYNrSG5!E/s,mKZq?hTaU$hVS1m!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9
+!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9
+!8dS7#N""]hT\s3k4n?F;ZD=9f'WW#S>7Ta~>
+!m8N2p?ho\NrSG5!EK0/mKZb7f#l.`g=h&5g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:O)hV-i?hV-i?hV-i?hV-i?hV-i?hVR8G
+cHb"`9Y0*UmK$>fJaV+W"+A23@=S~>
+!rqu=p>u?QNrSG-!E/s,jonZ%c,IZHJ^s#8#i<hN`Qc@o[,1T?!E/rKk18Ysc1_1-J,~>
+!h?&@p?hoYNrSG5!E/s,mK[g7hVQf5hVS1m!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d\:!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!Uf+Lh?0ig
+^#o+X!E/rKmage.0r1<gJ,~>
+!liB.p?ho\NrSG5!EK0/mK[a3g="9lf%U,[@+sJkhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hVL<IhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-iGio]+K
+db:j0]&*5M!EK/Nmage.H-4-8J,~>
+!quZ5p>u?QNrSG-!E/s,jp,t'e]l(Pc-:gimFD3m#M%)DeYHBUhY?46;ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/s,mK1("c2QQ$e_]/6k3_:;me6)2k1*@f`SUCX!E/rKmage.3LlloJ,~>
+!m8N2p?ho\NrSG5!EK0/mKgBtb1>.ldam-'hX0/+ipPschTefK^>AYQ!EK/Nmage.IE'E<J,~>
+!rqu=p>u?QNrSG-!E/s,joVn^`W"*``QcYYea:lnhWE\Fe\t.5^")o?!E/rKk18Ysc1_1-J,~>
+!h?&@p?hoYNrSG5!E/s,mKWBC9!$S"k5O4Gk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2n;Qk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2-+"#O^a2
+Zq>)?c1gW,;ZD=9f'WVpUmrla~>
+!liB.p?ho\NrSG5!EK0/mK`<B7&A2[g=Ci/mFhQsro+.5Y"394b3&Ke!EK/Nmage.H-4-8J,~>
+!quZ5p>u?QNrSG-!E/s,k%jCC8u0GNe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe^Z:se]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]n*Ds5!q(
+Ue5*t`V8Kq;ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/s+mKWBuC,%.d1&NI#1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%
+1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%
+1&WO$1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&`U%1&WR$0a(C,[(Y>j
+mK$5cJaV+W"$)mI.=_~>
+!m8N2p?ho\NrSG5!EK0.mV;=$AMbqd/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t
+/1<%t-orn-/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1;nt-nI2T
+KsJGHlM0cJ<W@X<f'WWg`l__?~>
+!rqu=p>u?QNrSG-!E/s+job%Y@PNE_js^Hg;M2'aebA2,;ZD=1f&d(ZpA^Y5~>
+!h?&@p?hoYNrSG5!E/s,mf)n^mcMd5J\C3Z"NAXJme6GD!E/rKmage.0r1<gJ,~>
+!liB.p?ho\NrSG5!EK0/mKW7Mo'5)S_L];\\cfmmhWj\,mK$>fJaV+W"*r&/@=S~>
+!quZ5p>u?QNrSG-!E/s,k5Od^k2+(j[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[
+[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[
+[(Wi[]fNO6[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(X/[]sPJ[
+]uAjjmeGoF;ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/s+mV;I`p?qA*k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7WhDs`Tk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2+tWhWE\W
+hX9h*p[/&[s+0UhmK5J>Ua^f~>
+!m8N2p?ho\NrSG5!EK0.mKE+KmcrqchW3Mok3D[.!EK/Nmage.IE'E<J,~>
+!rqu=p>u?QNrSG-!E/s+k%a>HmcNZ^hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5eN)L:hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUU05e_\j5
+e`Q#^pZ;KSs+0=`jo`m%s."T~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZD=9f'WVpUmrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<W@X<f'WWcb/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZD=9f'WW#S>7Ta~>
+!m8N2p?ho\NrSG5!EK/NmYC32<W@X<f'WWg`l__?~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZD=1f&d(ZpA^Y5~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZD=9f'WVpUmrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<W@X<f'WWcb/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZD=9f'WW#S>7Ta~>
+!m8N2p?ho\NrSG5!EK/NmYC32<W@X<f'WWg`l__?~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZD=1f&d(ZpA^Y5~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZD=9f'WVpUmrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<W@X<f'WWcb/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZD=9f'WW#S>7Ta~>
+!m8N2p?ho\NrSG5!EK/NmYC32<W@X<f'WWg`l__?~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZD=1f&d(ZpA^Y5~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZD=9f'WVpUmrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<W@X<f'WWcb/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5!E/rKmYC32;ZD=9f'WW#S>7Ta~>
+!m8N2p?ho\NrSG5!EK/NmYC32<W@X<f'WWg`l__?~>
+!rqu=p>u?QNrSG-!E/rKk(i(";ZD=1f&d(ZpA^Y5~>
+!h?&@p?hoYNrSG5!E/rKmYC32;ZD=9f'WVpUmrla~>
+!liB.p?ho\NrSG5!EK/NmYC32<W@X<f'WWcb/Rk?~>
+!quZ5p>u?QNrSG-!E/rKk(i(";ZD=1f&d(Rs7W7=~>
+!i2>Hp?hoYNrSG5JPq/!!<7W<f'WW#S>7Ta~>
+!m8N2p?ho\NrSG5JQ7A'!<7W<f'WWg`l__?~>
+!rqu=p>u?QNrSG-JPq/!!<7W4f&d(ZpA^Y5~>
+!h?&@p?hoYNrSG5JcCB&JaV+W"#6UA.=_~>
+!liB.p?ho\NrSG5JcCB&JaV+W"*r&/@=S~>
+!quZ5p>u?QNrSG-JcCB&J`bPG"3(<6Ujr~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?hoYNrO[uJaS*W_X7LdS>7Ta~>
+!m8N2p?ho\NrO[uJaS*W_X7MS`l__?~>
+!rqu=p>u?QNrO[mJ`_OG_WCsFpA^Y5~>
+!h?&@p?hoYNrO[uJaS*W_X7L\Umrla~>
+!liB.p?ho\NrO[uJaS*W_X7MOb/Rk?~>
+!quZ5p>u?QNrO[mJ`_OG_WCs>s7W7=~>
+!i2>Hp?mq?JaS*WJaUDC"$)mI.=_~>
+!m8N2p?mq?JaS*WJaUDC"+A23@=S~>
+!rqu=p?%A7J`_OGJ`ai3"3pQ>S:C~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@p?mK0JPq%sJPt0!p?i#;Umrla~>
+!liB.p?mK3JQ78$JQ:B'p?i$.b/Rk?~>
+!quZ5p?$p(JPq%sJPt0!p>uIrs7W7=~>
+!i2>Hp?mM3JcC<$JcFF'p?i#CS>7Ta~>
+!m8N2p?mM3JcC<$JcFF'p?i$2`l__?~>
+!rqu=p?$r+JcC<$JcFF'p>uJ%pA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@p?ocjJaS*Wna?AL"4a2o;Z8s)3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3W25G
+;M1dqrV$-V]Cu-iZhF+\"#6UA.=_~>
+!liB.p?k09mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+o'Z):o'Z):o'Z("mXafrmK`=No'Xr&I8JTZ#>fiFddH\oo)%iDo'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)>mdff:mdff:mdg8C:%I`Cmdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+o'Z):o'Z):o'Z)BmK7aW`aOA~>
+!quZ5p?'3ZJ`_OGn`Kf<"O3`h8jV8n#!k708pdAYrU0RF]C,RYZgRPL"3(<6Ujr~>
+!i2>Hp$P!:me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6):
+p?qYBp?qYBp4;X_mdKR$p?n_:5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+3C,Yk3C,[$me6JE6h]sAme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6):p?qYBp?qYBpA+,Lp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qABme6)Bme6)Bp$MoBS>7Ta~>
+!m8N2p$P!6mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff6
+o'Z):o'Z):nq$4[mdKQFo'W(G4<caI3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3;P`=
+SaQ(EmR-R5o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):mdff:mdff:mdg2A9ChNAmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff6o'Z):o'Z):o(DDQIE'E<J,~>
+!rqu=p#\F*k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBo
+mcNs"mcNs"mXaMOk3qF6mcL%e3<G`5meQ!4mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcN["k3hC"k3hC"q;t?<k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2u*omcNs"mcNs1jo`m%
+s."T~>
+!h?&@p?qtSa8c,3JaS*Wna?GN"+*="3W;;j3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk5rnp1"Z\k7HhR11mf3!ss8DZgmf3!ks8DZbmK52>S1/s~>
+!liB.p?i%Rme6M#rrr8mmdff:JaS*Wna6JLmWHi<!d3r%qsFRWme6Lrrrr8mmdff:qsFRWme6Lj
+rrr8mmdff:p?i$.b/Rk?~>
+!quZ5p?)DCrUquGpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0d
+s8DZimXaMOk4.U6mJq>-3<2@u3<2AE3<VW.F7/Jnk5XlJp,E$Fs7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmpAb*brU0RFs6fjZ5QCHWpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0ds8DZime5cF`W,Y-
+J,~>
+!i2>Hp$VkRr;Zfb.H^'\mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs7jok,G
+p?qX*mXafpmKT1A5ri\ek1Tb=k-Sk`5rkJ2mf3"Ys8VL?k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"qrS%Lp@dqJq<n:Vr;Zfb2s0PjmcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mec,Lme6ABp@[hU3LlloJ,~>
+!m8N2p$VkNs7SJQqXWq6io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7W
+hW!DOk3hg.nq$4[mdKQDQ2WltBsQIhs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+qZ$EGZ>';#!1!BJs763`5QCTNlK7*gio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7WhW!DOk3hg.o(h_Ro)JDRs8)<Ok2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2P7Sini\Wmdff:p$Mp1`l__?~>
+!rqu=p#c;B#PRTcp?peoec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D,e_]0\
+eHFakmcNqgk(2[`joCYF3<Erse_0WteZ<Nb3<5<>k5XiSp?qtSmbZgNrn[Y*rn[Y*rn[Y*rn[Y*
+rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rndP&"Q&;/k3i'-s6^-cmf3"KhVQf^h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hYYh+hWF7gme,]Ec1_1-
+J,~>
+!h?&@p?i(WmdB62d/O18k2-(!rq:p2JaW'r"k>n)3McBIs8MEdk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5F`Ijp(8IUcC_,c26o3p?qA2p<*C:mcNC)k5P)OmKE7OmcO5[rrVWNhYlU9p@dnV
+0r1<gJ,~>
+!liB.p$N%Dk2P\&s8W)p2"pe>qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+k2+\Gg>:iWmdbqsJaW'r!7(R+.%0Z&pAb!Oio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io^4!!p8p=r]C2'qX+RIk2P\&s8W)p3qiFDqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*qX+RIk2P\&s8W)p6MC9LqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*p?i$.b/Rk?~>
+!quZ5p>uACrn[_=pAb$`!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj["7G$r
+c2H2lmXaMOk4.R6c2K^,Pj\85s7Y.&"m2%05rlp]joFiKh?)j5s82Kimf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n`me6)*e]n'CrpK[G!:KjC!p94Vqt:$Xrq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6N`p?pefc2H2lme5cF`W,Y-
+J,~>
+!i2>Hp?qtCrnc!$!p8@irSE+nJaW!p#Fn(GF6;oQp>#ZTmcNBghWEsA5s_%<mf2GKhT>d!k2+Ye
+hYHU>k5O5RrrV?>ec"@smK5J>Ua^f~>
+!m8N2p?hq;rRq8FrVnPIs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)Tc
+k17uZg&UDhmXafqmPgP!4Dj*?ip-7;pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LF
+g=G-7hVN675ahN;!8d\.!;?Bk2>[@Ls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)Tck17uZg&UF7mJu,Bg&UjFs#p5YqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$Egp?'rSrRq8:p$Mp1`l__?~>
+!rqu=p?);'"Rc!`pA`\:#O^Hnc.1(heUck6k3qFcPX.<EhVQfFmf2_Kme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)BmbZL=rRD!b3C/o,k5<a4me6\Ss3LBDmbZ45e]lXpq<%V*"Rc!`pA`2,
+#O^Hnc.1(heb%u+c1_1-J,~>
+!h?&@p?i+@k2t4Np<WaCk1/#EhUUJ6mXafqmK7f.9!nT[!8cK1!q+pqroO<i8kOI-mKMJ0k1/>^
+ao;S-e^`g=e_^/j"lAD(e_^#9rs%W9e`P`=hY$:=0r1<gJ,~>
+!liB.p?i+4g=k!+o$ICAp>46GhV-9/JaS*WnEquQ6qFK7hV-]Ws8)HcpA4LZqY'dZqY'd^pA4LZ
+pA4XZqY'dZqYKp^pA4LZqW?M[rn7IW847UtmKM%mg="RCb5V_?hU9j/g<SFKmKM%mg="RC_Z'l7
+hU9j/g<SFFmK7aW`aOA~>
+!quZ5p>uP'e^_phmeZq`pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAP!tp?pJUc.1@heaA"NJ`cLb
+"*6b#V#AgEpAb-c!:KaX!:KaX!:KaX!:KaX!:KgZ!oDJPrm_+P8jROqjos#[e]lA,qYpQhr;Qcj
+r;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;QcjrVm2tma]S,e^_ppmec,Mc.1@hc0kH.!;??j!;??j!;??j
+!;??j!;??j!;??j!;??j!;??j!;?<i$23f;c-=ehc.27Ujo`U&p8!3~>
+!i2>Hp?ht+k5Nm2p<Wa=mf(`=hTa=-JaS*Wna?ET#"m.shUUKVg]%Q9e^`g=bt:l3qsFL0k5Nm2
+p<!=7mf(`=hTa=-qsFL0k5Nm2p;-b/mf(`=hTa=-p?i#CS>7Ta~>
+!m8N2p?i.)g="9pmeY?2#kmE+cI1Fdb2S!?JaW'r2c*1=b1bRtf(/k;s8)cls8)TlqZ$ElqYL6g
+s8)clqZ$ElqZ$Egs8)cls8)chhTjF#g<)r[;#BYb`nJkdddHtTrs8>\cHakl`ld<<mKU\bda$;/
+qSW==p?'ZGdb;^`iqDdBIE'E<J,~>
+!rqu=p>uChec*Mlk3hs:s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'(Ki
+pAaR;rl"ui]uAiZk(2[bk5S$X6,h+!`Qdi+p'0s8`PpBP`VrL,joN0Grl#*(me6ASpAb-c!rquo
+rq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6Nqp@eOShYtIre\/rYqrRpmec*Ml
+k3hs:s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp':Wk
+s7Z0dmb[r^"4b*(hY-(6c1_1-J,~>
+!h?&@p?i+'hUTm$ma(n<ma]S4k/G$rJaS*Wna6N`;Hh?-rm_#Bg]%9Arm_/6c!""KqsFX,hUTm$
+m`GJ6ma]S4k/G$rqsFX,hUTm$m_So.ma]S4k/G$rp?i#;Umrla~>
+!liB.p?i1"g="!hlLt)'rsAPqim,Qlg:k;\JaS*Wna6]`:fYBdd`U#+qVD/Xp?'ZCdb;Q<:f[D\
+#JSp?`mX/GqT]$HqY&po`mWST^>f%X#JSp?`mX/GqSiI@qY&po`mWST^>ekS"*r&/@=S~>
+!quZ5p>uOce]kePk5G!'s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKl
+p'9Hn^!5*7^#">&J`cLbr_b;\e]#MPk4\iKs7ZKds8VfmpAajds7ZKds7ZKmpAajdpAb0ds7ZKd
+s8VNDrl"og^&Cq,jor-Bc+VBarUqrFpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdrq6TR`P'OH[(Y>njor-Bc+VBarUr5NpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdrq6TR`P'OH[(Y>ijo`U&p8!3~>
+!i2>Hp?hsghYtb#me6;Q!!)rs!!)fo!!)Kf!VYs\blch0^#">.JaW'rr`TK=hUTm$me$PX!<)ot
+!<)ot!;?Erk1.H$hS&nlqsFKlhYtb#me65OrrDKe!!)Ng!VYs\blch0^#&YS!OU__blR8+o)JRe
+jSo2[pAY0emf(H5hR'uQp?i#CS>7Ta~>
+!m8N2p?i0kf#kkPk486=q>^Nnq>^Njq>^Nbq?cldk/tQ`f!;mDJaS*Wna6]d?!4bicGIllp@\Ia
+!<)ot!<)ot!;QTop'B[#_Tp`D=^>2-mK^&Kb/2<`o(M\OrrDK`!!)Qc$23rPb/2<PZF\oimK^&K
+b/2<`o(M\OqZ,^R!!)ci$23rPb/2<PZF\odmK7mWb$ff~>
+!rqu=p>uOSc,IB0hYupDp?qqR!q,dMrq6Bnp?qqR!W_r^rq6Wcp?qVSp?qYBrq6E]p?qqR!Uf[[
+mK_U^]uA6l[+0`iJ`cLb#uXr)[*?S'`SU%^p&P-ip&Y3er;Zuos7Z-drq6Bm!;uNjs8M`lmKh[g
+]uA7';HcuqjoqR*`P&tArpBg\mf)n]me6)Jp'C*[!!)`dme6)Jp&a[Umf)ncme6)Bp&OOSmf)n]
+me6)Jp&XUTrU'pI]tMD0UpS\LjoqR*`P&tArpBg\mf)n]me6)Jp&XUTqZ$Warq6E]p?qqR!q,dM
+rq6E]p?qqR!q,dMrq6E]!:Kj["Rc!Op@eLR#N!/-`Qb3ceb8,-c1_1-J,~>
+!h?&@p?i0ehTa$ik4\NHrrDcjrrMfnrVlol!<)otpAP!l!;??j!;??j!;?Bks7Q][e]#eiXM*bI
+mXafrmK@96C96:kblR8+pAY*mrr;uurr2rurr2rupAY0emf(H6hQ1I$CA[E(XPV4@e`QT!r;Qcj
+r;Qups8N'!s7ZBj!;??j!;??j!!)rs!;??j!;?Bks7Q][e]#eiXM*cnmK]iMc,J5qp@eFa!;??j
+#kn8u!<<)mrrE&u!;??j!;??j!;??j!;??j!quWorr2ulqu?]i#NjRUc/,P8k4\3F0r1<gJ,~>
+!liB.p?k/Ad`T;HhX^72o(MYJo(MYJo(MVSo(MYJnc87So(MYJo(MVSo(MYJo(MYJo(MYJo(MYJ
+p@@e2b.c$HV7PN7mXafrmPe]cAZF>(_TM$3s8)cls8)cqqZ$BlqZ$Qq!;c`l!<;oq!<;oqs8)cl
+s8)cho&@g/b1<S(@:f?(7A\GT^<5='o(MYJo(MYJo(MYJo(MVS!;?!Wo(MYJo(MYJo(MYJo(MYJ
+!;?!Wo(MYJo(MYJo(MYJp@@e2b.c$HV7PO\mS0P+b.c$To()MFp@@qJp@@qJp@@nW!:ojSp&OgW
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@nWp@@qJp@@qJp@e(JhTERTd\XP3p?i$.b/Rk?~>
+!quZ5p>u^Xc,I'/eaDSnme6YJ!qu'UrpBgfme6YJ!W_Z^rpC'cme6&Kme6)BrpBj]me6YJ%JK5`
+p?qA!`O*V/UpT!0k(2[bk5JfpUs6ll^#&2Wrq6Hop@eOcp(7;upAY*mpAagds7Z-ds7Z0drq6^!
+p@dqBhS$VAc(t>JqrS6]c,I'/eaDSnme6YJ!qu'UrpC'cmJm7Tme6)BrpBj]me6YJ#km][md:)K
+me6YJ!qu'UrpC6hme6ABma]:``Qb3chYZFBUs6lc`RXD=p?qYRmK3+MpAXI]p&G*lmK3(^pAXI]
+p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p&OgcmLT$Zp?qABmdAWE[)L:c[,1N="3(<6Ujr~>
+!i2>Hp?j`,hSmIYk3hs:s7ZKds7ZKds7ZHms7ZKdrrE)ms7ZKds7ZHms7ZKds7ZKds7ZKds7ZKl
+p'C*Kc,IZYSA!d1mXafrmL3iOC8BD)^!5^5s8Vflrt4u)s7QEms7ZKm!!*'!!<<'!rr3)os8Vfl
+s8M]thT`aYeYHr$CA[E6SDM6(c0"HfpAajdpAajdpAajdpAb*l+TM08pAajdpAajdpAajdpAagd
+pAajdpAajdpAajdpAb-c#k$j"`Pp](^#&YS6(HfN`QdQ5p@eO[s7ZKds7ZKdrr<&ms7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7QHds7ZKds7ZKlp'C*Kc,IZYSA!eQmK5J>Ua^f~>
+!m8N2p?i-Md_``<hX:%,!!)rf!!)fb!!)KY#k$Qh^;A<`]&&#+JaW'r$#+6jS^PNh`np.XpAY-k
+pAY-mp&b<gp&Og[s6^0L`k'1<SS;qTqsFZRd_``<hX9t*rW)EX!!)NZ#k$Qh^;A<`]&*>P#*mWR
+^;f$to^`"^hXUXHp@8LWhT!:HdZqE#p?i$2`l__?~>
+!rqu=p>uRDc+UKte`QMl!!)rb!!)f^!!)KU#j0[N[(X_K[+0`iJ`cLb$Y!j[SB\aS^")Q=pAXIs
+p?qABmJm7\mdBcK!:KO\me-YKme6):pAXIgp?q)2e\/?'`LLCP@f,9lPg-nK^")99mf!4TmJm7V
+mKht*]sPJtPdK!<jp%'p]sPK'k4J*A!8d,D!;>gdk1./P^!2eKeb8,-c1_1-J,~>
+!h?&@p?i*Ke]kePhXgF@!;uNj!<2]k!<2Zr!;?*dp&G*bp'9a)^!5)l^#jn6JaW'rrd-AahTa$a
+k3i9Cs7ZKds8Vfm!<;cms7ZHms7QHm!!)`mpAb0ds7ZKds7YmCc,IraPl?%,mKJj*c+VBYo(N(`
+!VQNlp&b<g!!*#l!s&#p!<2Zo!;6Bmrq6<lp@\aRc+VBPPeH5VmKJj*c+VBYoC`.aq"FXdrq6?m
+pAP'kpAG!kpAP'kp&G*cp'9a)^!5)l^#o%V"#6UA.=_~>
+!liB.p?i0Jd`/l<g?RtrmJm7bmJm7dmf!4cmKN[ZmJuYT!;>j\l3H%_]#N0\]&&#+JaW'r2gKOk
+Oj_+\`np"So(MYJo(MeJp&OgWp@e(N!;>s`p&G*`p@@qNo(MYJo(MM:hT!:HdZJftH2I"7Oj_7\
+`nK_Co^;_Z!U]sdmK3IW!!*#d!s%`h!<2Bg!:BgerpBadq!S1I#MR2/`mU!\hYZ^GOj_7\`nK_C
+p$Me[q!S(\rpBdemf!4cmem.cmf!4cmJm7]mf2PWg;^_DdZM,tp?i$.b/Rk?~>
+!quZ5p?!BR`P&Xle`Q#^k3hC"k3hC"k3h@3k3hC"joFQ3k5G?%k3h@3k3`6;!!)0Lk3hC"k3hC"
+mcNZ^]sPJtMmV>lk(2[bk5KE+Mp8rB^")9>mJm7amKN[ZmJuYT!;>j\jos;K[(X_Brc@u!7>o-u
+[(Y#Pk3hC"k3hC"k3hC"k3`3LjoFQ3k3`6;!!)0LjoFND!:K";!:Bgek3h@3k3hC"k3hC"mcNZ^
+]sPJtMmV@<jrKB!]sPK'k2u*omcNs"mcNs"mcFN3mcNs"mcNs"r;Zugk3`6;rW!#fk3i0J!TrhL
+!#P(cmJu\;mcNs"mcNs*k2t4-[(X_B[,1N="3(<6Ujr~>
+!i2>Hp?hs6ec*MfhYupmp?qYBp?qYBp?qVSp?qYBp&OgS!:KO\!:KO\p?hn\p&G*\p?qYBp?qYQ
+mK_mn]uAi\^#">.JaW'r$%%;WMq-(cc/.m_p&G*ip&Y6fpAP'bpAaOdhT`aYeVed,KDY';K@Tt?
+!8d_C0_Xr.me6)Bme6)BmJu\K!;>jSmJm7\!!)H\!!)Ee!;>g\me-YSme-YSme6)Bme6VI#Nj"=
+`SQ6\hYZ^AK@Tt?!8d_C3;2e6me6)Bme6)B!;>jSme6)Bme6)Bme-YSmJm7\mJu\K!!)H\me-YS
+mJm7\mJu\Kme6)Bme6VI#Nj"=`SQ6\hY-@>3LlloJ,~>
+!m8N2p?i-=d_`T4g?/%m!!)r^&HM+]!:&hL!:&hLlKS?Ll2UhXl3QP+_RdV4Kt?,lmXafrmf%V=
+M9a,P`nKSLmJm7amK*CVmf!4Zmf2DQg;^_DcADOKqsFZBd_`T4g?/"l!s%WO!<)3_!"\>p!:&hL
+!9sOalKSB7l2^hK!!)cY#j0jX]#)mL]&*>P#)1LB]#*1`o]cDVo]cealKS?LlKSB7l2Uh_l3@=S
+l2UhLl2^PC#j0jX]#)mL]&*/K"+A23@=S~>
+!rqu=p>u^/c+UKte_]HFk2-+"!oE(rroO7^k2-+"'EI:P!9WDD!8ci<k2$(<jo>D<k2-+"%Gp7(
+hWE\F]sPJtHaM=Sk(2[bjp?*UH\9;N[(X`@roO4KqrRkYqrRq[k2uXC!TrhIjoFiKk5X9Dc+U3l
+`Ii5YHi)q4Hd072^")!%hWE\ojoXE%hYuXUh>lEp!9W/#h>dQ<!!(m<!!(jU!9WDDhW=h;joPPF
+hYuXHhWE\Ok2+Y%[(X_2[+5'9$@C%2[(Y#Hk2,7WroO:=k2-+"!W_B>roO:=k2-+"%c6=Jk2lXD
+k2$+#jo>D<roOIdk2$(<k2$*proOaJk2,7_hWE\F]sPJtHaM>sjo`m%s."T~>
+!h?&@p?i0<e]kePhX9P(mJuDImJuDG!"A8q!:K";!:K7Tk3`6KmJm7bmJuDJmKr%DhT`aYeUtQt
+JaS*Wna6^JMj/kNc,IZak5P&Smec\X!;lHp!;?*dp&OgSqt:$Xrq6]ek2+(rc/+);Mj4,,#D:RO
+^!5F%k5=WIk5=WOk3`6;mJm7dmM#Zhk3`6;mJuD;mJu\C!:K7Tmd:)QmJuDJmKr%DhT`aYeUtQt
+qsF]Ae]kePhX9P(mJuDImK)GMrU'[Jr9adOmd:)CmK!7S!s%cO!<)?c!<2Bg!9W\LrpBdKqsFdQ
+mbZ4%c..H[k4\3F0r1<gJ,~>
+!liB.p?iTFd`/l<f&G]Oio]7_io]7_io]7s!$pP(!9W;'!9W8@ioU7'ioU7'io]7_io]7_k2PCO
+`k'1<J\']hmXafrmf&%tIF?!D_V4#;lL*s*lL+**mJu\?mdBB.!:K+PmJu\?mcs6.lL*s*lL*Zk
+g;:G<dXD+OqsHn(d`/l<f&G]Oio]7_io]7_io]7_!9W8@!9W;'!9W;'!9W8@io]5#ioU7'iW/!#
+!9W;'io]7_io]C_imu,\`mTFLhYZ_8J^VQL`n'//k2PO_k2PO_k2PO_!93/#k2PO_k2PO_k2HC#
+joFQ'joFQ'!93/#jo>D@k2HC#joFQ'k2PO_k2POcio8P/]#N0L]&*/K"*r&/@=S~>
+!quZ5p>uU,c+UKtc/."DhYI3Rh>dQTh?Eu:h>lEh!<1gT!;51Rc+UKt`I"uKJ`_OGn`C.9K7eNq
+]sPK'ebA2+!;km^!9WDDjoG):$Js=`]sPJtH]*N/qrS-1c+UKtc/."Ch?3i8h>dQTh>dQTh?*c7
+h>mQ3#lri=!8cQ4hVJ8*h?V<=[(XG*[,1]B#CF_/[(X`@eb.c!!;,+M!8cQ4rn[_WhVJ82hZ!TT
+h?*c7h>m6*#L0rh]u>?*hY-(6`W,Y-J,~>
+!i2>Hp?i**hSm1IhYuXMmcNs"mcNs"mcNp;mcNs"mJu\P!#F_b!:JtLk3h@3k3hC"k3hC"k2u*o
+hYtIreT8F\JaS*Wna7olS<SBNc+VBYk2u*omcNs"k3h@3k3hBomcFN3mJuAL!:K";k2u*omcNs:
+jp9hg^!5)SPan!8mKI[g`P'7IroORUk3hC"k3hC"k3i*H,j+OW!9W_3!9W\LmcNp;mcFN3mJm7L
+!9W_3mcNs"mcN["k2-*V"4_J+hYZ^EF5FmL`SUUV(%15Pk3hC"k3hC"!:K";k3hC"k3hC1!"JAY
+!9W_3!9W\LmcNs"qZ%/pjoFQ3k3hC"k3hBomcNC*`<4Y3^#&JN"$)mI.=_~>
+!m8N2p?i--d_`T4f&$&Y!!)rV!<D-V!<;$\!92u<ro*nXp>QA7f###8dWN.XJaS*Wna?C="a/,-
+[_gVhiW&uUiW]DBiW.s<!;>CWhW!,'[_g=4rfR*G#'JA2]#*%To]#`Jro*nXro+"[io0t;iX#VE
+iW.ut!!)!Yp>QA7f###8dWN.XqsFZ2d_`T4f&$&Y!!)cQr;clW!!*#X!s%??!<(pS!<;$Y!;>CX
+hU]QT_U<S<hY-@>IE'E<J,~>
+!rqu=p?!</c*Xjkc.1\$hUUK5hUUK5hUUH_hUUK5h>lF0!$0VH!8c6+e_\gVe_\j5e_\j5e^`O,
+c+UKkc"aW9J`_OGn`Kh/"`qYrXM)mXh>l+*h@\;phUMV_hUUK>eH"I_!8[\Urn[b-hVQf^hZ)+1
+hT`a8]u>'lMu2WMC<a,m^!5*ae_\j5e_\j5e_\j5qZ&.shUMVVhUMVVh>lE_h>lE_!7fp+!7_)"
+hUUK5hUUK5e_\j$]sP/kC:)OgjrS9^['[Nke_\j5e_\j5e_\j5e_U;_e_\j5e_\j5eboIWhUMVV
+hUMVVh>lE_hUVK'(>dRAe_\j5e_\j5e^`O,c+UKkc"aW9p>uJ%pA^Y5~>
+!h?&@p?i**e]kePhXfk0!;ts]!9O7]qrRt\k2l[Cjo>DSjp0bf^!5)K^#jn6JaW'rrhKR0hYtJA
+hWF7gmcNs"mdB6*!!)0LmcFKLmcFN;jo>DLk3h["mcNs"mcNZgrl"opCAt%+mKI[^c+VBYoB$#Q
+rT4([roO1\roO:_k2l[CjoYVGjoGDCrW)WR#N!_=c.-mKk54QMF4JOKc//'SrrDlW!!*#\!s%KG
+!<2*_!9WDDrT=+[qrRkYp#ZM9c+VBPF1p`0mK52>S1/s~>
+!liB.p?k.^d`/l8f&#9ChW!DOhW!DOhW!AlhW!DOh>lC4!92kphW!AlhVnOphVnOphW!DOhW!DO
+iniPC_Rdb8D7\STmXafrmf&a]C!sl0_UdT<ir9#Wir9#YiWK8@iW&uQir@j=f###8dV8]OqsH(R
+d`/l8f&#9ChW!DOhW!DOhW!AlhW!DO!92kp!92kp!92i8hW!AlhVnOphW"M7'B7m.hW!DOhW!PO
+hU]QT`mS_8hYZ_8D:6G8_UdT#ini\Oini\Oini\O!!)$8ini\Oina[lina[liW.upiW.up!8c_l
+iW&u8ini\OiW.upini\Oini\ShVQi#]#N08]&*/K"*r&/@=S~>
+!quZ5p?"SS`P&Xlc/."-e_\j5e_\j5e_\gVe_\j5eH","!8c8_e_\gVe_U;_e_U;_e_\j5e_\j5
+hUUK-]r\olC:)iKk(2[bjpR]DS79aV[(X`7hUVV^(tIL"e_U9+e_]05!!(m+!8c6+!8c8_hUVV^
+!S-'+eH`dp^!1#VPaqX5/o&A=[(X`@e_\j5e_\j5e_\j5eH".Ve_U;_e_U;_e_U;_eH".VeH".V
+!8c8_rW!Vge_\j5e_\j5hUUK-]r\olC:)jpk"TU0]sPJthUUK5hUUK5hUUK5hUMT+hUUK5hUUK5
+!7frV!7fp+hUUH_hUMVVhUUH_!7frVhUUH_hUUK5hUUK5hVQf>c+U3lc"aWBp>uIrs7W7=~>
+!i2>Hp?hrjec*PfhDjZSk2,7Wk2,7Wk2,5#k2,7WjoFQ#!8ckpk2,5#k2$*pjo>D<k2,7Wk2,7W
+hWE\O`P'7I@_LWLmXafrmL$&&XCB`)]uAOahYuX>hWEtWroOdmk2tO_!9W/#!8cl#!!)0DhYuXH
+hWEtWk2+(jc.-:)[&j/m!FjUY`W+dYk2,7Wk2,7Wk2,7WjoFQ#k2$(<k2$*pjo>D<joFQ#!!)0<
+!8ckp!!)0<k2,7Wk2,7WhWE\O`P'7I@_LXqmK$eIrl+oo7crRihWE\WhWE\WhWEYp!9W/#h>lEp
+!9W/#!9W,<hWEYphW=e<hWE\W!9W/#hWEYphWE\WhWE\WhVRDOhSm1IhI=1Tp?i#CS>7Ta~>
+!m8N2p?i,nd_`T0f%U,[2;6p@hV-i?hV-fdhV-i?h>lEd!8?;`hV-fdhV%t`h>dQ0hV-i?hV-i?
+hVQu;^:M20@Ck<HmXafrmf'3j@Eu`u_U@03h>dQSh>dQTh>dQThZ!TNhZ):5d_`H0c=-^PqsFYs
+d_`T0f%U,[45/QFhV-i?hV-fdhV-i?!!(m0!8?90!8?90hV%r0hV%t`hV%r0hV-i?hV-i?hV-iC
+g=F!L_U;l(hYZ^F@FE$(^=M$;hF$#Rg>:Q?g>:Q?g&M-0g>:N`g>2hdg>2hdg&Tj`g&Tj`!!(a0
+g>2hdg>:Q?g&Tj`g>:Q?g>:Q?hV-Pp]#)m(]&*/K"+A23@=S~>
+!rqu=p>uQ_c+UKkc-?7<29j[re]lXhe]lVEe]lXheH".E!6s'=e]lVEe]e*=eGoToe]lXhe]lXh
+e^_ph['[Nk>-uh2k(2[bk5M.[@`?$^^!66#!!)uJ!!*#K!!*#KrrDiE#L1fD]r\od@fE2#jp##6
+]sP/kc2Q6Tc.1(hc.1(hc.)gEc.1&=!7f<oc.)doc.)gEbl@aoblH#=bl@aoc.1(hc.1(hc.1@h
+c*Xjkc!%L)qrS)dc+UKkc-?7<6d=0+e]lXhe]lXh!!(Qoe]e*=eH".EeH".E!6s'=!6s$o!6s'=
+eH".Ee]lXh!6s'=e]lXhe]lXpc-<W&^!0`feb8,-c1_1-J,~>
+!h?&@p?ir1e]kePhWE\WhWE\WhWE\WhWEYphWE\Wh>lEphYdEWk2$*pk5>8ohWE\WhWE\WhWEtW
+k2+@rc.-::k(2rOmd]]O`P'5ohTa$YhVS7o!8dV8!T)u;!!MH@k2l[CjoO<=r8n"9rT=.:s2>/d
+hHIn3`V]'C@b&`:c/.U>k2,7Wk2,7Wk2,5#!8ckpk2$*pk5>8]hWE\n!$14YjoFQ#jo>D<k2,7W
+k2,7Wk2tO_hT`aYeRH5SqsG2.e]kePhWE\WhWE\WhWE\WhWE\WhY[?ThWE\l!!q]ek2,5#k2,8!
+!!1s=r;[VijoFQ#k2,7Wk2,7_hWE\>^!5):^#o%V"#6UA.=_~>
+!liB.p?ir,d`/l8db<F3g>:Q?g>:Q?g>:N`g>:Q?g&Tj`gAM!ShV%t`hYdEgg>:Q?g>:Q?g>:]?
+g=!jL`mS/(hLY*Gmd]`E\e8/s`kK=@g>:Q?g>:Q?hV-i?hYdEmhV-i?!8cGdg&Tj`hV-i?hV-iC
+g=F-T`n";l])1n8?.-a(_U@/lhV-i?hV-i?hV-fd!8?;`hV%t`hYdEUg>:Q^!$0qMh>lEdh>dQ0
+hV-i?hV-i?hVQu?d_`T8dTsH@qsG2)d`/l8db<F3g>:Q?g>:Q?g>:Q?gACpPg>:Q\!!qE]hV-fd
+hV-ib!!1g1r;[Veh>lEdhV-i?hV-iCg=jul]#N0(]&*/K"*r&/@=S~>
+!quZ5p>uN^c+UKtc1BHc!;t@I!<1OI!<:RN!7fWu!;+eHc+UKtc!%L2J`_OGn`KhX"]EUY[(X`V
+eboLHeGoUJeGoUCeHO42[(X^^rj;Rb"^90a[(X`Vec,XIeH,a$eboLIeboLIeGoUKec,XAeHa@4
+[(X^f[,1]B"^90a[(X`SebfFHeb]=IeH#U!!!*#Kr;clJr;clJ!!)]B#L0rh^!0`fhY-(6`W,Y-
+J,~>
+!i2>Hp?k.ChTa$YhVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7Wk2,7Wk2,7W
+hWE\O`Pp*Y;SCq<mXafrmPi,0`DYRC`QcrqhWE\WhWE\Ok2,7Wk2+tWhWE\WhVRDOk2,7WhWE\W
+hWE\Ok1._qe_X3Cc,KSJ78i!e`Pp]jk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7WjoFQ#k2,7W
+k2,7W!8ckpk2,7Wk2,7WhWE\O`Pp*Y;SCramS-U9c,IZYhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOhSmIYhGV&Dp?i#CS>7Ta~>
+!m8N2p?i)af#GG@dbrgZ!:ebJf##/@elB<<JaS*Wna6\"`kkR'b.bmDgY)q]`kKUH:r:5hqsFVf
+f#GG@dd#Nd!;kIM!;G1I!;"nLf##/@elB<<qsFVff#GG@d_XWBf##/@elB<<p?i$2`l__?~>
+!rqu=p?"S;c+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]e*=e]lXhe]lXhe]lXh
+c.1(`]sPJt;RFu*k(2[bk5N%K9$P>^^!5*Pe]lXhe]l@hc.1(hc-=e`e]lXhc.1(hc.1(`e]lXh
+e]l@hc+UL'bt@uKqrU=Fc+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXh!6s'=e]lVEe]lXhe]lXh
+e]e*=e]lXhe]lXhe]l@hc-<r/^!0H^ebeK';U)n^^!4gPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(`e]l@P[(X^^[+4m4"3pQ>S:C~>
+!h?&@p?i)^hUTTiec+\;hWE\WhWE\WhWFS5,NdkFhWE\WhWE\W!9W/#hWE\WhWE\WhWEtWk2+A%
+e_X3;k(2rOmd]`FeI^S0hUTlqhVRDOk2,7Wk2tOp!#j_Vk2,7Wk2,7_hWE\WhWEtWhTa<qk"=1S
+hYZ^E;VosCc.2gU$/Xh$k2,7Wk2,7q!%I%1k2,7Wk2$*pk2,7Wk2,7WjoFQ#k2,7Wk2,7Wk2tO_
+hTa$ihGV&LqsFVchUTTiec+\;hWE\WhWE\WhWFP40](sKk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7_hWE\>`RWgC^#o%V"#6UA.=_~>
+!liB.p?iPef$;.Pdb`^7g>:Q?g>:Q?g>;T),Mq/2g>:Q?g>:Q?!8cGdg>:Q?g>:Q?g>:]?hU]]`
+cIP\#hLY*Gmd]]Xda$93g<R^Xf%T!7hV-i?hVQu\!#jSJhV-i?hV-iCg>:Q?g>:]?f#G_Tg.9Z;
+deiGF9\.M+`mW_thV-i?hV-i?hV-i]!%Hb)hV-i?hV%t`hV-i?hV-i?h>lEdhV-i?hV-i?hVQuC
+f#GSPekE[3qsG(jf$;.Pdb`^7g>:Q?g>:Q?g>;Q(0\YC;hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-iCg>:E#_Tp_+]&*/K"*r&/@=S~>
+!quZ5p>uNNc,IB0c1KQ]!;=qC!:eSEc+UL'bt>A"J`_OGn`C/&`Q^^!`P&t0c1oi`!:JD;]`lC*
+6-[BnqrS&Sc,IB0c1KQ]!!1UMqpbZHpXK6Do@4)j]sPc'9!mIPjonB%`P&t0o[W[9f[U5O]sPc'
+9!mIKjo`U&p8!3~>
+!i2>Hp?i5QhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9k5='9k5='9k5F-Ck2+t>c.1Z:^#">.
+JaW'rrn[fVc/-^iec">)k54!8k54!8k54!8k54!8k5F-@k2+Y5hT\sthYZ^I6/L/:`STJ6hWFgo
+!9X49!9X49!9X49!9X49!9X49!9X49!9X49!9X7:$0L+$c-=eq6+u.PmKl29e]l(ihWE\Wrn[Y;
+r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9qq_YAhVQN%e_WU*hY-@>3LlloJ,~>
+!m8N2p?i/Rf$;:Pdb<R,g'QWif#l"Xg-iO/JaS*Wna?G2#1cVnf#l"Xh:hnc#hI;Df#gh?g=lGl
+#=R.g`kp0XhTaa\hV-Q'`m3:+]&*>P#=R.g`kp0XhSn1ThV-Q'`m3:+]&*/K"+A23@=S~>
+!rqu=p?"S*c,IB0c-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+c.1(`]tMD86+#0nk(2[bjos#[bt>t"rl+o^/Ci"qc.1(`e]lXhe]l@hc.1(hc-=e`e]lXhc.1(h
+c.1(he]l(Pc,E<"e]n!R77#2;]tM\8e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhc.1(`]tMD86+#2>k"S.d`P&t0c.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc-=e`c+Ug0eNpRmp>uJ%pA^Y5~>
+!h?&@p?i/hc/-^qe_]0\joF99joF99joF99joF99joF99joF99joF98jp0bne_\PK^#jn6JaW'r
+$23fTF0sf\c.1\MjoF98joF98joF98joF98joF9;jpLP=k1/>FZubs/pA=7_>0YpKe^`O5r8n"9
+r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9qrS.?e^`O$;SD5imKZq?hTaU$hVS1m!8dY9!8dY9
+!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dP6#N""]hT\s3k4\3F0r1<gJ,~>
+!liB.p?j_:b1=_Xdb<F3g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q_
+h?`,pcHb"`9Y0)3mXafrmPjFnl><iXf#lFlhV-i?hV-iCg>:Q?g>:]?hV-i?hVQuCg>:Q?hV-i?
+hV-iGini,7f!9/Xk3Dj33E=5Qb0&/dg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q_h?`,pcHb"`9Y0*XmQjjqf#l.`g=kE;hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?rn[q?g<S!pb"TD'p?i$.b/Rk?~>
+!quZ5p>uNV`QcB@c-XuHhTa<ac,E;^hLXg?k4%L=hWARSc-=5Pc/."Nh>l+*blb%^k2,ss"]E=a
+`Pp*EeHk$Vc,IrH9!mIPjonZ%c,IZH_USqKc-=5P`CdMop>uIrs7W7=~>
+!i2>Hp?i0,XPVgae_]0\joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF99joOo4
+rn[aY@_LoTmXafrmf*4f`DY7bh>m!CjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjpLP=k3hs2
+k2t2l`W#o7mK[g7hVQf5hVS1m!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!Uf+Lh?0ig^#o4[#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX<mcON*"0>tFk4\3F3LlloJ,~>
+!m8N2p?i0*WnPnHcIU_KhDEsCg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+io9+Wf$`9T?+SmDmXafrmPjk9qS#YKg=F^#ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\SmcrZcdSR[SqY'gS#B?ctda$.hgA]qig>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?io9+Wf$`9T?+SnimK[a3g="9lf%U,[6JC;MhV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hW!PWhU^-/Y$JWqp?i$2`l__?~>
+!rqu=p>uU$Ut*`/`QcZWec+D1e]l@hUft.^J`_OGn`KiE"11\>ec*fChUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK>k2t4Nbt>ABpA<tWF/7@2`Pp*HcIMpN#M%)DeYHBUhYZF?F/7@2
+`Pp*H`mt(F#M%)DeYHBUhY-(6c1_1-J,~>
+!h?&@p?i!q;U,3t!nH/aeE.)*p?q)*eP_=EhLY*Gmd]]FpAY'oPY/%-gti7tp@d@M8sK>T!;?<X
+!khLVrn[_,hVQQ?$1@NTk2t2lMoFQMmK1("c2QQ$e_]0&jpCJLmcNZ^;N&NNp?i#;Umrla~>
+!liB.p?i3t9Zkr;daH_#eD:MkmcNB_c:ir+hLY*Gmd]]Fo)AYBO[Q%kf%S^/f%S^/f%S^/f%S^/
+f%S^/f%S^/f%S^/f%S^/f%S^/f&#iceuhQ+rr2uhqsFa$9Zkr;daH_#cJAlemcNB_c:ir+hYZ^H
+\kL8tf$`!tg;_tUipPschTefK^>ASO"*r&/@=S~>
+!quZ5p>uF`9#^eS!l`F/eC=l^k2+Y=`CbcreUck6k4.R6mf*5>Ma<lPc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1tEc(msirr2udqrRse9#^eS!l`F/cIE6Xk2+Y=`CbcrebeJ1
+ZqA=:blYl/c,S9?hWE\Fe\t.5^")i="3(<6Ujr~>
+!i2>Hp?i.YMb:)$hWFgo.H]LLhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\o
+jp1>:hR#mi[*=0iJaW$q!;?Bk/^8W.0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+
+0ek+36$(<LrrDcimKWBC9!$S"k5O3jk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7WroOIRk2*I;C:)7^mKWBC9!$S"k5O3rk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WroOIRk2*I;C:)7YmK5J>Ua^f~>
+!m8N2p?i1VNC9Vgf%S^)g&U"/iWdu:885BPk(2rOmd]]Go(r@c/]Mcm/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1`2#4E8C?rrMueqsF^[NC9Vgf%S^#g&U"/iWdu:885BPk54QO
+nr6&6cIU_#`nCFLro+.5Y"394b3&Ec"+A23@=S~>
+!rqu=p?"1!Mb9eac.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1)<
+ec4J0c(ms@XMobQJ`cIa!Uf[\rrTlT3S>h_3HMn5rrMi]qrTp,Mb9eac.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8nh?D0"8n+m@qW:*3Mb9eac.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc2Q8n
+h?D0"8n+m@p#ZA$pA^Y5~>
+!h?&@p$N%X]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=@"s"OXS
+K=&>KJaS*Wn*U2Lc2Re;q<eI\]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=F$s"OXSK=&>Kq<eI\]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=F$s"OXSK=&>Kp$Mo:Umrla~>
+!liB.p$P$7[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbp
+/1<&+<J@`mg?O7WJaW$q!V6*5rrMueq<gZA[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&XqX.&J[Uh9H-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n$Vp/2U@\ZG,&Xp?i$.
+b/Rk?~>
+!quZ5p#ZAEZskc7.0VG(K<2c:J`_OGn)aZ=p<Wa>p?qb="7EO*0uk^H0iEY*^")r@"7EO*0u#.@
+0iEY*^")f<"3(<6Ujr~>
+!i2>Hp?qqR"7G<r`Qc(!`QdQ5p4;X_md]`Ep<Wd<pA=:Wp&jaFc,I`:"NAXJme6PGrq6H^k0:l[
+]`c=!k3hs:mK5J>Ua^f~>
+!m8N2p?i.UmdfZ"b/2E7"N&=<lLKMoJaW'r"7kmNqU,<FqXX(FqsF[ZmdfZ"b/231"N&=<lLOi?
+#4h3QlJB\#^UaQbb22FSp?i$2`l__?~>
+!rqu=p?)AB4QbM>]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd
+[(Wi[[(XH8k3df_J`cLbrpBd[dJj4?rpK[GrpE,8hSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd[(Wi[[(XH8k3i-/rpED@hSm18]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd[(Wi[[(XH8k3hs*
+"3pQ>S:C~>
+!h?&@p$P!:me6):hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\O
+k2,7Wk2,Oop4;X_mdKQGp?qYJe,TIA!Uf[WmR-^9p?qA*k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WhWE\WhWE\_me6JE9D7fImdArohWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Ok2,7Wk2,Oop@[hU
+0r1<gJ,~>
+!liB.p$MtRmdBB&bME9^l@JASmdBKHo'Z)>qYJhDs8)cd!UfOSmKE+KmcrrRh>ud(q!J:UmdBB&
+^"rePlLaKHH-4-8J,~>
+!quZ5p#\F*k3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,
+hUUK5hUUcNmXaMOk3qF9mcNs*p@d,<s7ZK\!TrhGk!SS!mcNZ^hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5e_\j5e_\j=k3i'-9CCs1k2t4Ne_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,hUUK5hUUcN
+me,]E`W,Y-J,~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+!h?&@JaS*WJaS*W_sRU]Umrla~>
+!liB.JaS*WJaS*W_sRVPb/Rk?~>
+!quZ5J`_OGJ`_OG_r_'?s7W7=~>
+!i2>HJaS*WJaS*W_sRUeS>7Ta~>
+!m8N2JaS*WJaS*W_sRVT`l__?~>
+!rqu=J`_OGJ`_OG_r_'GpA^Y5~>
+"JhPs@VYmOrFu=Arb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrG)=@"DVDAS2#N~>
+!QrFYV1GXtWe%1$Wm7XAV#nfZ@=S~>
+"98)gmf)n[mXb(_p4;pgp<*(4me6ASp8!3~>
+!M#taF8]hRF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fqQ@KN'q.=_~>
+!QN:\Xok],WiCQOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)Wii@OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)J$,fSWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)Wdh1OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,X1YWiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)ri5pn!liAkJ,~>
+!quZ^rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq?B[#PRTZme6ASS:C~>
+"f.Z'@VTZVEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEs-6!F)#Ih@KN?q.=_~>
+"Nn`\V5f*LJZaR,JZd+ts/Q'p!m8MkJ,~>
+!<7WDJbFZgJbHqR"7H3_Ujr~>
+$(Reh>$>BEC1:Y%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peIqiG-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@Xi-%C1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1;[-@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@5C1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:Xe@U`MES>7Ta~>
+$-(,YTqS<ZWhlPAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lJ#]?FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV15MAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhk3FV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5g@QWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhlPlV4jHR`l__?~>
+$24Dep?qYBp?q?up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBJ+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmXOrup?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?mG(me6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6'0p?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qABme6)BpA^Y5~>
+"/MGb;Z0f!@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO=@TlrE>%1Z=;P]g;J,~>
+!QrF\SUmJcTn/ngTuiu4V4F<Nb/Rk?~>
+#QOMkme6)BmeuhZmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mec\]me6)Kp8!3~>
+!M#tb8d&$a;G'Q2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8q0`2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G)F:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8<;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'PZ9)_]iS>7Ta~>
+"NJTLR?`>kJXM(WJXOQH"eD'P`l__?~>
+!VZQmmJutZmJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mK<1Nme6YJs7QKnS:C~>
+$)F)eS>;[NS>;s1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NJ"3=)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUjno1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>:Y)Un"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"5AS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;sNUn"6NUmrla~>
+$-L91`lc<D`lcGR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<DJ&]XNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb(%FR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`l`eNb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VRb`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lcHDb/VTDb/Rk?~>
+$30`!pAajdpAb/BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds*sbBpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpA]X9s7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZIRpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0ds7ZKds7W7=~>
+JLQ.!JLQ.!]IA@~>
+JRO+<JRO+<]O?<~>
+$(Rf]Un"6NUn!s)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NJ#&U1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS:@?)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUmuq1S>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;Z9Un"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn!sNS>;[NS>;[*~>
+%%EndData
+showpage
+%%Trailer
+end
+%%EOF
diff --git a/doc/kmouth/kmouthcwcp.png b/doc/kmouth/kmouthcwcp.png
new file mode 100644
index 0000000..6462763
--- /dev/null
+++ b/doc/kmouth/kmouthcwcp.png
Binary files differ
diff --git a/doc/kmouth/kmouthedit.eps b/doc/kmouth/kmouthedit.eps
new file mode 100644
index 0000000..ef2e964
--- /dev/null
+++ b/doc/kmouth/kmouthedit.eps
@@ -0,0 +1,2637 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: GIMP PostScript file plugin V 1.15 by Peter Kirchgessner
+%%Title: /local/src/kde32/kdeaccessibility/doc/kmouth/kmouthedit.eps
+%%CreationDate: Sun May 30 14:51:52 2004
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%Pages: 1
+%%BoundingBox: 14 14 344 420
+%%EndComments
+%%BeginProlog
+% Use own dictionary to avoid conflicts
+10 dict begin
+%%EndProlog
+%%Page: 1 1
+% Translate for offset
+14.173228 14.173228 translate
+% Translate to begin of first scanline
+0.000000 405.091101 translate
+329.074005 -405.091101 scale
+% Image geometry
+329 405 8
+% Transformation matrix
+[ 329 0 0 405 0 0 ]
+% Strings to hold RGB-samples per scanline
+/rstr 329 string def
+/gstr 329 string def
+/bstr 329 string def
+{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
+true 3
+%%BeginData: 154710 ASCII Bytes
+colorimage
+JcC<$\Gq'~>
+JcC<$\Gq'~>
+JcC<$\Gq'~>
+JcC<$\Gq'~>
+JcC<$\Gq'~>
+JcC<$\Gq'~>
+g]%?3[%r82[Yk6PXMsn;s*t~>
+g]%NDd`T;<]"Yn.]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi8\2XI^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%qcJJE%s*t~>
+f`)*Js7ZKmJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds$l_^pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdp9"@F~>
+h>[fLUk=SXMh?q?K7Af3Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh=W[K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?Mp8O,J,~>
+h>[NHb(7..\cKP)Z2]=~>
+g])iuYP,4#J,~>
+hZ!r-Mh?q?Mh?q?Mi3(;Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?p]K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YAXm^)qD~>
+hZ!W5^4Ekt\cKtEZi>O~>
+h#@EKs8M]os7Z0drq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6EnpAb-c!WVkus*t~>
+q>UNQ[&!)I"-iNZ]n(g9K*.&"s3:P$!/&=M".Z13pA"Z<~>
+q>Vc+d`T;<]"Yni^:M%i^:M%i^:M%i^:M2Ts44ci]!f2Y]!f2Y[XYls]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!bJI[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^ro]pAa-`\j*p?^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M>,iqE0IJ,~>
+pAYj#s7ZKmpAajdpAajdpAajdpAaj[rr7QCWV6>krUr>QpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAaj[s*t~>
+qu7W'Uk=SXMh?q?K8YA?K8YA?K8YA?K8YA?ec4KWK;aDkSH&VRMh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?MoG\q!58@2J,~>
+qu6]fb3QVL^?5I\]!f2Y]!f2Y]!f2]J$uqs]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y\l6&K[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roes8TgE]"Z+o
+!P[FirrCdOs*t~>
+q>]aRrr<#l!<<&l!<<&l"98)gs8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8;Qjs8M]ms7ZHlrq6?l_tNm*J,~>
+r;Rb]Mh?q?Mh?q?Mi34GK8YA?K8YA?K8YA?MuWg8JU=;A8^7:[H\6s/K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8ZQ!s8S>_s*t~>
+r;QfS^?W9?^An5IZF7'IZF7'IZF7'EJ$uYkZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZ;\3;[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?Iir@l@]!fJe
+"NpH<s2+d8J,~>
+qYpTis8M]os7Z0drq6?lrq6?lrq6?lrq?BlJbGu7rr3)gp@eOcp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lpAY'lpAY)B~>
+rVlr4K7!QL"+,[%hZ!3Lc(t>k!.4Wr"FIi^eT:_:!-A-d!-A$a!-A-d!-A-d!-A&<s*FcfHi*jE
+HZT15!HWVbrrdCis8R0>HN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHNA27qu6Y;rd+Wdrd+Wd
+rd+Wdrd+chs8RFerd+Wdrd+Wdrd+unHiO+eH[GemH[Gbls*ObF!IJneHN8-dHN8-dHN8-dHN\D:
+HiO-FHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-bHN8-dHNeJ;MuVpdrIYZ.
+K?a,ipAajdpAajdpAaj2rdto3K7hGBs7ZKds7ZKds7ZKdc%CXqrdt^*pAajdpAajdpAajdp<ESh
+#)i3Ts%<=kJ,~>
+rVm5U]!f2Y[^roYcKbE&%c5LB[^roY[^roY[atK@l*C3erNc>$qQg"us0D\)hm3.Zn?W)oo!8;q
+rj)S(s0DY(s0DY(mBZclcE^-Xs73>$]!f2Y]&*/WpA4LZpA4LZpA4L>]!f2Y]!gJhqY'dZqY'dZ
+qY'dZhR^/(]!f3,pA4LZpA4LZpA4LZp>3Bh]"7V8s-<WaJ,~>
+r;ZTdqZ$<`rr;6VquH]hquHTequ?]is8V!Mqu?0Zs8VZ`s8W)ls8W,mrr<#lrr;BZs8U@;s8N)e
+qtBU\qtBU\qtBU\rV$6j!q-*gJ,~>
+rr3GXK6r5tK7eNHc0kW*mf)>W`M@j5H\6ZtH\9TCV!<"$!;ulq!;uis!;gj;s8N)urr[?BrrCtu
+s8W*!rr;M0s8N'!o5js3"or`Err<%?rr3!!F8l1>!:k42s8R0?rr<&EErk_/rd+s(H\6\-s7ZKd
+pAOFWjpQNgH\6Ztk5Y/Tp@eIQr8nB6K7eN'HfkA%s7Z0bmel2RH\6ZtPlLcs3WFU~>
+rr2u\qR-RIhX:72mf)JPg;`rs)<1\=ZECL9ZECL9ZECL9Y-P49Y-P49Y-P5#!"#s6ZECL9s8N'!
+rr4CLs8N)%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9s8N'!rr4FMZECL9ZECL9ZECL9
+ZECM5rrB@-ZECL9ZECL9ZECL9s8N)%s8N'!ZMsk)!3Z>$9`VK%ZECL9ZECL9ZECL9ZN's-ZN'q)
+ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECM(s0As.[LVTr
+pAb!_o()5:lK[NslMJ""lLsrOqY'LNmdBB*k3D7/[LVTrpAb!_o()5:lK[NslM\-p_Z0YeM>r)~>
+rVuWc!<<#k!:KUTs8W&k!:Kj[!:Kj["7GmVmf)n[mf)n[mdU;Vp'0sYpAb-m!<3!&pAb-mp@dqR
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p'0sYpAb-m!<3#up&OO[p&OO[p&OO[p&sgWs8N)up&OO[
+p&OO[p'^<^pAb-mpAb-m!;?El!<DQerr<&up&OO[p&OO[p&OO[pAb0mpAb-o!;>j[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OOYp&OO[p&OO[pAb-np?qhOr;Qfks8DWmme6)FpAFpk
+pAb*b!q,dMqY'je!VZQlp&a[UmeleXrrM9^J,~>
+rr2tVqg/aAhWFP3s7YmCk2+XQqKiD>s+>B6CAr8SCAr8VC3+H2rc8'Src8-UErbh3!s!C`CAr;S
+rsAaICB+;6s8N(?CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr;SrrrIECB+;6CAr8SCAr8S
+CAr8[C3+Irrr@-?s8I'>CAr8SCAr;SrrrK'rr<%?CB"56!-A/>!s!C`CAr8SCAr8SCAr8[CB+;6
+CB+;6CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8UC3+.hEr]tSEs-7.s-.U&
+HNVg\me6SYs7ZHS!S)8hHNVg\me6SYs7ZHS!S)8hHNVg\me6SYs7ZHS!S)8iHN_Uns#L+0~>
+rr4"QZF7'IZEh@(lLt8Xo'Yf.inhPX[^*?I[^,W,]'?Hu!<<)p!<<*!!;ir!rs/V-Y5eM%s8N)W
+Y5eM*!3WL)rrDVms8N0$Y5eOqY5eM+!<<'!!3WL(rrE,&rr2runui#m"9>V)rrC?I%Hd]-Wj]4A
+ZF8WTme6\Zq@NAklK[NgZEgpE[^+cTme6\Zq??T`lK[Ngriud;ZF8WTme6\Zq@E;jlK[NgZEgpE
+[c7>eM>r)~>
+rr;ff!Uf[[s8M`lmeQSUs6B=X!<<)p!<<*!!;lKirs/VupAb-ms8N)WpAb-r!;?-drrDW`s8N0$
+pAb0dpAb-s!<<'!!;?-crrE,nrr2ruo(N+`"9A/qrrC@<rr2u\r:U0ZpA"[fpAXLXp&XUTq#CBf
+rpK^X!Uf[Vs8VflmeukYrrM9^J,~>
+s8N,MF8gLjF*i88hX9h2rsA,UhWE@iHZOOTrd4\Fl"U;#s'f1-rrZ_6rrDq2s8N6&C23eK!;uls
+CAn/4CAn22CB"84CAn20CB+;<!,?9Krr?g3s8Qj3s8Qj6rr`?%rr<&nCAn24!<-a4rrE+7rr3!!
+CAe,3CB+>6CA\#2CAe+YC';6MS9&cNHNeK(k2u+*r;QcbroO6p@fC]YF*kU_k3hs@rrDKdjpSk3
+H[Bg\HbJS(me6SY!:KjK$GBnqF*i7ls8T/\J,~>
+s8N)]qQ^4ChX9t6q??<Pk3Cg?qQg/$)lg'@Y,\Y)Y,\Y)Y,\M)WiiA)WiiA)WW3$)=o&(0?!..-
+Y,\Y)Y,_O%!334%rrDus!NN=$rrB(trr]F(Y,_L$!iiE'rVmA1WiiA)WrN)!WilC%!3Z8"!NrI#
+rt;?7s8N*!rr<&%WiiA)WiiA)Wr;tt!!9='Y5\G%!36%u!<B;#rroR*s8T7%qu6Z!r;SXWWiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)f)NadY5PX:b3J9[qZ$El
+qYKdJk2sg[r3?jUlK[g6s8)clqXWq6k/sCqZ4G+ClL+NKqZ$Ego'5B"b+\d>"MXp9c@LK~>
+rr;ig"6T%FpAY*lp&jaVk2uO6s8W,m)=I4dp?qYBp?qYBme6)Bme6)Bme6&K!+K.-rt/^D!!)`\
+p?qYBs8N)epAb-mr;QfcpAP!kmf!.fp?qYBrr3&fp?qnZ%ef>ame6)KrrDK\s8N)mr;Qfkmem(t
+me6\\!<<'!!;>jSme6)Bme6)Is8N'#p?qYRrrE,frr3!!pAFpop?qt\p?qhX!;??j2>6J3me6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6\\p?(fAp&NYBpA=mip&jaV
+hVS2(!7h)Bqu?]i"7Gm>hYd'Iec,:>s8Vcpme5MorV$3i!7cT~>
+s8N(pqf;mm^#nJNrVm&hhVRD.KDT`irrHkDrb;FBrb;FBqe?+?rb;FBrb;UG!<<(&>5eL$>6"U(
+!,?!BC'e?as8N(6CB+;6qu6Y*qu?Zrs8NOC@fQH.s8QhKrr<'!s8Ha6@VYi@#&4,<CB+;6rr3(8
+s8N)urr?O,s8N'"C1@0W!+PqB!FfgBrr`=:@VTZVrr?g5rr`=2s8N)ursNTArr?g6rrE*!!!)or
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBr+Z4@rb;XHC20"5c"d/t!3H1^!;??j
+"npg8k,`%iEr`<@jpUn_rr<'!p>4roXCD*K!3H1^rrE#trrE)]!N]c.Es(k1p*kL~>
+s8N)AqlUC6`ocRWqZ$Ecmc*6k`qlk<s6-K_!!<1'=oJC#=T\U'!;`_qrriD&WrN)!qu6Yrqu?Zr
+s8W,!s8NB*s8T+!rr<'!s88nprs#J'!36)!!<3!#WrN)!rr2turVultp8\)k!!)ttrVlktrr3*$
+WrN)!rr3A+s8N)!s8N*!rr<&rs3[hK_Z/Vdr2p%2roOU^qZ$ElqXWY.k.6iUXoQ'4jpUnZrr<&q
+o&Afo\s<2r!4r0lrr<B*qZ$Bl!9WFTQ2IcepAai#J,~>
+s8W&k#4D3Ymb[[2r;QromdBf*k5=oSmf3=NpAY*os&rV)s8Q7(rr<&qpAb-r!;?-drrDrr!;?<i
+rrE*!s7ZKm#lt#*p@eLd!<<)spAFppp&G*ds8N)urr_uprrE&u!;?BkrrDcdrVlitrV$3i!;?El
+"9A/qrrE&u$hjW#!;?Hm!<<'!!;lfDpAY'lhZ!3Pme53)p?qeW%IWrXc.2O]me6A)p@dqRs8N*!
+rs%obm`j;Umf)n`eb8_)!!)utrr</pm`j;\p&OO[rrB-N~>
+s8NX_C3+-2C3,$PhWF8+pAaj[rn[t#HYRV:F)#drs6*nl!<)p"@Tm5ErVlitqI9@%rrE*!rrE*!
+!W`9#quH`r!<?U.rrQX0!;lcr!<$C,s8E#urrlm3rr<%.rVult"(M<1!<)ot!<$C*s8?F,rrN3#
+s8?F,ru_=As'l$.!<<'!!+Q!.!<<'!@fQH.s8N(.s8N'!s8N)I@O%uSS765SC3+-Jk1/>Vs7ZKd
+s6eaok)3DaC3+-2MrrRHmf34c%dr3(k)3DaF)#c2MrrRHrW!!!pAP%#e`McnF)#c2F3Xab0n9~>
+%KH:9WiiA)Wii2Lk2u76q@<5iio9+GTrP8qY,\Z)s6-<Y!<<'&?!1H9s8W&uqPF)hrrE*!rrE*!
+!W`9#quH`r!<AtqrrT"s!;lcr!<&bos8E#urro8!rr<%qrVult"/Z%t!<)ot!<&bms8AeorrN3#
+s8Aeoru_=As/#bq!<<'!!2]_q!<<'!V>pPqs8N(qs8N'!s8N)IV'FFg_O77'Wii@qk1\hcqY'dZ
+qXWY"k+Rp?WiiA)U#t(go(r:b%eAW5k+Rp?Y,\Y)U#t(grVuuqpAP%#g?,)kY,\Y)Y2]K]@=S~>
+rr;lh"O6)sp@eFarpBgDc2757rtt1tme6)Bme6)Bme6):p?qYBp?qYBp?qYR!<<'&@Tm5Es8W&u
+#4D3Qp?qYBqu?Zrs8W*!s8N-#s8Vusrr3!!pAY'np&G*irrrJsme6)Ks8E#urrqijrr<&mrVult
+"7H3h!<)p#!;>jSmf!/qp?qYBs8N*!s6fUKpAb-ms8VfmrrE*!!!)`mrrE*!!:Kme!<<'!pAb-m
+!<<'!p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYJs7Y"2rUpB-
+p?(f:r;QromcO5Vebo+E^%UUVpAb'k"nqBHp:]#Sp&i#%k3i3Ks8W&u"6T<jebo.?rrAjF~>
+s7ZJ-!+PqB"(HW6k4ep&k1+ff@VT@eCB+<C>%1ZE>%1ZE>%1ZE@Tm5E@Tm5E@Tm5E@K?0&$347=
+>%1ZE>%7O3qu@+6s8N(.s8N*!rr?7%rru[,rr?53!<3!">6"X#!"`=C>%7O3!+K.3rrE*!!+K.1
+rso*5@fQH.s8N*!s&rl8@Tr^1@q&VNs8N(.s8Q83>6"U&s8N*!rrE*!!+K.3rrE*!!+Q!.!<<'!
+>6"U&>6"U&>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1[Ks,1&q
+@fC*HHf!<'me6\[p'0s8e_YXV@fC*G@XHt^eaE;7s4%P7HWjlnC1:q)hUU0EqZ-ZH"l=T0@VTBO
+CB+;6.=_~>
+!VZBdWWJIFk4eoYk1Z)or2Tes)5X%'Tr"HZTr"HZTr"TZV4j`ZV4j`ZV4jaa!<)rr!"#?qTr"HZ
+Tr%ehqu@,$s8N(qs8N*!rrAblrs#1srrAah!<3!"U&Y/j!"bj#Tr%eh!2ZChrrE*!!2ZCfrso+'
+V>pPqs8N*!s.Q9_V4mhf@\ocps8N(qs8SdhU&Y,ms8N*!rrE*!!2ZChrrE*!!2]_q!<<'!U&Y,m
+U&Y,mTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"I6s1XbprMg!c
+inE8Wr:U<^hV-tSOo23^Q/^NSmeZtehV-tSOo23^Q/^NSmeZtehV-tSOo)0Yrr?JX~>
+s8NDnp?qYBp?o<Up@nUpp?''Vme6)Bmf3=dp&OO[p&OO[p&jaVp?qqR!:Kj[!:Kj[r;cfrr;Zic
+rq6?[rq?Blqu@,us8N)ms8N*!rrDclrs&2srrDcd!<3!"mf3=b!!)HdpAb."!;>j\rrE*!!;>jZ
+rsJi#pAb-ms8N*!s6fm[!:Kdcrq?Bl.KK2Bs7Z0Ss8N*!rrE*!!<<'!p@eOd!<<'!pAb-ms8N)e
+s8N)es8N)erq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[$L[rop=8U!
+p?qX]rpKX_rpC#ueaE/!p?o<emK!:a!<2Bk[+4U4p?qX]rpBddqZ-W`$FJ@Op?qYBpAb/_J,~>
+%/0+(@VT@e@VTB7hVS)/rn[oi>&%M]@VYrCk#q`bq>UEppfd^t!!)q#s8O&=>6"U&s8N(&s8N'!
+s8N(&s8Q:&rr?7&s'#I&r*'.#!<?=&rr`=*s8Q:%rrW9$s'#F%"p"]'!<<'!p0.Lr'*)3>s8Q8+
+s8N*!rrE*!!*]F&>5nO(!<<'!rr3?+s8N(&s8N(&s8N)I=s:!IPZh7*@VT@]hTaU5p?qYBp?'oM
+hI9At@VT@e@c#A[q#CoLhI9AtC1:pe@c#A[k4\`R%d)<dhI9At@VT@e@fQHWJ,~>
+s7Qf"V5gAlV5f73injM3-JmbEKpes;Whl`qs.,jSTq.mJTq.mJTq.aJSY;UJSY;UJSY;UJpAd1D
+Tq.mJTq.mJs8N(iTq.mJs8N(is8N*!rrAbmrr<'!rrAbms.02i!1j/iU&Y.`Tq.mJs8N(irr3*$
+U&Y.`rr3'#s8Sels!IgHrrE*!!1fgSTq.mJTq.mJs8N(iU&Y.`U&Y,ms8N*!rrAbms.0/h!s&B$
+!<3"'!<<'!U&Y,mU&Y,mTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJ
+Tq.n&s2'nhWhl_lL#U\;lLON>o())"f&DCCWhl_lWeKH`gA(^Yf&DCCWiDnqV1mp[g?S8-!"S;J
+f&DCCWhl_lWhoal@=S~>
+s8Vrh!2TV^q>gN_!MnlUpAb.2me6)Bme6)Bme6)BmdBf:p?qYBp?qYBp?qYK!''E?me6)Bme6)K
+rrDK\me6)KrrDKerrE*!!;?Hm!!*'!!;?Hmmf3:emf3=\s8VN\me6)KrrDKdrr`>qs8VNdrrW9$
+s7ZHl-NO2H!<<'!me6)Bme6)Bme6)KrrDK\s8VN\s8N*!rrE*!!;?Hmmf*4g!<<'!rr51_s8N)m
+s8N)ms8N)mme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6ASp=8=(
+p(*tek3hsCpAajdp?q)2Ut,D:"/PAImeHhbk3f%qr:U;imcNs2s8;p$p?q)2Ut,A9s8N(pJ,~>
+%Hd(^@Tm5E@Tlslk1/Vl!%REek06e->%1ZE>6"V3;Hct%;Hct%;Hct%>#JO%>#JO%>#JO%>#JN(
+!<)rt!$+s@;Hct%;Hct%s8N(&;Hct%s8N(&s8N*!rr>r#r;Qfu;Hj)"rr<%&rVult"&`<#>5S@"
+!!#pps8N)ss8N*!ruhA?s8Q8#>#JO%>#JO%>6"U&>#PD#!)ijs!<<'!s8N'sr;Zcs!)iap!!*#u
+=Ao2!!)ijs!)cuu>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%^&NFW
+@Tm5E@TqX=eaDl!me6):e^`M[;HdO5@Tlsle^aHq%b9E>;Hd75>%1[le^a*Ur;[>qe^`M[;HdO5
+@Tm7/p*kL~>
+s7-PkV4j`ZV4i=ok2,D$!%@9lk14g?Tr"HZU&Y.hSY;UJSY;UJSY;UJTq.mJTq.mJTq.mJTq.nQ
+!$.W(SY;UJSY;UJs8N(mSY;UJs8N(ms8N*!rrAU`r;QfuSY?&_rr<%mrVult".c-VU&4li!!&Sf
+s8N)ss8N*!ruhB5s8Sd`Tq.mJTq.mJU&Y,mTq25`!1j/i!<<'!s8N(ir;Zcs!1j&f!!*#u7@jJY
+!1j/i!1fgSTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJgAeUDTqS<V
+V1%@Wg?S,*ndk0Rg=kP7NM32BV4i=sg=l?&%bfojNM3&BTr!1sg=ki[r;[>mg=kP7NM32BV4jaZ
+p0iI~>
+s8NJpp?qYBp?o$Mp?))H!%@R/p?&1-me6)Bmf3=\me6)Bme6)Bme6)Bp?qYBp?qYBp?qYBp?qYM
+!$1M$me6)Bme6)Bs8N)mme6)Bs8N)ms8N*!rrDK\r;Qfume6Y[rr<&mrVult"7GmNpA=mi!!)Hb
+s8N)ss8N*!ruhC1s8Vf\p?qYBp?qYBpAb-mp?qt\!:Kme!<<'!s8N)er;Zcs!:Kdb!!*#u=RQ4h
+!:Kme!:KRKp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBs8VfCmdBf:
+p8%-=k4\NKpAaj[k3hZ5eaE/!p?naEk2uI>s6^;keaDl!me3IEk2uC2r;[?$k3hZ5eaE/!p?qYS
+s."T~>
+s5j;jr`TS:>$=P"hUU0ErW!/jk2+sr5t_)Z"(L-eF8f&;9)_]g9)_]j8lAPZr_`_gr_`_gr_`ei
+;H!Gn!E)Ph;?0>g;?0>g;Z?as;?0>g;Z?as;Z?^u;?-^r;Z$Oo;Z6Xt;G'jc!<5ps9)_`c!<5ps
+9)J\h;Z$Op;Z?as;Z?ar;?0>g;?0>g;Z?as;@Z;!!)cDh!)`ds;?-\p;Z$Lr8lARb!!#Xj!!l0s
+!)cDh!)cGg;?0>g;?0>g;?0>g;?0>g;?0>g;?0>g;?0>g;?0>e;?0>g;?0>g;@UnN>#J7%>%1Z$
+k0;H=r9b*Xe]m5B8m5D->$=5Sc.1tSmK_n)c/q;a>%7J7"@;1pe`Q`/"P(cZ5t_)Z"CbR&mP04~>
+s6f`W"b",EhVRPs!!`#Zio[shNVoIllMn/\R@Tb:R@Tb:R@Tb6SXH%:SXH%:SXH%:SXH%:r;[t2
+R@Tb:R@Tb:R@Tb:!!&FXR@Tb:!!&FX!!&De!1fOKqu?ehR@X<W!hGaMr;["hSXH%:SbiBgR@TcD
+!!/LYquA%6R/d5XR/d5XR@Tb:R@Tb:R@O<XR@T`G!1fMX!1a)iR/d5XRJ[$dR@TcD!!&Gd!'6MJ
+!1fMX!1fOKR@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:ir>^3RJifi
+D<BR/lL+*2mdBAsg?*73r1OX<k1\\WmdBZ6mcrZ_k&$+UT`f5pg>;,l!!M04k&$+TT`XrY@=S~>
+s8W)l!:Kj[!OUDVmJut[!!`JsmdAVihZ!3Rme6\\p?qABrpBd[rpBm^mdBfJmJut[mJut[mJut[
+mem+cpAXI[pAXI[pAXI_p&G*\pAXIgp&G*\p&G*\!!)HTpA=pjmJut[!!;l^mem+dme6YJ!;?9i
+!q,dMqu?ccpA=pjmf*:emf*:emJut[mJut[mM#9o!:KRK!!)`\!!)]m!:BgemdBuQrpK[a!:Kgd
+#OVQlp?hn\pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI]p?qYRmJut[mMkm"s6eG"
+p?qYJPj[]%pAajdpAajSk3eJap?qqR&!ZMEme6\Ss7ZKdmcNr%ec#1FmZd/%me6MX"RbF?Ph#d,
+"n)*Xs8SmF~>
+s5"&[>#JO%>#It-k5O3YmJutKmcNYH0iCnQ;Hcu*s/\gj8lA8Z8lA8Z8lAQ:8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z>=qdc
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hbs8P\`>#JO%=ukHrebK4Fh?l88;Hct%;E<UjebK4Fh?l88;Gp[r=ukHr
+ec#RKmf!4dh?l88;Hct%;Hi5F.=_~>
+s6BHOs+q3Iinihc!;?!Ok2qY7NVo=Kf)O$HRAQATScA_<NVo=LA`D_+q#LHS!G.,cSHEH_injJ2
+s5F&jM>WnHA`D_+rVuueo)8XhiW3VIqjmcT!+CB~>
+s8NDnp?qYBp?pJ4pAXIirrE)mp?qXUPhtj%me6)Jrs\>hme6)Bme6)Bme6@(me6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B=RPnN
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBs8U'gmdBf:p6>REq#LH_#F*d,p?qYBPlC+H!<;HlPh#3ip?qX=rpKac
+!VZQm!<;HoPh#3qme6)Bs8SU>~>
+!T)B&;@Y^Ok2+tWmdBf2k05>89)MQiHiN5#62jIV62jIY5tXa8r^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m5X8jWGK
+!($TV"[S(H]fA^_;?/0FhY@-RhW?7Qr)*MDrndGN"5`/h62XU\.K83(!<2Bjp&G*Ljs`Un;?H";
+.=_~>
+!UAhCSITM:k2PC_mdfr:lIK*TOo1a\[f>c`Q'mo*Q'mo*Q'mo&J!lRiQ'mo*Q'mo*Q'mo*Q'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*PuF*9R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*^Alo4NLBa9"'+LCiqWTSjoJJ=r1*pik2PCr!<;0^<JgXE"]a^EiW&uXmKW4^!9WED
+M>NhFmcn52~>
+s8NE!me6)Bme6@U`Vo6)p(.2sp?%:7hY-C2me6ASs7ZH[!;?E[!;?<X!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;??Y
+!;?E[%/0,_s8TI_me6)BmXtN,q#LH_#D::pme6)BKDt<7!<;HlK?a,`me6($rpKdd'))A!rr<&e
+mXrdXme6)Bmf3<_J,~>
+/^;g<;G'hZ;G'PI0pLhWk2uC2mZ]FK3D)nA8lA8Zec1P"5tXF85tXF85tXb!5tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8>sV(K
+8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'8
+8jQ'88jQ'88jQ'88jQ)3s(Xhl;G'hZ;BXiYhWEu!mL]*[k2mdP8lA8Z8g*!QhWEu!mL]*[k2mdP
+8kMuR;BXiYhWEu!mLJsYk2mdP8lA8Z8lF3r.=_~>
+!TN8;R1=pVWoiI/lLsr>Wa/GHOo(OJk5W/HQ)KrORI:*TI?"/m%nu!Fk3D7"mdfrBmcrq.L&@>L
+9]G3slK[g*o()MBlK1cor0\'hio]CglL+*2o(MM:k"LL+RK)CL@=S~>
+s8W)d!;?BZ%b6KVp?qYJs8Vf3MhA_*rpCBlme6\\p@dqJme6)Bme6)Bp4)N(me6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme0lQp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBpAb0d`SU%Np?q@$me6)IpAY*lp&sf9c0k<)mK8+0p?qnQrr<#l!q(]crU'g^
+KC8I$rV$6js7QN^K?aD`"nqBPs8SU>~>
+s3:=2$ooG.PeH4uUfnTP0gYY.%[@"e;F*</3C,Yk3C,YcImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3E&4(5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh6,s0OL@8jWDJ!>+DmhYlU:mKE7OmLV\^8c]LcrndV9s6^$`md:WPr(6u$k5O69k5XiPp?q>[
+62O7Ue]fh!~>
+,3%IIQ'mo*Q'n&*I8G'_b3%-XI7-b?KpA'kR?a2*^An&#JWZpo&'Fq'D1Rh7R?a2*7-<Lkk5FQV
+mdg)>njJ%sQ'mo*7-<Lkk5FQVmdg)>njJ%sR?a2*7-<Lkk5FQUmdg)>njJ%sQ'mo*Q0.(7J,~>
+s8O27me6)Bme6ABc&8+2hY-*VS9'=QhX:+*p?qYBpAb/Dm\oO]pAaifc0"Hfme6'irU'^[meuhd
+s7ZJ6c1^T!me1`#mK*%LrUpTupA]3Yp@dqJmW8?p!VYs[p'q&qs)ZHYme6)Bmf3<_J,~>
+s2>")9)_*V9)LsU+;"MX#S7h%.60[d5t_,B"\M)"s5lrQ5l`qE5m',55rnp1!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!]`P,r]piN6&YdC5rh4s9)_*W8g*a3!"f)p!_Pa$oEYF.r]pWY5sZXc#QkW(5t_,B"%pPW.=_~>
+%bfd%Q'%>oQ'%2oNIb5#r]CcX6rdfLNKoWkOd2&oQ/;Q/R=UL$OUSi$s,hG\Od2&oOd05E49n9*
+Od2&oO^7TA#=O-*Od2&o?1^5d7"LJcOd2&ohVqso~>
+s8Vi]!nEffrc86XF,Qj=k54QIp?qq[!Uf[\mJut[mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;??Y!;?E[s7ZKm
+"R`t[me6VI!2T7.!IN)hmJs'TErgX4r9aQ\oQ(%[c26r/rrAR>~>
+!QDbG5liu#r$_Y$3VPfK9%Et(>!Y/73C,Yk3B;RT3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Z&5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh6,s8Q7W
+3B?q%!BDV&+9<oOq`t6C.J=kb.678k!BDV&+9<oOqa(8$!%EE~>
+s4RpIOd2&oOd22oQ&UK?C&VBMBm#,hQ'%>oQ'%>oOd5)/m\,2kY)Q8?b5_L8D1RP+Od2&oOd1K3
+<EW=)<EW=)<EW=9JX)@_Od22_BiS;9=]JU)=]JU)Bn;P7Od2&oJSA+e<EW=)<EW=)<G@#LOd2&o
+Ol"f#J,~>
+s8O&3me6)Bme6ABp?peNXIPNFXM*KYp?qYBp?qYRmf*7dmK_nBk3hC"k2q0]k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hA\mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs2s8Veoe`Q;fp?qYBp=67&P`(caP`(caP`)Wnp?qYBp@d%<Mj0-aMj0-aMj0.$
+eb8\Ume6)BeZ=[nMj0-aMj0-aMlbJ&me6)Bmf3<_J,~>
+*ONL?5rh4k5rgqk3C,Yc0f^sK0f_6[3C,Yk3C,\)5n$ZAs8TH03C,Yk3C,r\3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk:cUg%
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5s^.cs8Q7O3B@()7QEap5rh4c3AENK3AENK3AENK5rh4k5rgqk0f^sK0f^sK0f^sK
+0gRf[5rh4k5qtAS3AENK3AENK3AEf[5rh4k6+sr\J,~>
+s4/-KOc>K_Oc>?_NKK3[JUr6#JW5YONKK3_NKK5"OTh04s8UN@JW6sp#a)R`s8Sd,I>.Z_(QFQ:
+Oc>?OI<g6dI<g6dI<g6lNK''[OoC=KJUMflH$ssdH$ssdJc:WJOc>K_NIcM'I<g6dI<g6dI=[B;
+Oc>K_Ok/5pJ,~>
+!VZQdmK)J,rm_&+k4n?EpAXLYrrDcljob&6k3i62!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK#4CXAk2u+*rr3)oXNfVs
+mJtf2blH;imJtf2blH;imJtf2blH;jmf3:eS:C~>
+s0O:B3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh4k5rh4kXS2\om]<LBMh?Y3Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?7uN"X
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8Yu$`W#m5ZoKQi0f_6[3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3OH.JJ,~>
+*S/Z$NKK3_NKK3_NKK3_Oc>K_Oc>K_Oc>K_Oc>M%N<b<cqZ$TdcH_!P\@N$adbaj#s43$@H%GpR
+7Zi[mNKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NRlNdJ,~>
+s8W)d!9X:K!9X:K"6T%>k5OcKk5OcKk5OcQk3hC"k3hC0rrMinJbHSHr;R,thQ4]Hk2u*omcON:
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+"m57@s8SmF~>
+s/Z5]62ikE62ikE62NYB62ikE62ikE62ikM5rh4k5ri,MhLY^3rsHGS0ek[K5rh4k62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikH
+6*..:J,~>
+s3;R?NJWXONJWXONJWXOM2d@OM2d@OM2d@OM2dAiN<>$*cK]u\Z2Y'[V.FLlJVf6_NCJbaM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2fg/@=S~>
+!VZQRjoFiKjoOoDJcDqR"R`@uc.2dT!:IP_!quYaJ,~>
+*NZ&&3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh713<2AD3<M!.F*iJ.\=<bUC.^300erVe!($TE
+7R9%#3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3NT#*J,~>
+.F-(qM2d@OM2d@OM2d@ONJWXONJWXONJWXONJWXONJWXONJWLCQ*.Fl`dbkF_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T#Eh`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4
+`koa4`jVn4EG9E8JVAr;8r\[eM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM9a7PJ,~>
+!WVlTjoF9;jp0c*hVQfFmd>Z"\G#sj$Kf%']uAOPk2,7W]B01pp8!3~>
+-Cgkd3AENK3AENK3AENK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKpb;atr\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%pG#B&
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0fbc".=_~>
+.`TVVI<g6dI<g6dI<g6dH$ssdH$ssdH$ssdH$ssdH$ssdH$ss`F`h\Drb[.!D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!i\Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$
+Bl.R$Bl.R$D/jQ@Gti^4I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6d
+I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dIE'E<J,~>
+*VTNPc,IrHc,IrHc,IrH`QcBH`QcBH`QcBH`QcBublu)2`PoO(rj70V[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gW&XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XSoO+^&Q(Jbso[s`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`Qe,VS:C~>
+!i2>HJ`_OG^ubd=3LlloJ,~>
+!m8N2J_kt7^to46IE'E<J,~>
+!rqu=J^o>%^srS$c1_1-J,~>
+!h?&@J`_OG^ubd=0r1<gJ,~>
+!liB.J_kt7^to46H-4-8J,~>
+!quZ5J^o>%^srS$`W,Y-J,~>
+!i2>HJ`_OG^ubd=3LlloJ,~>
+"3SW3idos;hSJ%O`dPkL@=S~>
+"98)>hLX4.e\Tc=^!69NS:C~>
+#+VJDk3hC"roO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4K
+roO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroS^uk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hABmcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"`A+0Y.=_~>
+J&]WVhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhLFPAini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oind5chW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!D3H-4-8J,~>
+J+io]e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5eUQH+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUP0Re_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\ii`W,Y-J,~>
+"/MGImf)?TmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs:joFiKjoFiIjoFiKjoFiK
+joFiKjoFiIjoFiKjoFiKjoFiKjoFiIjoFiKjoFiKjoFiKjoFiIjoFiKjoFiKjoFiKjoFiIjoFiK
+joFiKjoFiKjoFiIjoFiKjoFiKjoFiKjoFiIjoFiKjoFiKjoFiKjoFiIjoFiKjoFiKjoFiKjoFiI
+joFiKjoFiKjoFiKjoFiIjoFiKjoFiKjoFiKjoFiIjoFiKjoFiKjoFiKjoFiIjoFiKjoFiKjp1>:
+k/B?NUa^f~>
+"Nn`4ing?fJ)92Aini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\OiaUd(hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO`dPkL@=S~>
+#64DAhUUK5rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*
+rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn`.ThUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUIne_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5^!69NS:C~>
+J"3;hk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k'ug]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcI(.k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBN0r1<gJ,~>
+"NJT0ioZonJ*,bQio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_iaV'0k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_`d,_H@=S~>
+!quZ5qq_>'rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*
+rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*J_m*W"MMeSp8!3~>
+"JhPJmcL21J*-1]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mUG>Hk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"`AsHa.=_~>
+"Nn`4k2N&rJ)]VMk2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k$m?4io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_`dPkL@=S~>
+!rqu=SDF7rrn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*
+r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*
+rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*
+rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[dkc1_1-J,~>
+!h?&@q!S"Z"RZ9XmJu\CqZ-N]!s%cW!:oOX!<)<c!;Ps^!.jR(mKCK`Umrla~>
+!liB.pu_GR"Qf^HjoFi3qZ-NU!s%KG!:o7P!<)$[!;P[V!.j9ujoi\Lb/Rk?~>
+!quZ5ptklJ"Ps.8h>m!#qZ-NM!s%37!:ntH!<(aS!;PCN!:ntHk5O3;k5='9k5O3;k5O3;k5O3;
+k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;
+k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;
+k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3?]uC$F
+Ujr~>
+"/MGIpAXI[pAXI_p&OOKpAXIap?qVSmdBfJmJut[mJut[mKWCQp?q>KpAXI[pAXIap?q>Kp?qYR
+mJut[mJut[mJut[mKN[Zp?q>KpAXI[pAXIap&OOKp?qYRmJut[mJus3m\B1Q`AsHa.=_~>
+"3SW3lMfpPlK7Bol2^,3lK7BolK7@3lK7BolK7BolK7BolK7BolK7@3lK7BolK7BolK7@3lK7Bo
+lK7BolK7BolK7BolK/*/lK7@3lK7BolK7Bol2^,3lK7BolK7BolK7A_k+h&A`dPkL@=S~>
+"98)>k5O4Dk2,7WjoFQ#k2,7Wk2,5#k2,7Wk2,7Wk2,7Wk2,7Wk2,5#k2,7Wk2,7Wk2,5#k2,7W
+k2,7Wk2,7Wk2,7Wk2$*pk2,5#k2,7Wk2,7WjoFQ#k2,7Wk2,7Wk2,6OhP8p1^!69NS:C~>
+"Iu8Bme6MF!!)f^!!)HT!!)`\!!)rb!!)][!!)uc!!)f^!!)ZZJ+i=(me6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmUGnXp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYB`A+0Y.=_~>
+J&]WVk3D*ok3D*ojoFQ/k3D*ok3D(/k3D*ok3D*ok3D*ok3D*ok3D(/k3D*ok3D*ok3D(/k3D*o
+joFQ/k3D*ok3D*ok3;s3k3D(/k3D*ok3D*ojoFQ/k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok'u[YlK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK1Y&k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*KH-4-8J,~>
+J+io]hWE\WhWE\Wh>lEphWE\WhWEYphWE\WhWE\WhWE\WhWE\WhWEYphWE\WhWE\WhWEYphWE\W
+h>lEphWE\WhWE\WhW=h#hWEYphWE\WhWE\Wh>lEphWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhLF\Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2&YkhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\.`W,Y-J,~>
+)5Nc_p?qYBp?qYBp&OgSp?qYB!:KO\p?qYR!#>4qp?qYBp?qYBp?qVSp?qYBp?qYBr;ZrnmJu\S
+!#+eome6)Bme6)BmJu\Kme-YSme6V[')(be!;>g\mJm7\me6)Bme6)BrpBd[rpBj]me6YJ!;?E[
+!;?E[!;?E[!qu'UrpBd[rpBd[rpBd[rpBj]me6YJ!;?E[!;?E[!;?E[!qu'UrpBd[rpBd[rpBd[
+rpBj]me6YJ!;?E[!;?E[!;?E[!qu'UrpBd[rpBd[rpBd[rpBj]me6YJ!;?E[!;?E[!;?E[!qu'U
+rpBd[rpBd[rpBd[rpBj]me6YJ!;?E[!;?E[!;?E[!qu'UrpBd[rpBd[rpBd[rpBj]me6YJ!;?E[
+!;?E[!;?E[!qu'UrpBd[rpBd[rpBs``AsHa.=_~>
+!m8N2q!%hZqs"7`lKSBKlM^eUl2Uh[lMU__l2^nMrW)ZW!!)u_!!*#`rW)r_"p!rR!9sOaJa/cj
+"NGl0b$ff~>
+"TS2?k2-+"!8d_;!!*#\#2\M)!8ci<roX1[!Tr8<joF9;jp'])hW=h#hYuX=hWEu!!!DB?!8d\T
+!8d_;!8d_;$f:%.!8ckpjoFQ#k5GA[jothJjoF6<!<2*\hYuYehWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W@c$8(k2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,76c1_1-J,~>
+B:PbPme6)Bme6)BmJu\Kme6)B!;>g\me-YSmJm7\me6)Bme6)Bme6&Kme6)Bme6&K!;>g\me-YS
+mJu\Kme6)Bme6)Bme-YSme6&Kme-YSmJm7\mJu\K!!)Ee!;>jSme6)Bmf)n[mf)n]me6)Jp&OO[
+p&OO[p&OO[p&a[Umf)n[mf)n[mf)n[mf)n]me6)Jp&OO[p&OO[p&OO[p&a[Umf)n[mf)n[mf)n[
+mf)n]me6)Jp&OO[p&OO[p&OO[p&a[Umf)n[mf)n[mf)n[mf)n]me6)Jp&OO[p&OO[p&OO[p&a[U
+mf)n[mf)n[mf)n[mf)n]me6)Jp&OO[p&OO[p&OO[p&a[Umf)n[mf)n[mf)n[mf)n]me6)Jp&OO[
+p&OO[p&OO[p&a[Umf)n[mf)n[mf)n`m_poVS1/s~>
+"NJT0lL+N6!!)o]$39AV!:&hLlKS?Lp$)MWqWe(\s69dglKSB7l2^MB!!)u_&HM+]!:&hL!:&hL
+lKS?Ll2Uh]l@86emcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcn9LlL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lGe+l`aOA~>
+"8;c6hYuX;hYuX?h>l^#hYuXE!9W,<k2l[+jo>D\joF9;jp'])hWEr#hYuXIhWEr#!9WDDhW=h#
+joF9;joF9;joF9;jqn*\hWEr#hW=h#h>dQ<h>l^#!!(jU!9W/;joF7hk+h&A]uC$FUjr~>
+"JhPJp?qeNquHcj"p"Aj!;?*drq6<lp%J7_s7QEmrq6Nrp@\L[p&OdZqZ-Zi!!*#l"p"Aj!;?*d
+rq6<lqt>O-p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qW`me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme4U[S>7Ta~>
+$d-J;mcs6*mcs6*med&%mcjf;mJu\?!:'";!:'";mcs6*mcs6*meZu$lL"Z?lL"Z?l2^,;!:K.?
+lL*s*lL*s*lMCR2mcjf;mcjf;mJu\?!:'";!:'";mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*H1'tclL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL)Z?`l__?~>
+!rqu=pu_JSs5jLck2l[+joGDC!!)]SqZ-ZY!!*#\"p!fJ!9WDDp#c,Os5j:]roOCbk2l[+joGDC
+!!%T4S`U'gc1_1-J,~>
+!h?&@qt:0\p@\LSrq6Qap&Og[!:K^a!VYs\p&OOYp&sd`p@dqRp($Kjp@dnSp@\L[mJutSmf)n[
+mf)n]me-Y[p&aX^pA4jip&b<_p&P*c!!*#l!:GF3U%SW.0r1<gJ,~>
+!liB.q!J+^qsFRemd:)CqZ-<W!!)l`!!*#d"p")Z!:K7Tp$Me[rU'[dme["amK3IWmK!7S!!%T<
+SaHX#H-4-8J,~>
+"SVl7k3i*.!!)oY"9@TH!9X.Yp#Z5SqW7bXroOCbk2l[+joG):!!)u[!<D9Z!<;0`!9WDDroO1\
+qrRnHroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK
+!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroO4KroO:M
+k3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4K
+roO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroOFQk.Sb6p8!3~>
+!i2>Hqt:0mp@\Ldrq6^!p&Og[!<;`mpAb-c!<<&l!<;uj"TJJqpAb-c%fZP&pAY-dp&Ogd!;?-d
+rq6?lrq6Enp&P*c"TJJqp&P*c#64Dj!<;`mrq6<lrq6?lJbGf2"N<BkUa^f~>
+"3SW3o)A&`o'Z):nc87Ko'Z):!:KCXo'QMGo'Z):o'Z):o'Z):o'Z&Ko'Z):o'Z&Ko'Z&Ko'QMG
+nc87Ko'Z):o'Z):o'QMGo'Z&Ko'QMGo'Z):nc87K!:KFG!:KFGo'Z("m\B1Q`dPkL@=S~>
+BE.\MmcNs"mcNs"mJu\;mcNs"!9W\LmcFN3mcNs"mcNs"mcNs"mcNp;mcNs"mcNp;mcNp;mcFN3
+mJu\;mcNs"mcNs"mcFN3mcNp;mcFN3mcNs"mJu\;!9W_3!9W_3mcNs"mf)>Kmf)>MmcNs:joFiK
+joFiKjoFiKjoXu5mf)>Kmf)>Kmf)>Kmf)>MmcNs:joFiKjoFiKjoFiKjoXu5mf)>Kmf)>Kmf)>K
+mf)>MmcNs:joFiKjoFiKjoFiKjoXu5mf)>Kmf)>Kmf)>Kmf)>MmcNs:joFiKjoFiKjoFiKjoXu5
+mf)>Kmf)>Kmf)>Kmf)>MmcNs:joFiKjoFiKjoFiKjoXu5mf)>Kmf)>Kmf)>Kmf)>MmcNs:joFiK
+joFiKjoFiKjoXu5mf)>Kmf)>Kmf)>Pm_-m=s."T~>
+"Iu8BpAb!_!!)oi"p"Aj!;?*dnb)q_qXt6rp@\Idp@\L[p&OdZ!!)uk!s&&g!;lHp!;?*dp@\Id
+qt>O>pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAahqs7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7XDdUmrla~>
+"3/K/mf)c`mdff:mJu\Gmdff:!:oOXmd^AKmdff:mdff:mdff:mdfcGmdff:mdfcGmd^>Xmd^AK
+mJu\Gmdff:mdff:md^AKmdfcGmd^AKmdff:mJu\G!:oOX!:oRKmdfdsntYaY`d,_H@=S~>
+?hXN=k3hC"k3hC"joFQ3k3hC"!:JtLk3`6;k3hC"k3hC"k3hC"k3h@3k3hC"k3h@3k3`3Lk3`6;
+joFQ3k3hC"k3hC"k3`6;k3h@3k3`6;k3hC"joFQ3!:JtL!.XG!mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcJ3Nk3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBF`W,Y-J,~>
+"/MGIs8M^)s7ZKdrrE)ms7ZKd!;?Ems7ZKk!"8N#pAajdpAajdpAb!i+nks0!!*$!s7QHdrr<&m
+s7ZKds7ZKds7QHds7ZHms7ZKk!!N#q!<;ck!!`Jss7ZKds8M]ls8M]ls8;Qjs8M]ls8M]ls8M]l
+s8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]l
+s8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]l
+s8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ss7Z0*3Lllo
+J,~>
+!m8N2q!nCbqsjgho'ue[o)/R]o(rFdo)A[qnc87O!:o[\!;>s`!<)Hg!<2Qf!<;Tk!:o^Z!.j^2
+ncZs\`l__?~>
+#64DAmcNs"rpBpOmJu\;rpC$R!:K7TmcNs9!<;Hek5OcKk5=ZE!<;Hsjo>DL!:K7Tmd:&TmdB6:
+mJuDKmK)GMrU'XcrpK^b"Qo+PmcOHJ!Uf+LmXOBek3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3cdBmcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNrNc1_1-J,~>
+".Z/ApAY(upAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd!<;cmpAajdpAajcrrDclrrDcjrrDclrrDcl
+rrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDcl
+rrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcj
+rrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrs/8t
+s2?^gS1/s~>
+"NJT0o(K-T!!)caJ+iI,o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJnm_=`p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ`d,_H
+@=S~>
+!quZ5qsFIHrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdK
+rpBdKr9aRIrpBdKrpBdKrpBjMmK!7S!9X:K!9Sk#U$`&s`W,Y-J,~>
+"JhPJs7Z?iq>fg\q#K^[q#L-g!!)cnJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds'k^%pAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajd`AsHa.=_~>
+$HgA:p@@qJp@@qJq>_<%p@@qJp@@qJp@@qJp@@qJp@@qJp@A"Z(A@=mo(MYJo(MYJo(MYJo(MYJ
+o(MYJq#Gp8p@@qJp@@qJp@84Sp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@p%o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJ`dPkL@=S~>
+!rqu=q<n(ZlL+HJlL+HJp?hn\JaSro"MN(Rs."T~>
+".Z/ApAY'lpAY'lpAY'lpAY'npAajcrrDclrrDclrrDclrrVoopAY'lpAY'lpAY'lpAY'npAajc
+rrDclrrDclrrDclrrVoopAY'lpAY'lpAY'lpAY'npAajcrrDclrrDbDs.fSs`A+0Y.=_~>
+!liB.JbFZg_"IoNH-4-8J,~>
+"SVl7me3=AJ+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)BmUGnXp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB]uC$FUjr~>
+!i2>HJcC<$_#FPV3LlloJ,~>
+J',cZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqLA58pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA.>RqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'd*IE'E<J,~>
+J,f5ep?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp4)N(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme03>p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qXfc1_1-J,~>
+!h?&@JcC<$_#FPV0r1<gJ,~>
+"3/K/pAXnppA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4K6qP3li`d,_H@=S~>
+"8;c6mf)odme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Jp&OO[p&OOYp&OO[p&OO[
+p&OO[p&OOYp&OO[p&OO[p&OO[p&OOYp&OO[p&OO[p&OO[p&OOYp&OO[p&OO[p&OO[p&OOYp&OO[
+p&OO[p&OO[p&OOYp&OO[p&OO[p&OO[p&OOYp&OO[p&OO[p&OO[p&OOYp&OO[p&OO[p&OO[p&OOY
+p&OO[p&OO[p&OO[p&OOYp&OO[p&OO[p&OO[p&OOYp&OO[p&OO[p&OO[p&OOYp&OO[p&OO[p':$Z
+p:\HFp8!3~>
+!i2>HJcC<$_#FPV3LlloJ,~>
+!m8N2Jbjro_"n2RIE'E<J,~>
+!rqu=rq6?[rq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[
+rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Y
+rq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[
+r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[
+rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6K.c1_1-J,~>
+!h?&@JcC<$_#FPV0r1<gJ,~>
+J&]WVqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqLAPAs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8#:dqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$E3H-4-8J,~>
+"8;c6mXb(_p;-G*]uC$FUjr~>
+!i2>HJcC<$_#FPV3LlloJ,~>
+J',cZs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls*snFqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqYs+_s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)c8IE'E<J,~>
+!rqu=JbFZg_"IoEc1_1-J,~>
+!h?&@JcC<$_#FPV0r1<gJ,~>
+J&]WVqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqLAPAs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8#:dqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$E3H-4-8J,~>
+!quZ5JbFZg_"IoE`W,Y-J,~>
+!i2>HJcC<$_#FPV3LlloJ,~>
+!m8N2JcC<$_#FPWIE'E<J,~>
+"98)>s+0lpp;-G*^!69NS:C~>
+!h?&@JcC<$_#FPV0r1<gJ,~>
+!liB.Jbjro_"n2RH-4-8J,~>
+!quZ5JbFZg_"IoE`W,Y-J,~>
+!i2>HJcC<$_#FPV3LlloJ,~>
+!m8N2Jbjro_"n2RIE'E<J,~>
+!rqu=JbFZg_"IoEc1_1-J,~>
+!h?&@kl:S]n,NCfaoDA@k5YG]k5Ph>`QcrXe]lXhc)gX!rrLZpnc/F8!1`<R!58?4!57h#q:5Ma
+!OTQ%rrg:qUmrla~>
+!liB.kk=rTn+Qb]anG`7k4\fTk4Si$`r!pY`W<+)jRrZGd`1hNq9f86l1P:lWhl_l]'f7ldehSu
+d`T_D]&iVg`d,_H@=S~>
+)ts<NmdBf:p?qYBp@dqJme6)Bme6)Bme6)Bmem-7p?qYBp?qYBp?qABme6)Bme-V\me6)Bme6)B
+me6)Bme6)Bme6ABp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBme6)Bme6)B!!)H\me6)Bme6)B
+me6)Bme6)Bp?qYBp?qYBp&G*\p?qYBp?qYBp?qYBp?qYBp?q?8p?qYBp?qY!`PpBHe]$(Xc(sdq
+p?qYBp?qYJme6)Bme6)Bme6)Bme6)Bme6)BmcN'nme6)Bme6)Bme6):p?qYMjtXRCme6)Bme6)B
+me6)Bme6ABp?qYBp?qXn]tMCuc0k;np?qYBp?qYBp?qYBme6)Bq<%_6s32\Sp?qYBp?qYBp?qYJ
+me6)Bme6)Bme6)Bme6(^`W,Y-J,~>
+!i2>Hl2Lkd;OiXFo`+gh!dg.3q#C6lh>dBQ!dgF;q#C6lqZ$Hn!dgF;q#C6lp&>'CpA4djp:]nT
+rrUaNc11f6ec#LNp?qA!SEp1UXIT7h!L0t[rrCUHs8Vcpma^I,k5PS'3LlloJ,~>
+!m8N2l1P5[<L&7<o_/1_!dTn.q"FUch=gaH!dU%2q"FUcqY'ge!dU%2q"FUcp%AF7mem(fqY'Wk
+k2c4;b5]KOp&NP?rrr8mlKZfglh1@ZRJm-dQ)a<H!7q&Is7QQ_f&F:'p&rB``l__?~>
+/H>Fgp@dqJme6)BmdBf:p?qYBp?qYBp?qYB!)f&.!:KRKp?qYBp?qYJme6PY$[\*<me6)Bme6)B
+med&0me6):p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp@dqJqu@+OS,i!Nme6)Bme6)H!!_lb
+mdBf:pA=muH^k*(p?qYBp?qYBqu@2op?qYJme6)Bme6)!meZr>p9`]Mme6)Bme6):p?qYBp?qYB
+p?qYBp?qYBp?qYBhZ)-op?qYBp?qYBp?qYJme6)2r;Zfj)<S="me6)Bme6)Bme6)BmdBf:p?qYB
+p:[j3rtMQJme6)Bme6)Bme6)Bme6ABp?q)=s!.7"m`k1nme6)Bme6)BmdBf:p?qYBp?qYBp?qYB
+p:\`Es."T~>
+9Uqn5p@eO*s2G#Ws8VfmpAajdpAajdpAY*m^%V/q!<;cmpAajdpAaj[s7QG6Pf895s-s)_s7ZKd
+rr<%hhMZFTs7ZKmpAajdp?)@n!58?<;66R`S<T7QPj\SFs7ZKdpAagd>*R!YMuT:IpAajdpAY*m
+SDK05!<;cms7ZKd!*YW+K8]c"!;?Hds7ZHm!1_o(@K?H%s7Z0dpAajdpA`\?s#'N<p9a8]s7ZKd
+s7ZKmpAajdpAajdpAajdpAajdpAajdc2YKWpAajK`W,Z3pAaj[s7ZKCr;R]'p=8#is7ZKds7ZKd
+s7ZKds8VfmpAaRKXH`\`s7R+aXQJsEs7ZKds7ZKds7Z0dpA`\>s8Vd:eaDk=pAajdpAajdpAb0d
+s7ZKds7ZKds7ZKds7XDdUmrla~>
+I`BNUo()h#s2P)Yp@e(No(MYJo(MYJo(E%`_Xd,c!;?!Wo(MYJo(MYFp@82/NOjClp6>XKp@@qJ
+p&G)XeqkXPp@@qNo(MYJo%q6t_R?VIY,\1hSXGV&EKTP[o(MYJo()MF!"=juH&;6_!:ojSp@@nW
+!0u,l&-2Fps7Rf1p@81lNOjClp6bpOp@@qJp&G)Xeqjq<p@@qJo(MYJo(MYJcLUr62YQ_,m]u!G
+p@@qJp@@qNo(MYJo(MYJo(MYJo(MYJo(MYJb5]'Ho(MY2`qJuso(MYFp@@q*rVnbOmdANSSbDXJ
+o(MYJo(MYJo(MeJp@@dgY*k:LqY'dZnr9'?_XdEkp@@qJp@@qJo(MYJf)#FHp*/)QlFQQ[o(MYJ
+o(MYJp@@qJp@@qJp@@qJp@@qJ`d,_H@=S~>
+$MOM=mdC+gs1SHGoBuVY"MONsS,i3L#QSq(XE0$fPQ:UKrr<1leVeJKq!J:IhVQf5rQYA]s1SH>
+!h?@Sq!JCf>)TJ'KD(N0qsOIa"J"##@K?8m#QS%dXE0$fPQ:UKrr<1leVdl:p$Mk*pAFpnp?qX]
+hW4)+ec3nmmK)J#p[/%Dr;Qons5ra_nEpGAK49J7r;QonUk;j'o'QM?q#:HYp@cbomKC5Bs7W7=~>
+!i2>Hrr4ams2G#Wp@eO[s7ZKds7ZKT!!&h_s8Veg!;?Hds7ZKds7ZKmpAY,-Mq*0]s8SShpAb*l
+(6mt]mZ_GdpAaj[s7ZKds2F-_s+>B>q>V8<K7imtpAajds7ZHm@Z/c`[/^/r!;?Hl!#_$`s6c+T
+!;?HdpAajd!+Ll:HaNhQS,i9_rW!Xsk5Xk6=oe9rpAb0ds7ZKds7Y=Crr<#ls6_]*^#o@gs7ZKd
+s7Z0dpAajdpAajdpAajdpAajdpAaj2s0VM"p>4'VpAajdpAb0ds7Y"@ruLh$Un"6Ns7ZKds7ZKd
+s7ZKdpAajdeaE-q`TH=NroOm=MuW5%pAajdpAajdpAb0ds7Y"=s!.6fpAa!VpAajdpAajdp@eO[
+s7ZKds7ZKds7ZKds2@!gUa^f~>
+36K6hp@eO+s2P)Yo()MFp@@qJp@@q:!!&k\s8VYX!:ojSp@@qJp@@qNo(E&#M8FP@qY$0So(N%_
+(6.>Rif+cTo(MYFp@@qJp;5tSs,i"pq>V8FNICBko(MYJp@@nW%#MiHY57j[!:oj_!#^dUs5K"H
+!:ojSo(MYJ!"=_$H*7#;R/lgOrW!XlirA"t$ioklo(MeJp@@qJp@?Z"rr4qNo'5B"[c7#Op@@qJ
+p@@eJo(MYJo(MYJo(MYJo(MYJo(MXss/tqdo%)+Go(MYJo(MeJp@?Z1rrW&flM[8+p@@qJp@@qJ
+p@@qJo(MYJS]]rK`oc:Cio]7?L$$CGo(MYJo(MYJo(MeJp@?f2s!7I7f(/jt](5Rcp@@qJp@@eJ
+o(MYJo(MYJo(MYJo(L(O`l__?~>
+$NKhEmdC+gs1SHGp?i7D!!&h_s8VMO!;,[e!,@G!F/8j0MZE25rW!.ek5X:rC&n%s#1`G8s0Sl/
+q>UNHXJGXZ$NOXoZu`&Cp58q=mf!1jPii#&Mcp,WmL'#(MmRQ$s7V?NmdC&S#*e9MhMYP;p$Mk*
+pAY*lpAaO^k-X"+mK28F`W#<*hY-@;k55/]p:[iH[.3Pe8ns9Bebeb;eUrch9(VHNk4nrZk5YJL
+c04Qu^!69NS:C~>
+$_4"Ip@eO*s2G#Ws8DWks8M^%rr<&+p@dp=SF30Qp@eOcp&P-ip&tG*Pg+ifrr2t_rW!#$mf3:S
+"-dO#s82Kqs7XFghZ$2OHhm[FUl.8,pAb$`"TV_jc%ED&rrASg!!97is8MEgP[XXmqt:0n>*R9a
+[/U(*SGiKiXR?,fmK8\_!<;ri!<<&l!rpgErr38tmdB6"XQK6Vrq6Hop@eOcp&P-jp&P-lp&P-l
+p(%,rp:^L%p@d%Us4-i:s82Kjs4.&Is7QQ_hT_kop&P-lp&P-ip(GpUs+AS8c,IrHc,GV@s3:92
+s8M]ls82Kjs4-oE!7h)K"7Ekrs8M]ls82Kis8M]ls8M]ls8M]p`A+0Y.=_~>
+2TEmbmdC+ps2P)Yo()5>mdff:md^>XY3u#KOd54&!:oRKmdff:mdff6o'QJlNP]tDs8)/?rW!e3
+lMBf2k)C2Xo'Z)>mdff:m_7Q;s']c$q>V28O[/L*o'Z):mdfcG%#r,LY5e@dNW&nqV<[pBlK4';
+!:oRKo'Z):!"=k(H*72DmZ%2G;5NRSlK[Mk&-2:ho'Yr:mdff:mdeZos8Vf`lK6s_ZJt<Cmdff:
+mdfr:o'Z):o'Z):o'Z):o'Z):o'Z(_s.T#OcGKV0o'Z):o'Yr:mdeg(ru(Cqk1[tKmdff:mdff:
+mdff:o'Z):RK*;@q8O&$s8SATmdff:mdff:mdBZ6o%*[;s8!qjs8Vr\]'f.Wo'Z):o()5>mdff:
+mdff:mdff:m`'Op`aOA~>
+2YR0ik2u]Ws1SHGmdB6*k3hC"k3`3L[.a4]Paq03!:K";k3hC"k3hBomcFLYMmRi,s8V5.rW!e:
+mf2_Ck)3sSmcNs*k3hC"k1/nfs-0%Tq>V2SZubZtmcNs"k3h@3>)Tb7V#UJWKDkigXR?,VmcKF:
+!:K";mcNs"!*Y;fH_g]Ak(EX5(9Hs(mdB4q@K>iYmcN["k3hC"k3gLfrr4qNmdB6"XPW+-k3hC"
+k3h["mcNs"mcNs"mcNs"mcNs"mcNr^s1Rj_e^a]VmcNs"mcN["k3hC.rtkCshS&(>k3hC"k3hC"
+k3h["mcHfnP_8e^&qc+#3UZ%tk3hC"k3hBomcNs"q#:?Vrr4&5c0"HVmcNs"mdB6*k3hC"k3hC"
+k3hC"k.Sb6p8!3~>
+!i2>Hrr35Bs2G#Wp@eOcp&P-lp'LeipA^AAec5?5!<2Zls8M^"s7Z0dp@\JqMp6U^rr3SuMhC0c
+p?n00k*0<TpAaj[s8M]ss0U>,s&t&Fq>UMlF#j6n$ifqos7Z-d@Z/KX^&J$LmYc_[p@dp=Pie36
+!;?HdpAaj[!+Ll2HbKFY&akR0k4\N:Pa(<p=oe9rp@eOcp&P-lp'0CAs7Z0Smf)&G^#o%^s8M]o
+s7Z0drq6EnpAb-c!<<&l!<<&l$NKh,p71j$^&RfFrq6Hop@eOcp&NY@rs8>dhTaT@s7ZKlp&P-l
+p(dW$pAaj[`W,t_K8YA?K8YA?c2[ggrq6?lrq6Hop@eOcp&NY=rsAC`Mj0-aMj3r8rq6Hop@eOc
+p&P-lp&P-lp':Wkp;K%^Ua^f~>
+;Td"-o()h#s2P)YmdBZ6o'Z):o'QL?o(nK2df8m'!:KFGo'Z):o'Z)>md^>lM8FPDs8VZDI<j];
+p?Id&ie\3Hmdff6o'Z):o![9+s)!mpq>Xg%I6?rgmdff:o'Z&K%#MiHZN'sqg3n8'me5q.OlD3+
+!:KFGmdff:!"=_$H*[JMo%JM;hX:+&OceX[$io_dmdfr:o'Z):o'Xros7Z$Kk2+hGZJP0?o'Z):
+o'Yono'Z):o'Z):o'Z):o'Z):o'Z):ZL4"G`kMKD_X@!_o'Z)>mdfeor;RZ.mbZ77Sau4>mdff:
+mdff:mdBZ6ns0(F`qb<$_YW\_mdff:mdff:mdfr:o'Y*)rrDchOW3`Zmdff:mdBZ6o'Z):o'Z):
+o'Z):o#?*tb$ff~>
+$ifqFmdC+gs1SHGk5F]Jk5OcYjoC&-s-/bus6bdFmdB6:mJuDHmM5e3K=#^$s8V6#@WU]*p?n00
+hMYhCk54QPk3gLVk5U[Q`VKN;`M@8:mcOE7('%frZu`>Ks5q:0F6<2imZ`smMcp,CqsG4"@Y;%/
+XT/=_`F<oNp@dp=Phq=%!9X1H!9X:K#Nj;!s7Z0Smf)&F[,165rpBmNmdB6:mJuDImJuDKmJuDK
+mLJCIm`"n,ma]S^p=8U!k54THk55/]p?peo[/B=lk5OcKk54QI6&YGh"cI^nmdB6:mJuDHmf2GE
+s8SkpXT#!rXQKNM!9X1H!9X:K!9X:K!9X:K"MN(Rs."T~>
+$CmnHp@eO*s2G#Wp\"poSG*!Ns8VfdS,i3T"TW"rc%E_/rs\VX!<<(hPh#g%Mdc\]p'.nKec2GY
+ebT4HP\MrJp&tG"Pg+iorr3#mhY[?Wc2[3i@K?8u"TV_jc%E_/rs\VX!<<(hPh#g%Mdc\[p&XU#
+rq6Tbk2+tFeZ@$Vp'7D]K>kOtk,e:M!7h#Is7Z9=!1`cV!6+d6q:,J8p%AC9q#CBf"Ragbc#`1D
+"N<*kS1/s~>
+$HC56mdC+ps2P)Yp[/@gOn/P7qYKdNPlUIE'`\f%_KiTdqXWLW!;?8SOk0QlM%B[^mKTuJf)Mni
+f(o=IST-XamKrq&M8FPHqYKd>^AIs7b5^IX&-2Rp'`\Z!_KiTdqXWLW!;?8SOk0QlM%B[\mLA<q
+k47s&inE,7d\XtKjmEDNk(UC\p?&4:p[/%0r;QfkmeP92SbDIOOnnSDdK#j2mJti6rs/Dko'Y)S
+c?\^C"NG`0`aOA~>
+%efqAk2u]Ws1SHGk3hC"roO^Yk2lZ%pAaR\s7YlF!:KjK!:KjK+R\CSmcFLYMl_!$s7YToS,iTh
+S<VS(k(@+Ck2u+"k3i62#0l;ms39*Vq>UQ(S8.Kkjq$nBk3h@3>)TJ'XT/"V`LQi+.*_eSK44iC
+k3h["mcFLQMl_!$s7YToS,iThS<VS(k(@+Ck2u*ok3i62%drKA^$bUfmcNB_e^^J?roO4KroO=N
+k2u+2joXu5mf)>Kmf)>Kmf)>Um_/=ic-?:V^#nb^job&6k3i62qZ$BR"23jZmf)AKmL/1Fk!=?H
+H\6ZtH\;.V"23jZmf)>NmcN["roWqS#PR<:hLjtQmf)AKmK)J<roO4KroO4KroOFQk.Sb6p8!3~>
+$Da1Pp@eO*s2G#Wp\"poS,iTW`KZVTS,i3T'`_^$c$RG0s7Z-dK)kr6s8VfTMcp,Up'%PB`V/`n
+rU'pQmcNZ^HWi0!p'C_.Mp6Ufs8VfdrVur3r;ZrV!*TC!p([R:Mp6Ufs8Vfd!')boV!dsMk)3CC
+p@\U5]r\U?X9PJjS<T8Fc/nX'SDJUoma[j#p&NYArr_u_k10G1"SV9OeXZC-!4;S%!7h&J"SV9O
+eXZ@,!7glE#57KIc.1'clLkA"3LlloJ,~>
+$HgA:mdC+ps2P)Yp[/@gOT>FH`fZDKPlUIE'`\f!_Ki`hqXWJCGl[m,qYKdBM$sCZmK0E:cMmD5
+mf)JSk0erp2#-JF!"=RuH+NkKo%s?G!4r+/"4@/X!;c*j!"=RuH+NkKo%jBG1^B`>p@@4"$ip"h%
+E>u^ZEC@1V4F$>NOH^cmK]06H)g#TQ0S)2!7LlH"T%iWimRi+"o@rXlI)6tmKnI4lL*s*lL*rcr
+r3/up?LqkSbDIOf(o=NqY'@>daHEdlL"epIE'E<J,~>
+$NKhEk2u]Ws1SHGrT4+JroO^YjoC#6s6djjPjXb9k3i62!:KjK)=HYLmJp^KZu`>Bs5q9#Erc7&
+s8VfLK3A9Pjp:D;k.Tp6s7ZKgp''<KMe_DBroO[Xk2u(3@Y;%/XS2\V`Voi;^&7p5blCoIqrS[^
+!+LSfF0,*8k/@<\0fc&tp@d?q=oeQa"7G=6mf)>Om_ul@[/R-2Un!s>PdJF/joFiHjoFiIjoFiK
+joFiKjoFiKjp&3TSAjpQ[/T1fmf)>PmcN["k2uUA!qu'Er;Zfj"Qm)Rk3i-/$LTp$F*htTF*huj
+r;Zfj"Qm)Rk3i62"n(O8mcN[+rrr,ahWE[QroO4KqrRnHroO4KroO4KroOCP^!69NS:C~>
+17Y-pmdC+os2G#Wp@dqJme6)Bme-XNpA^AAhZ*;>!;>jSme6)Bme6):p?hoiPg+j"rr3f.hL#;&
+m_t]\mYbNSp?qYJme6)Bm]=D,^&PJ>XT,(2S<SYQ@Tk5Sme6)BmdBf:!*YW3K>mii#5/%<]tM[K
+r;[=:!;>jSp?qYB!*YW3K>mii<VBUl>*NbV3MbMi@K?,ip?qABme6)Bk0<r+pAaj[mdArge^^J`
+me6)Bme6ABp?qYBp?qYBp?qYBp?qYBp?qX=UnlkdMrsa$p?qYBp?qABme530rr_u_ma_78%ds&@
+hOO<-p?qYJme6(Mq>UHFr;R;qp=8#ip?qYBp?qABme53+s!$n)k2+YFF8#%qme6)Bp?qYBp?qYB
+p?qYBp?qYB`A+0Y.=_~>
+$HC56lK\Dhs2P)YpZ`(cOn/@2Q/;6&PlUIA'`\f%_Ki`hp@@(SH1q:+`g)\KM%B[^l4Kl8`l>m0
+]!eoIY,.\KJT5*Pq!&@i%#MiH]))-kh>hE(]#p$2!!*W2qW\dq%#MiH]))-khH?CLO_HX/U"4o/
+!;Ga[hT#Ejp'L<Tk2+h?d\Yg_kNW82Tq0oWM;n3n!7LlH"SVEKlI,Y2"o@ZTdajual3Vn$lK7Bo
+lK7B[rVm&tmdANSSbMCLf)G[Lmf!.jqWbfGhV-\/lKSMlH-4-8J,~>
+$MOM=k2u]Ws1SHGpZ;e_KD,>0PhuH.PQ:@<'`_^$XF%&Bp?onaF8u:.`LN1TK44iUjoW6QhYl")
+bm;;5`P&@KP`'#GjpqGqMl_9,p@dpn!,B3\c&;N#!Fc'*jqRl"Ml_9,p@dpn>,5>dC,%`EeUq<2
+pZ<"C`W,u3s7Z0SmbZgNeYM'ajoqj"[-#o7oB,uNs7QHTr;Qons5rIWpuVlCC3+-2C3+-2k5>5^
+pAa:;^%UUfrrDKbrs&21k3hC"MsBF-]uC$FUjr~>
+(SmQ]p@eO*s2G#WmdBf:p?qYBp?hpNpAY(.eWfct!:KRKp?qYBp?qYJme-WiMp6Ufrr4nMeH#=C
+Pa(%uk)3CCme6):p?qYBp7/gtXJDY^S<SqaHYR"n>"U73p?qYBp@dqJ!+Ll2Hc?!a#PQCBhX6;[
+`VoiI=oe!amdBf:p&JQ[c$RG/rttGaMdkQCs5%KF3EcFNp?qYJme6)*c0"`ns8VdGe]lY<me6):
+p?qYBp?qYBp?qYBp?qA*k2uC*F+_`EF6<2ap?qYBp?qYJme6)!rr2ulrpBd:r;RT,m\HAKSG)CE
+mdBf:p720Vs7ZKds7Y"@rt"hkUn"6Np?qYBp@dqJma_.5s7ZKms5"dHHg^Uqp?qYBme6)Bme6)B
+me6)Bme6)B`AsHa.=_~>
+$HgA:lK\Dhs2P)YpZ_e[On/MO"O<.tPlUIA'`\Yr_Ki`hqXWLW!;?8OOl#fkKa[tVl4KT,]!eoI
+Whl8SNJ2XtBk:9qq!&Cj%#)QD]))9ohQd.<mZ!(CrVus-!;bsq!"=RuH+NkKo%l3WA_R1ag1<)t
+$ip.h"Qn:\g@kCCrV?Zjm`ri#mck2"[^sKDl>:sl[WUU%l3Pi<s8)<Smcr7!rrW&flM[:Ll3VIi
+hW!DOhW!D?rVlrqo'61Eq!&%6s8VAu^Ads6o!VP0db`]'lKSMlIE'E<J,~>
+$NKhEk2u]Ws1SHGpZ;MWKD,<E"P&b)MZED3'`_]qZu`>Bs5q:b!;?GWPhu,jK3A9Mjq5;`c-=5P
+`PoO(XJDAVP`'ltpuW+f@Y;%/XS2\V`JX`QmYd"BrVut&!;bgm!+LSfF0,*8k/B'5@c%.bhJ+c*
+=oeB\"4bZQp@eOdp&`dhc0j^$XF#Sik2qSlhSk`Mk5G>Zp&O7Prri&/[(WjBjp<bW@VT@e@VTB7
+qu6fm]sPJ[pZDMU!p6S[rVm)/3E"`%k)8Ne"MN(Rs."T~>
+$CmnHmdC+os2G#Wp[/@gS,iTGS<Vn(U]C&T"TV_jc%F"7rr_rpHN='F"kAk*Mdc\]mK&ikrj;^,
+s.'+Is*FliC/RYHq!J:c>*R9a`W#l>p&KF>rr;os!Fc'*mKESoPg+j"rr3(j0pK'BrrVUl1&C;?
+hUT<@nc&X/hXU"8k0<>nrs%WRUs47-k4A!@ec,UKp&a[UeboIIp&ja>c(t1'$(U_hpAajdpA`\@
+s8VcpmbZ3aq!J.4qYpQ`rVlunk2paMmKCK`Umrla~>
+3QB3ek2u]`s2P)YlK[Nsk3D*ok3;r/!<:o@OkT5k!:&_3k3D*ok3D*klK/'TM8"8HqY'L:!-nSD
+s#//bie\3HlK7Bsk3D*ok+0B#^:q1eWhG]?M1p4t@8JB;k3D*ok2tsk!"=^uH+NkGo%j@d!<3#s
+!#6%FlK7Bsk3D(/%#M]D]))-kR4sc/qu7,j=Z#F+lK76ok17uCiq!+-qSq+Ok3D6olK7BolK7Bo
+lK7B_NO%F+b+ZtCc?XQhlK7BolK7BolK76ok3CCps7Z$SmdAO$rtk7ok1[tKk3D*olK7BoD;*k#
+hV-i?hU;?%47_h%g<,uKlK7Bok3D*of)PceY,//dm^cOl33M9#H0XPWk3D*olK7BolK7BolK7Bo
+lK7Bo`d,_H@=S~>
+3VNKlhVS:Gs1SHGk2tO_hWE\WhW=fr!<:oGPhthm!9W/#hWE\WhWE\Ok2$)AMl_!$s7YTo!-8/>
+rt!YEk(@+Ck2,7_hWE\WhS&m<s3:S_s0Vg%s-spaHWoRgk2,7WhWEYp>)TJ'XT/"V`;jWQrr;os
+'k.1*hWEtWk2$)AMl_!$s7YTF0pK'BrseC"1$7?ThVRDOe^_@7nc'<Bc0!mFk2,7Wk2,7Wk2,7W
+k/BV'r[ARJS;Z6oPh"pQk2,7Wk2,7WhWE\Wk5>5\pAa:OrtY7qhS%e.hWEtWk2&+%@Tm5E@Tm7'
+qYrSLmbYY6k2,7WhWE\Wk5YIgP`(e"p9Zh/(pr`!KBD%QhWE\Wk2,7Wk2,7Wk2,7Wk2,7W]uC$F
+Ujr~>
+$Da1PmdC+os2G#Wp[/:eSG)uIk5YJTrr<#d!<;i^$ijapc$RG0s7Z0:s7ZEk"Q&;@=oe?c!gL(!
+rr<#d$0L*pe]l(H@Q>S+mM,_2Mp6Ufs&)He8pg:3hNWqoS75Y%qX+al@Z/KX`W,u3>)S$iqYpS2
+c2-i2c0h[/p@A4ahTbTY$cW/6k4\iKp:Z*"k47pAec5[Jp&XU3r;QrombZ4=SGDRTPkOhNr:U-@
+r;QrombZ4=SG;LPeb9"Gp?(MoHg:#%`AsHa.=_~>
+I`fZYlK\Dhs2P)Yk2tsklK7BolK/)/o(nL.AcM10s(1KXA`i:?lK7Bsk3;pXKu/,HqYKd>\n1U8
+C&2DliaiZ$k3D*klK7BolB/fps8VfXk2+hCd`TSDBga6/lK7BolK[Ns!"=RuH+Ni/0JkJ'o)IR/
+M5?JC$ioGTs5jjWk3;pTKu/,HqYKbcM1s[[s&*^Vk3D*olK7BOlJg[ss8)cls8)cls8)cls8)cL
+`ocRKk3D*ok3D*ok3D*ohLWDDS[R\'d^FR0hWj7gk3D*ok3D*olK7Bodf9@<o'Yr2des+Tp?pe_
+cCO7_lK76ok3?[[ecj45^:q2,r;SkPmbZ77Sa,A&k3D6olK6[ts731PKoNB<82R1*k2L[KlK7Bo
+lK76ok3D*ok3D*ok3D*ok3Bs7`l__?~>
+*WPiXk2u]Ws1SHGhVRDOk2,7Wk2$)jpA^B>!<;Kd!%m?i!8ckpk2,7_hW=fIK=#^$pAa9oPR.!_
+#RCFeh?[9bhWE\Ok2,7Wk-W[hrr2ulrpKgCs4%h.MfW(Yk2,7Wk2tO_!+LSfF0,'XrYQ\kpAa!6
+MklS@=odFAhVRDOjoAkCZu`>Bs5mLCKAQJ)%;O/Ek2,7_hWDfFXJGR\s"2d?hWE\Ok2,7Wk2,7W
+k2,7N+:oA,+<W*^@[(?Pk2,7Wk2,7Wk2,7_hWE\WrVluns7YUPrt+nlhWD3-hWE\Ok2,5T>#JQ&
+8c_6?qu8_Nmb[*5k2,7Wk2tO_hWFk<mZ_d-F0%AN(o6TnmYfrahWE\WhVRDOk2,7Wk2,7Wk2,7W
+k.T%5s."T~>
+%@j4Kk2u]_s2G#WmdB6:mJuDKmK*BYpAFpjpAY'lmf*7dmL/1FmcNs*!*Y<*K>mii!quZfq#:Kt
+mcNs*k5Oc]k*2sSs8VNTk2+Y=c-<r8=udH!mL\OKmcNs*!*Y<*K>gaNs8VN`;@q*"@K>iYmdB6*
+mJpFKc%F"7rrOWr@f$*4mQnh[k3h["md@d^r;Qcjrr2ulrr2ulrr35sm^2EEmdB6:mK2P=k5OcQ
+k/I&EeaDl(rr_]OmcON:!9X:K"6T%>k5OcNec5@CrUp6Ar;Zfjs5"+5V!d[5mdB6*m[X+H!7h#I
+s7ZKL#M#X<mcNs*k5OcKeb9%CmKD\?F7/2imK;V>mcON:!9X:K!9X:K#NkIB`A+0Y.=_~>
+EQ6.Hio:!Xs2P)Yk2t[cio]7_ioU6#mf3;us(1V0s(12$s(13Pio]7[k2H@LKt_i@qY'L:C%cE?
+C&`&MD>IZ@k2POcio]7_if1C\s7Ya?hV-E+b/V0,@6bstio]7_io9+[!"=RqH+#Q+f#F`d1`")V
+&-1kPk2t[ciW'C@^3R0`p@9VW@J^"&l9)fCio]7[k2Ni;qY'dZqY'dZqY'dZqY'dZqY''Sk2POc
+io]7_io]7_io]6_To$ACcGJl?k,tDp_W'S;io]7_io]7[k2POOs7Z0Wo'Yqor;RT,maft;S`8ek
+k2t[cib?]`]"5>][^sobrt"hkf%/9?io]7_io9+[k19P3.-ce;Bj!tdV<[@.k'?+Kk2PO_k2t[c
+io]7_io]7_io]7_il68d`aOA~>
+$MOM=hVS:Gs1SHGpYH#QKC8d>rVurdrVurTrW)cN'`_EiXF%&Bp?om*!"f/9#S@"I#RCG*h@[->
+ec5[Cp?qA2k2+t>eVeKHptc_c>(`o'X<;8RMeX(O(a'Y<(r^Q*!;bO[!*Y#VH`Zr7mO<KlqYpWb
+6,i]W!OVRurrDclrrDclrrDclrrVo^XRb3XC'YZ@hQ.hK0e"OoMj2cah>l^9rrVook5,,WjoE*j
+h?#E0;Yr`[k5,,WjoE*ih>l^;rs.\-;G&qu(o7-(!/p.!"MMeSp8!3~>
+$`':QmdC+os2G#Wk5F]Jk5OcNjoC;>p&G'[!9X1H"TV_Yc$RG/rr_rps7Z<h!a5TdqsG6^mXqU:
+k/G<Q]sP/JUn!sN;DB$VmcOE7"or+bc$RE%pAY6qHWgF3qsFjm@Y;pP`W,t.0mhdNqu6b5PZ$Z@
+mK0cXk47s?josVCk3h["rpBdKr9a^Mm^3#-rU0^c!9X7[!oEA-rpBdKqsFOJec5XB"7GmNec#LR
+p?q)*hVOdjk54QQPkOP=me6)Bma_:9#km]Kk2+sbmcOE7#3OJ9s7ZKdr;Zfb"Qo.7Hfk=q!9X1H
+!9X:K!9X:K!9X:K"N<BkUa^f~>
+E6?1Kk2u]`s2P)Yio9+[k2PO_k2HAp!;?9cAcJ1Ps4Wn@A`Dk3k2POcioU4HJ\HE<p@dq2!+k_l
+gAflts()<5io]7[k2PO_k(0hDhT!FD]!AK=V4F$J=Z@P`k2PO_k2t[c!"=FmH+#EX`l@hW(]\[e
+!93/#io]7_!"=FmH+*G?SLf3CpA4^e(N#F;io]7_k2PO/io9+_lK[g&mcs6*meuE0k2P6oio]7[
+k2PO_k2PO_k2PN?Tp=d"ij.RpU$C(Wd[etKk2PO_k2POcio]7Ks7Z$SmdBAgrr3l4p?LYog=i+[
+io]7[k2PN7b-nUYZECL9df07ZqY'46hV-\Sk2PO_k2t[cin"//qBt-><Ces;mdBB*k'>tKio]7_
+io9+[k2PO_k2PO_k2PO_k/Mhhb$ff~>
+$NKhEhVS:Gs1SHGpYH&RHN<d>p@nX_h@0HgH`V:amdB5V!!iQ9rWiW<#RFT6ptcC[c,K,-hUU0$
+c,I[$]`Ngq;Y])T!+L;VF/0YCMhCh7!s!CG!;bO\!+L;VF/86lS2#BIpA=jkC6VWmh?'e@k47s?
+joO>7o%jQ^#\r5QeJS9.s!\$m.4Mt'h>l^:rr_upp?);Q!;?BZ!4;RY!@^Y>3<Lur3Tg8>!;?BZ
+!4;OX!9X7[#Mr?=.2\<Cs8M]lMsB.%^!69NS:C~>
+(S%9Uk2u]_s2G#WmdB6*k3hC"k3`56me6Ykk3hC"k3hBomcFLIMp6mfrr3&nhL#,!14ra1mcNs*
+k3hC"k(BJ"hUTlq`Po3kXK84n8hh1Nk3hC"k2u*o!*Y<*K=t1_s&*#ur`T;"r`]:$'^k,OmcNs"
+!*Y<*K>%<b;M0=KC;'QF$9?W:mcNs"k3hB=ptc#5qq_>'rn\NgmcNs*k3hC"k3hC"k3hB^m`">V
+c2[gomem)"hX9Ook3hC"k2u*oma_@2s7Z0Sp=9-A)#!Cck2tNrk3hC"mcNs"SF6+=p?qYBp=9-A
+&GGP[k2tNrk3hC"k2u*oma_(3!;?BZ*-:Q1mcNs"mdB6*k3hC"k3hC"k3hC"k/B'NS1/s~>
+$HC56io:!Xs2P)YpYlV^L$&+"p@apScMu2iRJ5\U!!IkeH+*G;o%ps'Sc@"8cMsGd"9A5V&V6sY
+hU9Qd_S3IaWiDbh<AY]jiXZ"tJ\HE<1s3fp:f(.p<D`ZprW)fS%0-ff^3R0\nkam_JSD^nrrP1*
+"T%*]Y1hU\g=H5V!oDYfrRqD*g=FuOo&:1&M4rqgS\E+3ZKgT'hVssriX"!4p@e(JmdAO&rs/8g
+k3CschOXK%$"^QJWiiA)WijeLrs/8gk3CschOXH$!S7;Mq?t/C82r"_ipQ7"l?V[S"NG`0`aOA~>
+)ts<Ne^a]5s1SHGhVQf>e_\j5e_U:QhX9h*pAP$lhYmLLe_\j5e_\j,hUMU(K<0-imdB5VP]IBA
+&Dds(&:7R\hUUK>e_\j5eZ?a/mcNB_e^_ph`PoO0HX]n0e_\j5e^`O,!*Y#VF/0q:M\uFk!*]:u
+rW!Yhe_]05hUMU0K<0-imd<u*H\6(Hr;R*aeH"IVhUU05e[5,.!9X18!7h)*)k>d8hVQf>e_\j5
+e_\j5eIW"Ee_XaP(dT8n+T<f!3Sr<Ce_\j5e^`O,hWFb9!quZVr;Zfj%IWrX^"(uihVQf>eM0)\
+0`^A6s8Vd%me6(^e_\j5e^`O,hWFe:-bVMh(_AFipAaj[KAP/8e_\j5hUUK5hUUK5hUUK5hUUK5
+]uC$FUjr~>
+(o3Z^mdC+os2G#Wk2u*omcNs"mcFM-me6>R&anfLk3h["mJp.;c*W_cs7Z0\s'ta&k3hBomcNs"
+mW4VNe]#M7[&g@)Un![65p.$,mcNs"mdB6*!+LT*[$42_`DZF0mdArgc-<r8Zn^_2k2u*omJp^K
+c*W_cs!`;9H[CBtC4lP=;OgYImcNs*k3f>$c->k!2pKmtUuq+-k3hC"k3hC"k3hC"^&P1I[-mt5
+k3i9;k2u^;hX9Ook3hC"mcNs"Un"6NUn"6Nec,RKpAOFZjp[dJk3hBomcNr%mdBfJmK3+Mec,RK
+pAOFZjpdjKk3hC"mcNs"ec5[Cq>VT2mdB4ak3hC"k3hBomcNs"mcNs"mcNs"mcNrV3LlloJ,~>
+$HgA:io:!Xs2P)YpYlGYJ`>t_AS'T<rr3)Cg1=jkir8udICc8+`q&QSARX<<rr3,Hg1=Oipu2[,
+Tpa?C^:(>MWhH!_PlaW1*;JM.!"=:eV1C>?Ki%L:mcNBWb/V0(Z7u.7'`\Yj\tsttngJd'I=6g#
+D1V_<:n:V_iWZ@-b/V<<p;6jL!m\rVo&:3pR:VM3S[OO7WnO;hWku3]p>Yn=$e#(TqXX(BlK7*c
+Sb_7Z@ATZoTr"HZU!iu@qXX(BlK7*cSbV1Uf)PUC_Gs,`1`-WPip,gkH0XAl`dPkL@=S~>
+)?9EThVS:Gs1SHGe^`O,hUUK5hUMUIe_]He!<1jR!#=A@hUUK>e_U:(H`WHH[-$5a!!!91rndV[
+rr<b`hUU05e_\j5S@u;le^_ph`PoO(rj57<>#No-e_\j5hUUH_@XG2@C)DRq;YL.YmbZgFc+Uft
+1"G.2e_\j5!+L;VP\RSf.=6,_H\6rcKE$R%S5Rnoe_]05hPA]Hc1An5c.1(/e_\j,hUUK5hUUK5
+hUUHg!#THC(_B!X+;cPc=r8BPhUUK5hUUK>e_\ii[(Wi[[(Wj/rVmB$s7Z0Sp9`],hUU05e_^'M
+!9X7[&GH.tp?qX]hUUK5hVQf>e`Ql2#e`5I(a&eY.IR3/*/iA(e_\j5e^`O,hUUK5hUUK5hUUK5
+hS%2-s."T~>
+$CmnHk2u]_s2G#WpZ;PXMZEJCs8(j_!)eHgeZ>Rso`"pbpuW00Mi5j!]tLeSUnjNNPaj`V&GYB&
+!*Y#oeZ;[K;VpR(mcNBN`O)G*;?6RU'`_Ei`RV&ceN%t[HWjToC2-pEMcuqQjoi'1`G.F,0a0Ql
+K>kO"o&]tSpAY'mhTc&^#63QBk2--gmcFN"rr<#l"n)*PmcL>@joCqNmJut[mK*%3rr<#l"n)*P
+mcL>?joEs.rrDcks8MEdF6_lj`A+0Y.=_~>
+$HC56hVS:Ps2P)YpYH#QJH4hDpAY,(qVM5P$@TA"TomLgC%hDsqu6`op0maQ&TsA(cGI0$Y-+Up
+R@02&81YVQhA$#!IC@"d1r;*+ip,ggf#k_0Tp8:OqVDqe%"5S$TomJSI9Chu=`%ke=\OZPU&*UK
+Y/8%i2"iX'1]r0C\tS]O&9WPlTrsBCg>8C;[bfl3_Q*%\$e#(Tp@@eBmcNZkSb_+V?(I[[Tq.mJ
+U!iu@p@@eBmcNZkSbV%Qf)PT`=\(NTarCB]/Df[WH0X5h`d,_H@=S~>
+$MOM=e^a]5s1SHGpXK?GErabh!!M0'hTapU!;b4P!)e0>[#9:<jp:qd#i<h_c/&^+#QXYM&Y-58
+hVQf5c-=5H]tLe[F';32eJ/'fH_e$,+G1fnk3h["e]l(7Um+IOqUH;\>'m'PMgMfkHWkc">'"Fn
+>"X]VV#&UEXMr.n3VG023AH0*]q"ZD!)!4j$j[DRc.*XRK@SL4(jk]$!9X4Z"nquip?oWieGq&o
++9:R%rrr,rp@dpfpsfr<s8Tbm.2]/2&-)\bme6@4lI?$N`W,Y-J,~>
+$Da1Pk2u]_s2G#WpZ;SYKBDUipAasN#lm84SAia[Ut,25rrMfnpuW/tK6tkV]sP/BUn!s>P`%O=
+&GYB&!+L#>`Q_#g;Vp9mhVQMr[&g'<+9;9#'`_]aSAia[>(^"Cs5nr";Gp[Yh?X,Xjp&f<Zr.0%
+Pl@0\Pamu&Mi0k4@_JkVn`BtU]u@A'roOI9p>4ro`W+3Njoj67s7Z0bmf2DLSGD:KPj[]5mK_nB
+ma_@;p@eIQs5j<OpuVS,qu?Zhrr<#d!TnaojoiX`S>7Ta~>
+$HgA:hVS:Ps2P)YpYH/UH.(9tAS'T<rr3)Cg1=jkhZ!Q`EKR]DV3T'WAS'T@rr3,DemVhaptcTs
+NJYfl]!AK8Tq.U6NK$1G)#2r&!"<k0[_=GD:u9pchV-,h[]6$8+9;8p'`\Y^Og`!#=b0S<s5nkt
+:f(:WedMQThA*c1[SRB'Q'mo*Q'mbsNJTn3@Ci;@o%jQ$JSAtHY5[8_OfH:ThMK+CmbS?"s8VZ\
+mdBB*k2Ms-h@s+\Q'mo*Q'mocs8VZ\mdBB*k2Ms,h@S9<qK5=cY4hS/&-)^(lK3BWh?:iH`l__?~>
+%KH.HhVS:Gs1SHGe^`OUeH"J*eH>k][(X0O!<1jR!<:R\hUU05e^XXcC4i=`MgMhM!<*9'h?aGf
+#QOkThUU05rm_Y<PcUtCe^_ph`PoO(['ZoL8kT*57c)\GhUU-V@VUOkX;FQ%hVRDOhTa$HXIO#J
+!7frVe_\j,!+K\qUo]JXK3FN>k(>rt;Hc*;#QWE3e^`O,e\/Z';@#mZrgXOaS<T7rMa7n`]r\<c
+hUU05rm_),e_^;U'&LlB(_AE[e_\gn&?OF=8e?(#rm_,-e^`OUeH"J*eH"J*eH"b1rt"i'p@dqJ
+[+3^`e^`O,eKFZ)!9X7[%/0_pp?qX]e^`O,e_^;U''B5o=t(;is8U=T!!&hgp5@JXrm_,-e^`OU
+eH"J*eH"J*eHas]e\06$s."T~>
+)k<]YmdC+os2G#Wk2u*omcNs"mcFM-hVPV\!;c^&mcNs"mcNs*k3hC2!!d8/['ZXZeU./mrr=A5
+k3hBomcNs"mUC6Y]tLe[XK7q^Pa%)a.2WWYmcNs"mdB6*k5G>a@[p=ge]n*Ms32%e[%s3a!3G>N
+k2u*omcOKK*b(YH3C-:2me6)Ks%5m]PZjU>mcNs*k3gd,XIPg*r;Zfjs6_r)[$7)VSDNDrk2u*o
+mcNs"mcNs"mcNs"mcNs"mcMdo^#nb-p;QI^mcNs"mdB6*k3hC"k3hC"k10J2rV$9Z$g+8Qk3hBo
+mcNqik5OcKk5OcKec,UIpAaOgk+qG-mcNs*k3hB^qYp]ls7ZKdrpCbIk3hC"k3hBomcNs"mcNs"
+mcNs"mcNrV0r1<gJ,~>
+$HC56io:!Xs2P)YpYlV^H,d^tAH8.ucMu2iRJ,Y>!"]j0V4j$_\p9kHcMu&\OT5CUiXoUEH+pkq
+Y,.tcR?<VgKesb`pYu/P&J13a0[e+tf%/-d]!A#t8-#@Zir/oi&='(K5Y1>*mcOQL84ZF:<L*F?
+("T4]SX%4pqZ$Elp@@M2hR8];Tpa?niWk1;NT/ZCV4m>:$e#(Kp@@eBmcs)sSb_7Z9T>="Q'%>o
+Q.#^+p@@eBmcs)sSbV1Uf)PU;?*=&#p@c?7Q1!r&H0XAl`d,_H@=S~>
+$hjV>hVS:Gs1SHGec">)ec+D0eGs'SUm,']!!(mT!<1gTebe2'ec#OR@Y9ntF.AJ9rWiP]#lO`(
+hUVM[(=h9+S=IjK`PoO(['Zp9Unh0d9&AFTqq_>'rW!R?K-2#]c/."$c-<r/Umt$WSCRMn!7h&K
+&n6KX3C-:2me6)Ks%5m]PZj=%qq_M$XK7q^c2@VApAaOfhR&N;Un#][hVQf^h>l+(h>l+*h>l+*
+h?qfihD#RNhUN_SHiDk%ebe2'ec+D*ec+D+e`Q`.rq6E,hUVM[!\"ZtrX]/K&.n"#s8M]n^#%<:
+h?MNms8VdYXSr/(bn-EFp@a-hrn[Y*qq_>'rn[Y*rn[Y*rn[dk`W,Y-J,~>
+$Da1PmdC+os2G#WrU'[JrpBpOmJqU@rW)`n!Uf+LmK;V>mcON:#Nc!d@Z.%P[/Bt(pAb-nmcOE7
+"m57@X?elG;Z05d5m97c#aFc>rpBmNmdB6:mLA:Y!(pG>`Pp*@`O*"Jq#LE^!9X:K''9/o>(\O0
+me6)BmQj`CK2SM8rpC*TmdB6*hSl:dpA=mimf2DQc'4a3hWF_'!9X4I!9X:K!9X:K!9X:K$GHJi
+Unm_7hX9gorpBmNmdB6:mJuDKmKD\?ec5[JpAaR\joM"7qsFOJmX+ep!nI>NrV$9Zs5j?Pk5OcV
+k3h["ma_@;pAajdrV$3X!Tnb.mJuDHmJuDKmJuDKmJuDKmKMal3LlloJ,~>
+$HgA:k2u]`s2P)YpZ;MWD4UY+#\F%(gAflps(1ibrr<K>Kp@XgAbqhGp<Jg#AbP6uV*I"?:f'hV
+845^.4?PSC&;g&Arr<B[<R/J$b/2$(ZDI?sq<%\W%h*kC!:'";mcm&68;1';RJGtJg:F,SpAP!u
+qY'@BinhhCRBkE-jp-m:JU(spJ^3]G$e#(Ko()5:lK[NkSbV=\86&em=]JU)df9%3o'Yr2lK7)s
+puW.=s8)Hcp@e(No()5:lK[MWlK/5hIE'E<J,~>
+$NKhEhVS:Gs1SHGpYGrO>(cJJo\TTJ$!MCsF*e/m#QP//!;>7][!QP?H[Bg\F*htLC3+,f6(IT(
+rr<BC;U*2"c,IZ/[&!Ktq;2,O%pFT?!:KRKp?k4E8qU$;Pkj/=e[2-JpA=mimf2DPc'4Hoc04!h
+C&efC0`VcumbRs+rVlols8DWk[.rJX.Jb.ek5G;\pAb*b!4;OX!9X%UrUp9[MsB.%^!69NS:C~>
+'V(sRp@eO*s2G#WmdBf:p?qYBp?qn[!Uf[\rrDclrrDclrse\ip?qYJme6)Bme6)BrVuq5rr3*$
+s7ZKdrr4VEme6):p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp@dqJme6)Bme0PlXK;E."0A;g
+SG<-kme6)Bme6)Bme6V[(g8pS3UZSq>!^[UPcX<Hme6ABp?qYBp;R"(s6fpLs5"mCeYMX,me6)B
+mdBf:p?qYBp?qYBp?qYBp?qYBp?q@UrVoBpme6)Bme6)Bp?qYBp?qYBp?qYBec5@Cp@dqJmdB55
+p?qYBme6)Bme6)Bme6)Bma_@2s7Z0Sp?qA2V"X6Mme6ABp?pK+s8DZkmMp<9p?qYBp?qABme6)B
+me6)Bme6)Bme4USUmrla~>
+$HC56lK\Dhs2P)YpZh_Xs69r&s(1J,s(1J,s(1ferW!<?Abog8@J49tAcH>ml3]A^WiEA-Y,\=d
+Q2(FSlM^b`%/r'hk3ap'4OP43V>'6bk/-][mdff2io8\CcH`9Jl3>sZQ(=>&JaM_1df9%7o()5:
+lK[B"nELD0s7Z0Wo'Yr2lJeB0l2]E5s8DfopAa^`mJqOtl3,+Pb/Rk?~>
+%efqAk2u]Ws1SHGk2,7WroO:=k2uXCs5s:\!9X7\!9X7\roO=>k2tP"joF9;k5G>_;@!7.r;Zi[
+rW)r[s5!e=hYuX;hYuX;hYuX;hYuX=hWE\ojoF9;joaK&k2-+"!8d_;$6[$`XL,(9XJDAVq#CKQ
+k2-+"!8d_;rW!R73AEP^p+]`:eJO4?k2tO_k2-+"!oE(YrV$9Zs5s@<"jPSnk2tP"joaK&k2-+"
+!oE(rroO4;roO4;roO:=boluc":/2nk2-+""5`2&hYuX;hYuX;hYu[8rrr,rp@dpfroX7;!Tr8<
+joF9;joF9;k5>5_pAaj[m_/V^"5`2&hYu[0rrr,rMrs0YroX7;!Tr8<joF9;joF9;jp'])]uC$F
+Ujr~>
+"JhPJmdC)J!:KgZ!:Kj[!:Kj[#gKa$p?qYSp?qq[s7QHmrq6H^p@dqRp&OO[p&OO[pAY*orrDKd
+s8Vcms8M]ome6ABrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj["7GmVmf)n[mf)ncmN>+o;G'hZ9)_*V
+3VrgVp&OO[p&OO[p(d#hp?hn\;PZ<-3B:95;P`1Cme6ABrq6K_p@c2$rNuL("Ji-#mdC)J"7GmV
+mf)n]me6)Jp&OO[p&OO[p'U6]p?&0i]r^r$mf)n^me6ABrq6?[rq6?[rq6r"S>;[NS>;[NS>;\K
+p?qYJmf)n[mf)n[mf)nlUn"6NUn"6NUn"6Np@dqJp?qqR'%M&MF*htTF*htTF*htTF*mWKrq6H^
+p@dqRp&OO[p&OO[p':$Zp;K%^Ua^f~>
+!m8N2n*U8&Y0-b3#\EGlAcH?0mUbkTrr<=5!:FFuAa\ttea<J]9M#.Vs%*/X!C/L=!;,[^iW&sT
+U&HkP4B\4TS_!Q'!U@,jY5YI#V#dUYjmE<#Bl.F<k3_U0Sac(?SbVUQg@9IRmKCOX`l__?~>
+!rqu=n)a\jUrE>q!W_BFrW)u\!!)KMrr<*+!9X7\s5j:]e`HrV8kN"[9)_*V3VrgKjpg/I!(s%I
+0f_6tS5PTrp>u@^r2f^i!8ci""iW2%&7XM`jpSl0]sPJ[]sPJ[]sR:k$b`p\[(Wi[[(Wi[[.i\n
+K8YA?K8YA?K8YA?K8YA?lK/5_c1_1-J,~>
+H(:Zbs8VfmpAajdp@eO[s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmpAajdpAajdpAajdpAajd
+pAajdpAajdpAaj[s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds8VfmpAajdpAajdpAajdpAajd
+pAajb!.=h?pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0ds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7Z0dpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0ds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7Z.\s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds8VfmpAajdpAajdpAajdpAajd
+pAajdpAajdp@eO[s7ZKds7ZKds7ZKds2?^gS1/s~>
+!liB.MXp]GJb$GD"NG`0`aOA~>
+!quZ5rU'[JrpBdKrU'[JrpBdKrpBdKrpBdKr9aRIrpBdKqsFIHrpBdKrpBdKrpBdKr9aRIrpBdK
+qsFIHrpBdKrpBdKrpBdKr9aRIrpBdKqsFIHrpBdKrpBdKrpBdKr9aRIr;c`_!9X:K!9X:K!9X:K
+!9X4I!9X:K!9X1H!9X:K!9X:K!9X:K!9X4I!9X:K"6T%>k5OcKk5=WIk5OcKk5OcKk5OcKk5=WI
+k5OcKk54QHk5OcKk5OcKk5OcKk5=WIk5OcKk54QHk5OcKk5OcKk5OcKk5=WIk5OcKk54QHk5OcK
+k5OcKk5OcKk5=WIk5OcKk54QHk5OcKk5OcKk5OcO]uC$FUjr~>
+!i2>Hrr2ulrr2ulrVllkrr2ulrr2ulrr2ulr;Qcjrr2ulrr3)os8VflrrDclrrDclrrDcjrrDcl
+rrDcirrDclrrDclrrDclrrDcjrrDclrrDclrr_ups7ZHl!;?El!;?El!;??j"SVlq!!)or!;?El
+!;?El!;?El!;??j!;?El!;?El"8;cppAY'lpAY'lpAY'lpAFpjpAY'lpA=jipAFpjpAY'lpAY'l
+pAY'lpAFpjpAY'lpAY'opAb0drr2ulrr2ulrr2ulr;Qcjrr2ulqu6Zirr2ulrr2ulrr2ulr;Qcj
+rr2ulrr3)os8VflrrDclrrDclrrDcjrrDclrrDcirrDclrrDclrrDclrrr,83LlloJ,~>
+!m8N2M>$rLJbH\K"NGl0b$ff~>
+!rqu=M=1BDJaU,;"MN(Rs."T~>
+!h?&@JcC<$_#FPV0r1<gJ,~>
+!liB.Jbjro_"n2RH-4-8J,~>
+"nqu8p@dqRp''mXp?qYBrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj["7GmVmf)n[mf)n[mf)n[mf)n]
+me6)Jp&OO[pAaO]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6H^p@dqRp&OO[p&OO[p&OO[p&a[U
+mf)n[mf)q[mK*%Lrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj["7GmVmf)n[mf)n[mf)n[mf)n]me6)J
+p&OO[p&jaVp?qqR!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj["7GmVmf)n[mf)n[mf)n[mf)n]
+me6)Jp&OO[pAaO]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6H^p@dqRp&OO[p&OO[p&OO[p&a[U
+mf)n[mf)q[mK*%Lrq6?[rq6?[rq6Qap:\HFp8!3~>
+!i2>HJcC<$_#FPV3LlloJ,~>
+!m8N2JcC<$_#FPWIE'E<J,~>
+!rqu=JbFZg_"IoEc1_1-J,~>
+!h?&@JPq%s^et=80r1<gJ,~>
+!liB.JQ78$^f:O;H-4-8J,~>
+!quZ5JPq%s^et=8`W,Y-J,~>
+"f.YK;U%N,3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE
+3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<MQ-3C3X)!($TE!($TE!($TE
+!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE
+!($TE!($TE!($TE!($TE!($TE"$nq-62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikJ5rgqSbsD=h!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE!($TE
+!($TE(dU/B.AV<CH\6ZtH\6ZtH\6ZtSGtU>Ua^f~>
+"Nn`4<Q9SLO>m7d`l9tQ,b94/H$ssdH$ssdH$ssdSc=,Xb$ff~>
+"TS2?;T8Vq!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5
+!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=@2!&=I5!&=I5!&=I5!&=I5
+!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5
+!&=I5!&=I5!&=I5!&=I5!&=@2!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5!&=I5
+!?fA\3<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f5
+3>E[,F*htTF*htTF*htTF*j/Oc1_1-J,~>
+"Iu8B;ZD=AOS/^>s2Oa5P^E3*s7ZH["ag8(Umrla~>
+BZA2?<WDLXmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:md=QTmdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:md>/emdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mZ%87o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'VK_qYL6gqY'dZp@@YNl32J5H-4-8J,~>
+B_MJF;ZGnIk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2p.@k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2p[Ok3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k)99%mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcKFKp@eO[p?qYBpAO+XhK/_9s7W7=~>
+"/MGI;M"k/rrAS.rr\dDp@e=^$23fLp3Zg"S>7Ta~>
+"3SW3<It12rrA>'rreU8o'ZAOrsJVjk2,BKs*_o0@=S~>
+"98)>;Z6UqpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpA=jipAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpA=jipAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+Pl:U^pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'p
+P^DidpAY($pAaj[k2t4VF8sMYs."T~>
+".Z/A;M"k/rrA;&rr\L4p?qbV$23NDmXtNoUmrla~>
+"3/K/<It12rrA>'rreU4mcsNCrsJJfhW!gGs*;c,@=S~>
+"8;c6;M"k/rr@trrre7$k2u+1s8VfmmKhA"k'R-Is7W7=~>
+"/MGI;M"k/rrAS.rrJXBrq??k!!*#u$23NDp3Zg"S>7Ta~>
+"3SW3<It12rrA>'rreU8mdBZFrs\u.s8)0ChWfCdIE'E<J,~>
+"98)>;M"k/rrA;&rreR5k2u+2rs\u.p@dY*e`LrQc1_1-J,~>
+".Z/A;Z-Rm!<<'!!.k0?rrA;\s82lsrr<&Jrr\L4p?qq[rW)uu$23NDmX+sgUmrla~>
+"3/K/<W)mp!<<'!!.k0?rrA2Ys82lsrr<&Jrs"U2mcsNGs8E!+s7Ym;ip(ghH-4-8J,~>
+"nqu8;ZHIis82lsrrE,nrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ul
+rr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr3)os8VflrrDclrrDclrrDclrrDcl
+rrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDcl
+rrDclrrDclrrDclrrDclrr_ups7ZHl!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El
+"nqurMuWMMrrDcj!<<'!!<2uupAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'u
+pAb/NF7/2YpAb*l$hj#Ne_]/(s2G$3Ujr~>
+"/MGI;Z-Op!<3#u!!3*"JcD8?!1`ue!!)lq!!(LJ"e:5=pAb0j!"/c"k2uAas#HUF.=_~>
+"3SW3<W)js!<3#u!!3*"JcD8?!1!K^!!)lq!!(LJ"dON(mdgDU!"/SjinisGs*_o0@=S~>
+"98)>;Z6V$p&P-mp&G*m!<2uupAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpA=jipAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpA=jipAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+Pl:Ubp&P-mpAY'pp&P-mpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'q
+P^DQTmf31b$MNW=e`LrQc1_1-J,~>
+".Z/A;Z-Op!<)p!!<3%Ms.')hPl1O]!;c]q!:^!g!:p-i!;6?pP^E,ls7u^%p?(N*KE![%S1/s~>
+"NJT0<WE$o!!)uo!W`&sJbko5!KmE\q>^Nlq>^Nbq>^Ndq>^Ngq?2q+mcsNB!"&)Mip(ghH-4-8
+J,~>
+"SVl7;ZH^h!!)uk!W_ooJbGW-!K7!Vp&G*hp&G*^p&G*`p&G*cp&p:pk2u+.!"&)DhWB1b`W,Y-
+J,~>
+"/MGI;Z-Op!<)p"!<3'!rW)uurW)uurW)rtr;cisrW%NL\,QGur;Zcsqu6Zss8E#ts8E#ts8)fr
+s8;ourrE&u!<E0!!;?EpS:gP/p]1?V#53ED3LlloJ,~>
+"Nn`4<WE$k!!)uk!s&#ppAP'lpAP'lpAP'kpAG!jpAP&Cp:'_rQ2ggVrrDri!<Dim!<2]k!<2]h
+!<;ck!!2cnrq6?mpAP'cp&gS.mdBiM#ia_+H2i<4b$ff~>
+&c_RL;ZHIYp?hqKp?qVSp&Ogc!!2f]rVuuepAP$np?qYQ!!;T^mf!2Kme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bp1!I`me6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bp,VR7me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)BPlLIFp?hn\p?qYBp?hqKrW!#fp?qn[!q,dMqZ$Zjmem+ip&OgSp&Ogc!"S_jp?qYB
+p?qYBp69pdk4eo^hUUb0s3:9;S:C~>
+"Iu8B;ZHai&H;b(pAY*mp&G*dp&Og[!!*#l#ljVl!<;`mpAb-c"9A/h!!*#l!<<&l!<<&l!<<&l
+!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<;ri!<<&l!<<&l!<<&l!<<&l
+!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l
+!<<&l!<<&l!<<&l!<<&l!<;ri!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l
+!L3W`p&Y3erW)rk)#jR9pAY-dp&Og[!!)`d!!)`d!<;`m!<<&l!!*#l"9A/h!<<&l!<<&l!<<&l
+"dFB-mf3=b!"/c"k2u)Ys"U=>.=_~>
+"NJT0<WE$g!!*#hrr<Ar!!)T\!:o[\!;l<h!:o[\r:0sjo'ub\Jb$>A!KmE[o)8Xfo)A^ine(rn
+nc87O!!)T\!!)T\!:o[\!<)Hg!<2Nk!:o[\p$r9KH1'tks82j(p?pesl?WDTb/Rk?~>
+"nqu8;YK8PmJm7dmf*7omJm7TmJuD;!!)0\mL\OK!:JtLmdB6*mJuD;!!)0\mJuDKmJuDKmJuDK
+mJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmK;V>mcON:!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K"6T%>k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcPk3hYqp?)AB!9X7\!9X:KrrE)e+9:it!9W\L!9W\L!9W\LmcFKLmcNs*!9W_;!9W\LmcON:
+!9X:K#j1RCMf\=Kme6PY$L[',hVN>R`W,Y-J,~>
+"JhPJ;ZH^hquHcj!!*#l!s&&g!;cBk!;?*dr:U*jrq6<lJbHVI!M'2dpAY-lp&G*lp&b<gp&P*c
+!s&&g!<2Zo!;?*dr:U*jrq6Eop@\LZp'$t=p@eOdqu@*(p?(N2HiH*rUa^f~>
+"Nn`4<WE$cquHcb!!*#d!s%cW!;c*c!:K7Tr9aObrpBadJaU&9!L<]]mf*:dmJm7dmK3IWmK!7S
+!s%cW!<2Bg!:K7Tr9aObrpBjgmd:)JmKJl(mdBZGqu@*#mc**gH2i<4b$ff~>
+#ljVC;ZH1ImcOEI>3>5QmcNp;mcFN3mcNs"mcFN3mJu\;mcNp;mcNp;mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs*@cm+@mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs*D!(0JmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNr%s6f%;k3hC"!!)0LjoFQ3joFQ3!:K";!:JtLk3h@3k3`6;k3hC"!:K";!:JtLk3hC"
+k3hC"k3hC"P^DQTmf31b$MNW=e`LrQc1_1-J,~>
+$CmnH;ZH1Ymd:)KrpC6hmJu\KmJu\K!:K:Kmem.cmKE4`!:KRX!!2N]rpBd[rpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBm^mdBfJmJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+"nqASs6fU[mMtrgmJm7TmJutKmJutK!:KRK!:KO\mdBcKmd:)SmL8gW!:KRK!:KO\mdBfJmJut[
+mK`IRS9stts8Vus$NKh^k3dm%0r1<gJ,~>
+"NJT0<WE$_!!)o]!!*#`!s%WO!<)3]!<29`!<;?]!.jFFl2d1Mq<It[s69RarosRclKSBKl2q%O
+l2^hK!s%WO!;u*^!<26c!:&hLp$)^GH1'tks82j(p?pesl?WDTb/Rk?~>
+$hjV>;YK88hW=h#hYuXCh>l^#h>l^#!<2*\hYdHRk5PG]k5,/YjoF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joaK&k2-+"!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!8d_;!8d_;"5`2&hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX@
+hM_*ik2-+"'].sP!8ci<k2,5#k2$+#k2$+#joGDC"9@TH!8d_;#i5RDk2$+#joGDC!8d_;!8d_;
+#2Y8Zk2u+*quHcb#h@eoHiM(bp8!3~>
+$`':Q;ZH1Qp?hqKpAXIcp&OOKp&OOK!<2Bd!<2Bd!<2Blp?hqKp&OOKpAXI[pAXI[pAXI[pAXI[
+pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI^p?qABrpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpBd[rpBd[rpBm^mdBfJmJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mKN<Ss6f=KrpCKomd:)KmJu\KmJu\K!:K:K!:K7TrpBmhmd:)KrpC'c!:K:K!:K7TrpBd[
+rpBd[rpBj]S:gh7!<;rs$NKh^k4X0%3LlloJ,~>
+BZe>C<WD@HlK/*/lK7Bol2^,3l2^,3!9WS/!9WS/!9WS/lK/*/l2^,3lK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolKVj@lK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolKW3JlK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolC%\;k3D*ok3D*o!:&\Hk3D(/k3;s3k3;s3joFQ/joFQ/!:&_3k3;s3k3;s3joFQ/
+k3D*ok3D*ok3A@_mdBZGqu@*#mc**gH2i<4b$ff~>
+$NKhE;ZGn9k2l[#roP3WjoFQ#joFQ#!9WG#!9WG#!9WG#k2l[#joFQ#roO4;roO4;roO4;roO4;
+roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO=>k2tP"joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joaK&k2-+"!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;"lAC+s5r2;joF9;jqn*\joF9#joF9#!9W/#!9W,<k2tM#k2l[Cjp^,/!9W/#!9W,<k2tP"
+joF9;jp0c*P^DQTmf31b$MNW=e`LrQc1_1-J,~>
+BUkkQ;ZGnIk3`6;k3hC"joFQ3joFQ3!:K";!:K";!:K";k3`6;joFQ3k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2p.@k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2pIIk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k+)J6mcNs"mcNp;!9W\LmcNp;mcFN3mJm7LmJu\;mJu\;!!)HLmcFN3mJm7LmJu\;
+mcNs"mcNs"mcL$dp?qYMrs7cTmX+sgUmrla~>
+BZA2?<WD(@ioU7'io]7_iW/!#iW/!#!9W;'!9W;'!9W;'ioU7'iW/!#io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io4G0io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io4e:io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_igKi+k2PO_k2PM'!93,@k2PM'k2HC#jo>D@joFQ'joFQ'!!)0@k2HC#jo>D@joFQ'
+k2PO_k2PO_k2MeSmcNs6r;R-#p>4foH2i04`aOA~>
+"SVl7;YL(G!!)oQ!!*#T!s%37!<1gT!<1gT!;t[U!8cQ4J_mcj!L3<RhZ!TUh>dQTh?j8>h>lEh
+!!(m4!<1gX!8cQ4!<(aZ!8cQ4!8cQ4p"fn;F7.oIpAb'a$1?@#hK/_9s7W7=~>
+"JhPJ;ZH^`!!)oa!!*#d!s%cW!<2E`!!)Hd!<)?a!.jRJmK'-`rU0R`rpBadrpBadrpKacrpBad
+rpKdds6fgc!:Kgd"muBYmJm7\mK',9rq?0f#km][HiH*rUa^f~>
+)Tp'J<WD@HlK/*/lK7Bol2^,3l2^,3!9WS/qZ$W]rW!&ck3D+-!'BK.lK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolKVj@lK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK7BolK7BolKU%blK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolCIt?k3D+,!".lRjoFQ/joFQ/k5G>fk3D(/k3D(/!:&_F!!)<`!#Fi"lK/'HlK7BolK7Bo
+lK7B&II?CcpAOgqpA4gWlL&rtIE'E<J,~>
+"TS2?;ZHaY"Ps.@k2-+"!!*#\"p!fJ!8cl#qZ$WYrW)r[!8dYSroO4;roO4;roO4;roO4;roO4;
+roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;qrRn8roO4;roO4;roO4;roO4;roO4;
+roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;
+roO4;roO4;roO4;qrRn8roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO6Os8M-\
+hY[BRjp9fDk2tM#k2tP"!".TFjoF9#jo>DDk5>8[k5G>ajoFQ+!!*#\!8d_;!8d_;!M"N9k5=o\
+me6ABhX5Ibc1_1-J,~>
+"Iu8B;ZD=9OR<.Fs2OI-UjN(6!<;ujrVm%Rs"U=>.=_~>
+BZA2?<WD4Hk3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok2p.<k3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok2pIEk3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok+2P7lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK4X_o'YrFnc8+Wnd5$iqY#47H-4-8J,~>
+B_MJF;YJu0hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVM`(hWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVN)2hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhN[`jk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2)>DmcNs"rpBjMmdC)J#4?j<`W,Y-J,~>
+BV_.Y;ZHIYp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp@_t`p?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp@`n%p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp8n;fme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme3`XH\6ZtH\6ZtH\6ZtH\7jg3LlloJ,~>
+BZe>C<WDLPmcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*md=QLmcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*md>Jfmcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*m\TsOlL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL(L>H$ssdH$ssdH$ssdH$u7`IE'E<J,~>
+#QOMB;ZGnAmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>K
+mf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>Kmf)>NmcN["roO4KroO4KroO4K
+roO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4K
+roO4KroO4KroO4KroO4KroO4KroO=Nk2u+2joFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiKjoFiK
+joFiKjot1Cs5rJ3roO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4KroO4K
+roO4KroP!aS=FYIF*htTF*htTF*htTPlK#%s."T~>
+"Iu8B;ZD=AOS/^Vs2Oa5XISjG"TL3PS1/s~>
+"NJT0<W@X<OR<.Gs2OI-V2=bs"TNbi`aOA~>
+B_MJF;YK8@k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2p.@k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2p@Fk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k+)/-mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcL$SnmVb%`W,Y-J,~>
+"JhPJ;ZD=AOS/^^s2Oa5[$:4_s-*Zd3LlloJ,~>
+BZe>C<WDXXo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o($8Xo'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o($J^o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):nui#`mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mddN7o`#,LM>r"Db$ff~>
+"TS2?;ZHaa!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X1H!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X1H!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!MobpmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDK
+mK97o]sRdP!4;a=!4;a=#$PL9c1_1-J,~>
+#FqSE;ZHIamf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n^me6ABrq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6H^p@dqRp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p''lcs7Z0Srq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6K_XIT=YqZ$T`#i=*rPlEJ6S1/s~>
+"NJT0<W@X<OR<.Ls2OIAWepbuiqi66mcrfWcG$lDL&ZG@`aOA~>
+B_MJF;ZGnIk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2p.@k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2pdRk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k+r%>mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcL<S]mH!NXK84nP^@alraH$1`W,Y-J,~>
+"JhPJ;ZD=9OR<.Vs2OI0[$:UQpA=mimKh(fPa)2.S>7Ta~>
+"Nn`4<W@X4OQHSHs2O19Y(cnqg@Ft*mcrfWd^$H<M>r"Db$ff~>
+B`IeN;ZGn9k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2p.0k2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2paAk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk+r%>hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWCVC]kWJ$XJDqfS9one@Kc_UpA^Y5~>
+BUkkQ;Wb'fXL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XK5m<XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XK63EXL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XK:Qc[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&g@!s5s%Ps8VKmhURjTs"U=>.=_~>
+BZA2?<T:$]WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiBO2WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiCHLWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)Whn^TY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\=Ts2NXXo()56im,i\\qPk<H-4-8J,~>
+"SVl7;Vlu#OJDoIhSu>oS8,`YMuKgXU]Zj.HYWOh"TQI@p8!3~>
+"/MGI;M"k!s3^iKPlKn>qu?]a#h@drPlEb6Ua^f~>
+"3SW3<It1$s3^iKL&]0HrpC6\k2O\3[^q0Ls*_o0@=S~>
+"98)>;M"k!s3^i\@_HN7Uo^AfS<SAI@U`MMs3:9;S:C~>
+".Z/A;YU1k!;HNk!;c`o!.k0$s7ZHpSH%aFqu?]as4..6"TL3PS1/s~>
+"3/K/<VQLn!;HNk!;c`o!.k0$s7ZHpM>tTHrpC6\io88/]"3TLs*;c,@=S~>
+"8;c6;YU1k!;HNk!;c`o!.k0$s7ZHp@_Hi@rM9IXs*O]R"TQI@p8!3~>
+"/MGI;XFDe!+LR'p&P'krr</XXBGUTs+14Drr\Mck4\]Ps6fp;s-*Zd3LlloJ,~>
+"3SW3<UB_h!"=9$nc8Xgrr</XTaUpPs+14DrtL1e`nKkKlK7*ccH`l0Ko,hX`l__?~>
+"98)>;XFDe!+K[cmK!4crr</XS6>oDs+14DrsN;LC5\mhS=Gh.H[G^#"TQa?s."T~>
+".Z/A;YU1k!;HL(!*[nqs8N*!!!)0]s.j*(rVucqJcC<$s8N1ks5s%Ps8VKmhURjTs"U=>.=_~>
+"3/K/<VQLn!;HL(!"?^es7QHm!!)$Ys.'PurVucqJcC<$s8N1Xs2NXhmLA=<im,i\\qPk<H-4-8
+J,~>
+"8;c6;YU1k!;HL(!*Z`Ps7QHm!!)0]s.!NurVucqJcC<$s8NLB]lT+5UnjNNP^@alraH$1`W,Y-
+J,~>
+"/MGI;XFDo!*[Vis8VcmhZ'+9hP=<Trr2rurVlitJcC<$s8N1cs5s%Ps8VKme_ZOTs#HUF.=_~>
+"3SW3<UB_r!"?^is8V3]gAdS3hOP&Trr2rurVlitJcC<$s8Ndes2Nd\mcrroim,iX\qQ"@IE'E<
+J,~>
+"98)>;XFDo!*ZHHs8UULhZ'+9hOIaLrr2rurVlitJcC<$s8NdB]kWJ$XIPfFP^@ad@Tm7@c1_1-
+J,~>
+".Z/A;Z$Lh`V]Z;!*[Virr3D.s.&6Os.j*(s8N'!kl1V_JcCu7".]DRpA=mimf1i;PQ_"@Umrla~>
+"3/K/<Vugk`r#cL!"?^es8)#Sp6jq?s-X8qs8N'!kl1V_JcCu7",[&tf)G(Hk2PCGcFUT@L&ZG@
+`aOA~>
+"8;c6;Z$Lh^&.gC!*Z`Ps7Y<-s.&6Os--sms8N'!kl1V_JcCu7"(JrbMuKLTS<T7bHi7CVs2G$3
+Ujr~>
+"/MGI;Z$Io`VTT7`V]ZJ!+O1qs8Vf"pA^YQhP=<Ts8N)os8E#trr<&urrN3#s8)frs8E#ss8E#t
+rr<&urrN3#s8;rtrrE-"rW)rtrW)rtr;cltr;_EKao;I-s5s%Ps8VNeec1j:s#HUF.=_~>
+"3SW3<Vudr`qo]8`r#cK!"?ReqYKKNo)G,KhOP&Ts8N)os8E#trr<&urrN3#s8)frs8E#ss8E#t
+rr<&urrN3#s8;rtrrE-"rW)rtrW)rtr;cltr;_EKao<'/s2Nd\mcrroim,iX\qQ"@IE'E<J,~>
+"98)>;Z$Io^&%a/^&.gB!+N#PpA`[-pA^YQhNV1Ds8N)os8E#trr<&urrN3#s8)frs8E#ss8E#t
+rr<&urrN3#s8;rtrrE-"rW)rtrW)rtr;cltr;_EKao;`X]kWJ$XIPfFP^@cU@Kc_UpA^Y5~>
+".Z/A;Z$Io`VTT7`V]Z;!*[Virr3A5s.&6Os.!Nus8N)prs&Q(rr<'!rrE&u(]aU9!!*'!!<<'!
+s8N'!s8N*!rr<'!rrE&u!s&B$!;uls!<<'+!<<'!s8N'!s8N)srr<%Ms2P'@SH%aFqu?]a#i=*r
+PlEJ6S1/s~>
+"3/K/<Vudr`qo]8`r#cK!"?^eqYKKNp6jq?s-X8qs8N)prs&Q(rr<'!rrE&u(]aU9!!*'!!<<'!
+s8N'!s8N*!rr<'!rrE&u!s&B$!;uls!<<'+!<<'!s8N'!s8N)srr<%Ms2P'@M>tTHrpC6Xio88/
+]"3TLs*;c,@=S~>
+"8;c6;Z$Io^&%a/^&.gB!*Z`Ps7Y<-s.&6Os--sms8N)prs&Q(rr<'!rrE&u(]aU9!!*'!!<<'!
+s8N'!s8N*!rr<'!rrE&u!s&B$!;uls!<<'+!<<'!s8N'!s8N)srr<%Ms2P'IC;"\HXJDY^S<SAI
+CAqZFs2G$3Ujr~>
+"/MGI;Z$Io`VTT7`V]ZJ!*[Vis8Vf"pA^YQhP=<Ts8N)prr<&urrW9$rrE&u!s&B$!<3!#!<<'!
+rr3'#s8N)urrW9$rrE&u!s&B$!;uis!<3!#!<<'!rr3'#s8N)srr<%Ms2P'@PlKn>qu?]a#h@dr
+PlEb6Ua^f~>
+"3SW3<Vudr`qo]8`r#cK!"?ReqYKKNo)G,KhOP&Ts8N)prr<&urrW9$rrE&u!s&B$!<3!#!<<'!
+rr3'#s8N)urrW9$rrE&u!s&B$!;uis!<3!#!<<'!rr3'#s8N)srr<%Ms2P'QL&]0HmdBB&io88/
+[^q0Ls*_o0@=S~>
+"98)>;Z$Io^&%a/^&.gB!*ZHHp@d%$pA^YQhNV1Ds8N)prr<&urrW9$rrE&u!s&B$!<3!#!<<'!
+rr3'#s8N)urrW9$rrE&u!s&B$!;uis!<3!#!<<'!rr3'#s8N)srr<%Ms2P'Q@_HN7Uo^)VPa$NA
+@U`MMs3:9;S:C~>
+".Z/A;Z$Ip`W,i9$ie3G!<3'!rr?6I+TDBKXT+gQs8STu!<<'!q>UEprr3'#s8N)urrW9$rrE&u
+!<E/s!<<'!!<3!#!<<'!rr2rurr;uurr2rurr3!!s8)fqs8N)ts8N(Ms2b3BSH%aFqu?]as4..6
+"TL3PS1/s~>
+"3/K/<Vuds`rGr:)ZRhW!<3'!rr<JE+Sts"U%Xo6s8S>m!<<'!q>UEprr3'#s8N)urrW9$rrE&u
+!<E/s!<<'!!<3!#!<<'!rr2rurr;uurr2rurr3!!s8)fqs8N)ts8N(Ms2b3BM>tTHrpC6Xio88/
+]"3TLs*;c,@=S~>
+"8;c6;Z$Ip^&S!1)ZRMN!<3'!rr?60+TM/lMuT=0s8S<m!<<'!q>UEprr3'#s8N)urrW9$rrE&u
+!<E/s!<<'!!<3!#!<<'!rr2rurr;uurr2rurr3!!s8)fqs8N)ts8N(Ms2b3B@_Hi@rhK[ePa$NA
+rF,p0`W,Y-J,~>
+"/MGI;Z$Io`VTT7`V]Z@!+Nnis8Vf"mf!.iS6>pmrr<&qrr<&urrW9$rrE&u!s&B$!<3!#!<<'!
+qu6Wrrr3'#s8N)urr<&srrW9$rrE&u!s&B$!;QQo!;uis!.k0lrr\ekk4\]Ps6^0LeWc<u3Lllo
+J,~>
+"3SW3<Vudr`qo]8`r#cB!"?Rep@ddFlMCM[#*fSss8N'!qYpNqrr3'#s8N)urrW9$rrE&u!s&B$
+!;lcr!<3!#!<<'!rr2rur;Qj!s8N)urrW9$rrDio!!)rs!!%TMao;I"s2NXhmLA=<im,i\\qPk<
+IE'E<J,~>
+"98)>;Z$Io^&%a/^&.g8!+N#Pme51qmf!.iPZe(err<&qrr<&urrW9$rrE&u!s&B$!<3!#!<<'!
+qu6Wrrr3'#s8N)urr<&srrW9$rrE&u!s&B$!;QQo!;uis!.k0lrsWYUF,R,qUn!s>H[BN,@Kc_U
+pA^Y5~>
+".Z/A;Z$Io`VTT7`V]Z;!*[Virr3#+pAP!mP[XXlrr<&trt,82rrE*!!!*'!!<<'!!<<'!rr3'#
+s8N)rrsJi,rr<'!rrE*!!!)rs!s&B$!<3!#!<<'!q#:<or;Q`sJcEjl"-iiJpA=mimKhA"Pa)2&
+Umrla~>
+"3/K/<Vudr`qo]8`r#cH!"?Rap@@LBk486>qN20drr2rurVmH0s8N*!rr<'!rrE*!!!*'!!<3!#
+!<<'!qu7$(s8N'!s8N*!rr<&srrW9$rrE&u!s&B$!;QQo!;uis!.k0lrtL1e`nKkKlK7*ccH`l0
+Ko,hTb/Rk?~>
+"8;c6;Z$Io^&%a/^&.g9!*ZHHmdAqihX:C:!fLLfrr2rurVmH0s8N*!rr<'!rrE*!!!*'!!<3!#
+!<<'!qu7$(s8N'!s8N*!rr<&srrW9$rrE&u!s&B$!;QQo!;uis!.k0lrtJqUC5\mhS=Gh.H[B42
+>%7NNs7W7=~>
+"/MGI;Z$Io`VTT7`V]ZG!*[>a@fQ//mf3"\p68_\rVufrrVuisrr;rt"TJK%rrE&urrE*!r;cis
+rW)rtrW!'#!<<)u!<2uu!<2uu!<3#s!<<)u!<3#t!.k0krs#!OH\76/MuA87F*ih0PlEb6Ua^f~>
+"3SW3<Vudr`qo]8`r#cH!"?:]@IEEShX9h&mYqVTrVufrrVuisrr;rt"TJK%rrE&urrE*!r;cis
+rW)rtrW!'#!<<)u!<2uu!<2uu!<3#s!<<)u!<3#t!.k0krtL<4D/FE8F`DD<D.RF(Kn]PT`l__?~>
+"98)>;Z$Io^&%a/^&.g?!*Z0@@cl4*c/.=>k(?h;rVufrrVuisrr;rt"TJK%rrE&urrE*!r;cis
+rW)rtrW!'#!<<)u!<2uu!<2uu!<3#s!<<)u!<3#t!.k0krtJp.3B9Ac5rh4k5rgqk@UfA^pA^Y5~>
+".Z/A;Z$Lh`V]ZG!*ZJS@Uf&4me6A)@Tia3JcC<$pAY,Wo`+rU"TL3PS1/s~>
+"3/K/<Vugk`r#cH!">R<@:A;lf&#Q/$k*+9JcC<$pAY,Ho`#,LM>qkD`aOA~>
+"8;c6;Z$Lh^&.g?!*YVo@UdlG]uA7'@Tia3JcC<$pAY,%rk/<=rk/<=rk/TE]jbIN`W,Y-J,~>
+"/MGI;X=A^!!fT7@^P":>$Cn*JcC<$p&>5dMgKf/K8]\\$$1HO>*T%IS>7Ta~>
+"3SW3<U9\a!!f''@A1QH$k3+8JcC<$p&>__F_tu<EHQ8@D/EiuF\%5dIE'E<J,~>
+"98)>;X=A^!!eEk@[*CQ>$Cn*JcC<$p&>,/5rgt)5n,h?3C,Yc5q-:Cc1_1-J,~>
+".Z/A;YU1k!;-9p]`8%A@WVMK!6p)pJcG?A!0m-Us-*Zd0r1<gJ,~>
+"3/K/<VQLn!;-9p^&S.A@:fE<!6TlmJcG?A!/:(F#).p6H-4-8J,~>
+"8;c6;YU1k!;-9p]`8%A@Tra2!6p)pJcG?A!b/jMrk/<=rk/<=rk/M>@fOFIp8!3~>
+"/MGI;We#X!.k0$s7$$mS;V`HMh?rdK*cUGMj0J+3LlloJ,~>
+"3SW3<Ta>[!.k0$s7$%&M03ZPF`DPDEG]Q(Bm#,`s*_o0@=S~>
+"98)>;We#X!.k0$s7$%&@R3"75rh4k5rh4k3C.+`s3:9;S:C~>
+".Z/A;YU1k!.k0$s4mVSPk>"UPQ_"@Umrla~>
+"3/K/<VQLn!.k0$s4mVSL%PBLKo,hTb/Rk?~>
+"8;c6;YU1k!.k0$s4mVS@fF%@[/R`=[/R`E[(TpXs2G$3Ujr~>
+"/MGI;M"k!s3^iNS;V`@Mh?rdK*cUGMcuAF3LlloJ,~>
+"3SW3<S@D'hLXPZh@tfhD/FE8F`DD<D.RF(8;7(l`l__?~>
+"98)>;VD)$F+JE.Es$/C3B@()%66^75rgqk.:W>%pA^Y5~>
+".Z/A;YU1k!:Kje!:Kmd!.k0)rrA;Us8S;ds"U=>.=_~>
+"3/K/<VQLn!:Kje!;QTghYmM+hM0keL%PBLKo,hTb/Rk?~>
+"8;c6;YU1k!:Kje!;QTgF8c/jF,"`;@_K/J]`>G=]`>G=]`qYLs2G$3Ujr~>
+"/MGI;UPOE!!;;Y!.k0)rs#!OH\76/MuA87F*ih0PlEb6Ua^f~>
+"3SW3<S@EJhZ!QWigg(#hM0l$M03ZPF`DPDEG]Q(Bm#,`s*_o0@=S~>
+"98)>;VD*GF8l4Ak*,jsF,"`M@R3"75rh4k5rh4k3C.+`s3:9;S:C~>
+".Z/A;YU1k!:Kje!:p0i!!MHas/Z4qrr<&drr<%Ms/#_qPk>"UPQ_"@Umrla~>
+"3/K/<VQLn!:Kje!;QTkhZ!QYirB%P!;PCN!:AVC!.j"'h>i9%rs"16s*;c,@=S~>
+"8;c6;YU1k!:Kje!;QTkF8l4Ck5YIO!;LU8!:=h-!.f3fEr]\K]`>G=]`>G=]a2!Y@UfAVs7W7=~>
+"/MGI;Uk^O!8daGSE?UIq#:<omJd.dJcDSH#+UTuH]*N7rIYDtH])'ls#HUF.=_~>
+"3SW3<S@EMh?O&7s.,S7SH/HA!!)EC!!%T,V;;oCF_tu<EHQ8@D/EiuF\%5dIE'E<J,~>
+"98)>;VD*JEsD^%s.#VAPQ:K"!!)D-!!%RkV/l`R5rgt)5n,h?3C,Yc5q-:Cc1_1-J,~>
+".Z/A;YU1k!:Kje!;$3q!;<5Fs8Skpqu6`us8N)drr<%Ms/#_qPk>"UPQ_"@Umrla~>
+"3/K/<VQLn!:Kje!;QTlh?O&OS_jDHR/m-@!s%37!:AVC!.j"'h>i9%rs"16s*;c,@=S~>
+"8;c6;YU1k!:Kje!;QTlEsD^=Uu).OPQ:T%!s!C`!:=h-!.f3fEroga[/R`=[/R`=[/R`C>%7NN
+s7W7=~>
+"/MGI;Uk^O!;?G_SE?=Ar;Z`r!ri9#rW)rtrW)rt!<E0!!<<'&!<<'!s8W#tJcDnQ#+UTuK8YA?
+rIYDtH]+,Qs#HUF.=_~>
+"3SW3<S@EMh?O&Ss.,S7R/m0ArW!#V!8d\TrndVSrn[YUhYmNTh?<o9h>lEhr;_E*Y20kLF_tu<
+EHQ8@D/EiuFbPPLIE'E<J,~>
+"98)>;VD*JEsD^=s.#VAPQ:W&rW!"@!-A,>rcA&=rc8)?F8c1>Es2PbEr^9&r;_CiY&b:d5rgqk
+3C,Yk3C,Yc6"4='c1_1-J,~>
+".Z/A;YU1k!:Kje!;$3q!;<5Ns8Skpqu6m$s8N'!s8N)rrsSo-rr<'!rrE*!!<3&urr<%Ms/Z/"
+Pk>"UPQ_"@Umrla~>
+"3/K/<VQLn!:Kje!;QTlh?O&OS_jDHR/m-@#6<W;!!(m4!;kU]!8cQ4!8cQ4hVJ7h!<1gT!.j"-
+h>i9%rs"16s*;c,@=S~>
+"8;c6;YU1k!:Kje!;QTlEsD^=Uuq^WPQ:T%#68gd!!%(]!;ggG!-<2]!-<2]F)q>&!<.$>!.f3l
+Er]\K]`>G=]`>G=]a2!Y@UfAVs7W7=~>
+"/MGI;Uk^O!;?G_SE?UIqu6`us8N)urr<&rrrW9$rrE&u"T\T&!<3&urr<%Ms/Z/(S;V`@Mh?rd
+K*cUGMcuAF3LlloJ,~>
+"3SW3<S@EMh?O&Ss.,S7R/m-@!s%37!<1gT!;kUT!8cQ4rn[eYhVJ7h!<1gT!.j"-h@tfhD/FE8
+F`DD<D.RF(8;7(l`l__?~>
+"98)>;VD*JEsD^=s.#VAPQ:T%!s!C`!<.$>!;gg>!-<2]rc85CF)q>&!<.$>!.f3lEs$/C3B@()%
+66^75rgqk.:W>%pA^Y5~>
+".Z/A;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8Skpqu6`us8N)urr<&us8;rtrr<&urr`?%rr<&s
+s8N(Ms/l;$Pk>"UPQ_"@Umrla~>
+"3/K/<VQLn!:Kjn!<3'!!<3'!!<;uR#6==chZ*VD!;kUT!8cQ4rn[VTrndSRs5!_Urn[bXhVJ54
+r8.GRJ_mNc!/:(F#).p6H-4-8J,~>
+"8;c6;YU1k!:Kjn!<3'!!<3'!!<;t<#6=InhZ*V?!;gg>!-<2]rc8&>rcA#<s)S/?rc82BF)q<]
+r,_l<JTIr7!b/jMrk/<=rk/<=rk/M>@fOFIp8!3~>
+"/MGI;Uk^I!;?Bk!Ls/errW9$rrE&u!s&B$!<3!#!<<'!rr3-%s8N*!!;lcr!.k0Qrr\ekk4\]P
+s6fp;s-*Zd3LlloJ,~>
+"3SW3<S@EMh?!]FqYpKqPlU^<!s%37!<1gW!8cQ4rn[_WhVJ83h?<o9h>lC4qq_;QJ_mQd",[&t
+f)G(Hk2PCGcFUT@L&ZS@b$ff~>
+"98)>;VD*JErl@0pAY'mMZEWq!s!C`!<.$A!-<2]rc8/AF)q?\Es2PbEr^7]qf;`;JTIu8"(Jrb
+MuKLTS<T7bHi7CVs3:9;S:C~>
+".Z/A;YU1k!:Kje!;$3k!:Kgc!Ls/errW9$rrE&u!s&B$!<3!#!<<'!rr30&s8N*!!!)rs!!%TM
+Y5\Tgs5s%Ps8VNeec1j:s"U=>.=_~>
+"3/K/<VQLn!:Kje!;QTlh?O&Cp@e@VOT>:8!s%37!<1gW!8cQ4rn[_WhVJ83h?Eu:h>lC4!;t[R
+!.j"0h@t\D`nKkKlK7*ccH`l0Ko,hTb/Rk?~>
+"8;c6;YU1k!:Kje!;QTlEsD^%mdBfBMZEWq!s!C`!<.$A!-<2]rc8/AF)q?\Es;VcEr^7]!;pm<
+!.f3oEslHjC5\mhS=Gh.H[G^#"TQI@p8!3~>
+"/MGI;Uk^O!:KR\pA^?Wqu?Zr!WN0!rrN3#s8)csrrE&u#QXo)!<<'!!<<#uJcDkP".]DRpA=mi
+mKh\"Pa)2.S>7Ta~>
+"3SW3<S@EMh?O&;lL+*2M#dG0rr<)V!<1gV!8cT0!!1pVrn[n\hVJ7hh>dQ4rW%N+Xkj/:s2NXh
+mLA=<im,i\\qPk<IE'E<J,~>
+"98)>;VD*JEsD]ihWE\WK)kdirr<(@!<.$@!-<5Y!!.-@rc8>FF)q>&ErZ2]rW%LjX`Fnc]lT+5
+UnjNNP^@alraH$1c1_1-J,~>
+".Z/A;YU1k!:Kje!;$3p!9X"Kh>dP,s+UITPlKn>qu?]a#h@drPlEJ6S1/s~>
+"3/K/<VQLn!:Kje!;QTlh?Eu.hVuZX!.j!\h@t\D`nKkKlK7*ccH`l0Ko,hTb/Rk?~>
+"8;c6;YU1k!:Kje!;QTlEs;WX`Qbai!.f3FEti)sC5\mhS=Gh.H[B42>%7NNs7W7=~>
+"/MGI;Uk^L!8bZp!.k0&rr\ekk4\]Ps6fp;s-*Zd3LlloJ,~>
+"3SW3<S@EMh?3hu[K$;YhLjYeM>tTHrpC6Xio88/]"3TLs*_o0@=S~>
+"98)>;VD*JEs)K=PQ1]7F+\N9@_Hi@rhK[ePa$NArF,p0c1_1-J,~>
+".Z/A;YU1k!:Kje!;$3l!,;Lbs+11PPlKn>qu?]as4..6"TL3PS1/s~>
+"3/K/<VQLn!:Kje!;QTlh?![g!.j!Xh@t\D`nKkKlK7*ccH`l0Ko,hTb/Rk?~>
+"8;c6;YU1k!:Kje!;QTlErl>>!.f3BEslHjC5\mhS=Gh.H[G^#"TQI@p8!3~>
+"/MGI;UkaH!.k0$rri@ls5s%Ps8VKmhURjTs#HUF.=_~>
+"3SW3<S@EMhZ!S,hLXMdhMM9Pf)G(Hk2PCGcFUT@L&ZS@b$ff~>
+"98)>;VD*JF8l5kF+JBAF)&C0Ml`_MS=GgjHYWOh"TQa?s."T~>
+".Z/A;YU1k!:Kje!.k0$s7$$jPlKn>qu?]a#h@drPlEJ6S1/s~>
+"3/K/<VQLn!:Kje!;QSFhLXPZh@t\D`nKkKlK7*ccH`l0Ko,hTb/Rk?~>
+"8;c6;YU1k!:Kje!;QSFF+JE.Eti)sC5\mhS=Gh.H[B42>%7NNs7W7=~>
+"/MGI;M"k!s3^iKSH%aFqu?]as4..6"TLKPUa^f~>
+"3SW3<It1$s3^iKM>tTHrpC6Xio88/]"3TLs*_o0@=S~>
+"98)>;M"k!s3^iK@_Hi@rhK[ePa$NArF,p0c1_1-J,~>
+".Z/A;YU1k!:Kje!:Kmd!.k0)rr\Mck4\]Ps6fp;s-*Zd0r1<gJ,~>
+"3/K/<VQLn!:Kje!:Kmd!.k0)rtL1e`nKkKlK7*ccH`l0Ko,hTb/Rk?~>
+"8;c6;YU1k!:Kje!:Kmd!.k0)rsN;LC5\mhS=Gh.H[G^#"TQI@p8!3~>
+"/MGI;UPOE!!;;Y!.k0)rr\ekk4\]Ps6^0LeWc<u3LlloJ,~>
+"3SW3<RLjH!!;/N!.k0)rr\,X`n(.Ws6:!OcHa#4Kn]PT`l__?~>
+"98)>;UPOE!!;;I!.k0)rsWYUF,R,qUn"6FH[BN,@Kc_UpA^Y5~>
+".Z/A;YU1k!:Kje!:p0i!!MHas/Z4qrr<&drr<%Ms/#_tPlKV6qu?]a#h@drPlEJ6S1/s~>
+"3/K/<VQLn!:Kje!:p0i!!M<]s.KGfrr<&drr<%Ms/#_uL&]$@lMg2[lJg+7[^q0Ls*;c,@=S~>
+"8;c6;YU1k!:Kje!:p0i!!MHas-s)arr<&drr<%Ms/#`0@_HN7Uo^AfS<SAI@U`MMs2G$3Ujr~>
+"/MGI;Uk^O!8daGSE?UIq#:<omJd.dJcDSH".]DRk5,)ap>4>aPlEb6Ua^f~>
+"3SW3<Rh$R!8@IDRGOJ7q#:<omJd.dJcDSH#)WB"b3JE_rosjEf"/GHL&ZS@b$ff~>
+"98)>;Uk^O!8daGSE?%9q#:<omJd.dJcDSH$t?nkF/5V5S>;[5Me`6#"TQa?s."T~>
+".Z/A;YU1k!:Kje!;$3q!;<5Fs8Skpqu6`us8N)drr<%Ms/#_uPlKV.pA4ghk5UYKs"U=>.=_~>
+"3/K/<VQLn!:Kje!;$3q!:l];s8SJequ6`us8N)drr<%Ms/#_uL&]$4gA^(?hW!hcb/T-ls*;c,
+@=S~>
+"8;c6;YU1k!:Kje!;$3q!;<5Fs8S;`qu6`us8N)drr<%Ms/#_u@_HMtMuJqLMk$<5F)tf"s2G$3
+Ujr~>
+"/MGI;Uk^O!;?G_SE?=Ar;Z`r!ri9#rW)rtrW)rt!<E0!!<<'$!<<'!rVlitrVlp!s8W&urr2ru
+rr2ruJcELb!1`]]s-*Zd3LlloJ,~>
+"3SW3<Rh$R!;?G`RGO>3r;Z`r!ri9#rW)rtrW)rt!<E0!!<<'$!<<'!rVlitrVlp!s8W&urr2ru
+rr2ruJcELb!/^@Js+LUUIE'E<J,~>
+"98)>;Uk^O!;?G_SE?%9r;Z`r!ri9#rW)rtrW)rt!<E0!!<<'$!<<'!rVlitrVlp!s8W&urr2ru
+rr2ruJcELb!,D/>s'c-2c1_1-J,~>
+".Z/A;YU1k!:Kje!;$3q!;<5Ns8Skpqu6m$s8N'!s8N)rrsSo-rr<'!rrE*!!<3&rrs\u.rrE*!
+!<<'!!<<'!rr2ruJcELbnWX1V0r1<gJ,~>
+"3/K/<VQLn!:Kje!;$3q!:l];s8SJequ6m$s8N'!s8N)rrsSo-rr<'!rrE*!!<3&rrs\u.rrE*!
+!<<'!!<<'!rr2ruJcELbnq@7(s*;c,@=S~>
+"8;c6;YU1k!:Kje!;$3q!;<5Ns8S;`qu6m$s8N'!s8N)rrsSo-rr<'!rrE*!!<3&rrs\u.rrE*!
+!<<'!!<<'!rr2ruJcELbs'bt3raGk2raGk2raH(8@fOFIp8!3~>
+"/MGI;Uk^O!;?G_SE?UIqu6`us8N)urr<&rrrW9$rrE&u"T\T&!<3&rrrrK'rrE*!!<3!#!<<'!
+rr2ruJcELb!M%^3PQ_"HS>7Ta~>
+"3SW3<Rh$R!;?G`RGO>3qu6`us8N)urr<&rrrW9$rrE&u"T\T&!<3&rrrrK'rrE*!!<3!#!<<'!
+rr2ruJcELb!K"\bK`qF(`l__?~>
+"98)>;Uk^O!;?G_SE?%9qu6`us8N)urr<&rrrW9$rrE&u"T\T&!<3&rrrrK'rrE*!!<3!#!<<'!
+rr2ruJcELb!FguY@Kc_UpA^Y5~>
+".Z/A;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8Skpqu6`us8N)urr<&us8;rtrr<&urr`?%rr<&q
+rrrK'rrE*!!<3!#!<<'!rr2ruJcELb"LR%Jme6DT"g%_YUmrla~>
+"3/K/<VQLn!:Kjm!<3'!!<3'!!;ld$!:l];s8SJequ6`us8N)urr<&us8;rtrr<&urr`?%rr<&q
+rrrK'rrE*!!<3!#!<<'!rr2ruJcELb"fg/5k486@rroG&H-4-8J,~>
+"8;c6;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8S;`qu6`us8N)urr<&us8;rtrr<&urr`?%rr<&q
+rrrK'rrE*!!<3!#!<<'!rr2ruJcELb"g$82hX:+4rro4u`W,Y-J,~>
+"/MGI;Uk^I!;?Bk!Ls/errW9$rrE&u!s&B$!<3!#!<<'!rr3-%s8N*!!;c`q!<2uu!<3!#!<<'!
+rr2ruJcELb"K^JBme6DT"g%_aS>7Ta~>
+"3SW3<Rh$M!:K^_rrJAbqu6`us8N)urrW9$rrE&u!s&B$!<3!%!<<'!rrDoqrrE&u!!*#u!s&B$
+!<2uu!.k0brroFRhWF8&q#:Mts*_o0@=S~>
+"98)>;Uk^J!:KR[rrJ#Xqu6`us8N)urrW9$rrE&u!s&B$!<3!%!<<'!rrDoqrrE&u!!*#u!s&B$
+!<2uu!.k0brs#:Le`Q#fpA+^lXT-Q=s."T~>
+".Z/A;YU1k!:Kje!;$3k!:Kgc!Ls/errW9$rrE&u!s&B$!<3!#!<<'!rr30&s8N*!!!)orrrE&u
+$NU5,!!*'!!<<'!!.k0brrf^ck3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!;$3q!9X"KqY$$Oqu6`us8N)urrW9$rrE&u!s&B$!<3!&!<<'!rr<&rs8N)u
+rsJi,rr<'!rrE*!!!%TM^]+J;f&Gi_pA"XkWrI@e`aOA~>
+"8;c6;YU1k!:Kje!;$3q!8d/3p@aCEqu6`us8N)urrW9$rrE&u!s&B$!<3!&!<<'!rr<&rs8N)u
+rsJi,rr<'!rrE*!!!%TM^]+J=e_]0NpA"XkV#SF6p8!3~>
+"/MGI;Uk^O!:KR\pA^?Wqu?Zr!WN0!rrN3#s8)csrrE&u#6=f(!<<'!!;uls!<)rs!<3#t!!3*"
+JcELb"K^J:me6DT"g%_aS>7Ta~>
+"3SW3<Rh$R!8d#/mdc27qu?Zr!WN0!rrN3#s8)csrrE&u#6=f(!<<'!!;uls!<)rs!<3#t!!3*"
+JcELb"fg/1k3i*@rroG&IE'E<J,~>
+"98)>;Uk^O!6sB_hWBFjqu?Zr!WN0!rrN3#s8)csrrE&u#6=f(!<<'!!;uls!<)rs!<3#t!!3*"
+JcELb#,Kf"k2uC2q>UVos3:9;S:C~>
+".Z/A;YU1k!:Kje!;$3p!9X"Kh>dQ.rr<%Ms0)G*[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!;$3p!7K``aoDForr<%Ms0)G+Wn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!;$3p!56@rZiC*Yrr<%Ms0)G+XOZ1ame6GU"f21;s7W7=~>
+"/MGI;Uk^L!8bZp!7q/M!.k0RrrfF[k3hs;rroM(3LlloJ,~>
+"3SW3<Rh$O!62GI!7q/M!.k0RrroFRhWF8&q#:Mts*_o0@=S~>
+"98)>;Uk^L!2PhZ!7q/M!.k0Rrs#:Le`Q#fpA+^lXT-Q=s."T~>
+".Z/A;YU1k!:Kje!;$3l!,;Lbs+11Q[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!;$3l!+c.]s+11RWn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!;$3l!)`fJs+11RXOZ1ame6GU"f21;s7W7=~>
+"/MGI;UkaH!.k0$rrrG(hVR\op\tDus#HUF.=_~>
+"3SW3<Rh'K!.k0$rs&M'f&#QWqY:'oWrILeb$ff~>
+"98)>;UkaH!.k0$rs/S"e^`gEp@e=^"f21CpA^Y5~>
+".Z/A;YU1k!:Kje!.k0$s7$$k[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!.k0$s7$$lWn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!.k0$s7$$lXOZ1ame6GU"f21;s7W7=~>
+"/MGI;VD)$mXag%mKBWJk3hs;rroM(3LlloJ,~>
+"3SW3<S@D'p4;r5p'%JIhWF8&q#:Mts*_o0@=S~>
+"98)>;M"k!s3^iNUt+#Xk4\NErroM(c1_1-J,~>
+".Z/A;YU1k!:Kje!;QTgmf!3;mY:-4[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!;QTgpAP&Cp4i8EWn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!:Kmd!.k0)rroLShVR\oq#:Mns2G$3Ujr~>
+"/MGI;VD*Gmf*7gk+i!.mY:-4XPVh%p@nRjXT(;NUa^f~>
+"3SW3<S@EJpAY*oigg(#p4i8EWn-%hmeZ_Y"fhTN`l__?~>
+"98)>;UPOE!!;;I!.k0)rs#:Le`Q#fpA+^lV#S^5s."T~>
+".Z/A;YU1k!:Kje!;QTkmf*7ik5YI_!;Ps^!:B1S!3tql!.jS3mKBoRk3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!;QTkpAY*qirB%P!;Q6f!:BI[!3u4t!.jk;p'%JIio]h*q#:Mts*;c,@=S~>
+"8;c6;YU1k!:Kje!:p0i!!MHas-s)arr<&drr<&(rr<%Ms7ZHrXOZ1ame6GU"f21;s7W7=~>
+"/MGI;VD*JmKWaKs.#VAU]C2X!!)ES!!':l!!%T<p?i'bhWF8"p\tDus#HUF.=_~>
+"3SW3<S@EMp'1TOs.,S7SH/HY!!)E[!!':t!!%TDp@\Zif&#QWqY:'oWrILeb$ff~>
+"98)>;Uk^O!8daGSE?%9q#:<omJd.dZ2Xe(JcGHD#,Kf"k2uC2q>UW"s3:9;S:C~>
+".Z/A;YU1k!:Kje!;QTlmKWacUu).OU]C;[!s%cW!:B1S!3tql!.jS3mKBoRk3hs;rroM(0r1<g
+J,~>
+"3/K/<VQLn!:Kje!;QTlp'1TgS_jDHR/m-X!s&&g!:BI[!3u4t!.jk;p'%JIio]h*q#:Mts*;c,
+@=S~>
+"8;c6;YU1k!:Kje!;$3q!;<5Fs8S;`qu6`us8N)drr<&(rr<%Ms7ZHrXOZ1ame6GU"f21;s7W7=~>
+"/MGI;VD*JmKWacs.#VAS,iKTrW!#f!:KgdrpKacrpBdemf!4dmK3IWmK!4R!!)uc!W_ZVrW)rc
+!!*#d!!)uc!!)uc!W_ZVrW)rcr;cfa!!)uc!<DQb!<;He!<2Bd!<2Eb!!;Qgmf!3;meZ>SXPVh%
+p@nRjXT(;NUa^f~>
+"3SW3<S@EMp'1Tks.,S7R/m0YrW!#n!;?Blrq?<krq6?mpAP'lp&b<gp&P'b!!)uk!W_rfrW)rk
+!!*#l!!)uk!!)uk!W_rfrW)rkr;cfi!!)uk!<Dij!<;`m!<2Zl!<2]j!!;iopAP&CpA4IdWn-%h
+meZ_Y"fhTN`l__?~>
+"98)>;Uk^O!;?G_SE?%9r;Z`r!ri9#rW)rtrW)rt!<E0!!<<'$!<<'!rVlitrVlp!s8W&urr2ru
+rr2rurVlitrVlp!s8W&urr;osrVlitrVllus8)frrr<&urr<&us8;p!rrE)u!.k1Hrs#:Le`Q#f
+pA+^lV#S^5s."T~>
+".Z/A;YU1k!:Kje!;QTlmKWacUuq^WU]C;[#6=2[!!)HT!;l0m!:K7T!:K7Tmd:)C!;l0n!:K7T
+md:)CmJm7TmK!7S!!)rb'EIRh!:K7Tmd:&Tmd:&Tmd:)CmK!1QrrE)e"p")Z!:K7TrpBmhmd:&T
+rU0[cs6]jeJaWC&"LR%Jme6DT"g%_YUmrla~>
+"3/K/<VQLn!:Kje!;QTlp'1TgS_jDHR/m-X#6=Jk!!)`d!;lHu!;?*d!;?*dp@\L[!;lI!!;?*d
+p@\L[p&G*dp&P*c!!)rj'EIk#!;?*dp@\Idp@\Idp@\L[p&P$arrE)m"p"Aj!;?*drq6Hpp@\Id
+rV$6ks7QEmJbJs6"fg/5k486@rroG&H-4-8J,~>
+"8;c6;YU1k!:Kje!;$3q!;<5Ns8S;`qu6m$s8N'!s8N)rrsSo-rr<'!rrE*!!<3&rrs\u.rrE*!
+!<<'!!<<'!rr2rur;RH2s8N*!rrE*!!!*'!!!*'!!<<'!r;Zcss8N9's8N*!rrE&u"9AK%!!)ut
+rrE*!!!%TMqYp`#e_]0NpA"XkV#SF6p8!3~>
+"/MGI;VD*JmKWacs.#VAU]C;[!s%cW!<2Bd!;l0d!:K7TrpBpimd:)C!;l0g!:K7Tmd:)SmK3IW
+mK!7S!!)rb"p")Z!:K7TrpBjgmd:)SmK3IWmK!1Q!!*#d"p")Z!:K7TrpBjgmd:)QmJm7dmJm6<
+meZ>SXPW+-p@nRjXT(;NUa^f~>
+"3SW3<S@EMp'1Tks.,S7R/m-X!s&&g!<2Zl!;lHl!;?*drq6Kqp@\L[!;lHo!;?*dp@\Lcp&b<g
+p&P*c!!)rj"p"Aj!;?*drq6Eop@\Lcp&b<gp&P$a!!*#l"p"Aj!;?*drq6Eop@\Lap&G*lp&G)D
+pA4IdWn-%hmeZ_Y"fhTN`l__?~>
+"98)>;Uk^O!;?G_SE?%9qu6`us8N)urr<&rrrW9$rrE&u"T\T&!<3&rrrrK'rrE*!!<3!#!<<'!
+rr2rur;Qs$s8N*!rrE&u!s&B$!<3!#!<<'!r;Q`srr30&s8N*!rrE&u!s&B$!;uis!<2uu!.k1H
+rs#:Le`Q#fpA+^lXT-Q=s."T~>
+".Z/A;YU1k!:Kjn!<3'!!<3'!!<;ub#6=InhZ*VO!;l0d!:K7TrpBadrpK^bs6]jerpBmhmd:&T
+qX+Ofmd:)CmK!7S!s%cW!<2Bd!;u6f!:K7Tme["amJm7dmK3IWmK!1Q!!*#d"p")Z!:K7TrpBjg
+md:)QmJm7dmJm6<meZ>S[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kjn!<3'!!<3'!!<;uj#6==chZ*VD!;lHl!;?*drq6<lrq?9js7QEmrq6Hpp@\Id
+qXt*np@\L[p&P*c!s&&g!<2Zl!;uNn!;?*dpA4jip&G*lp&b<gp&P$a!!*#l"p"Aj!;?*drq6Eo
+p@\Lap&G*lp&G)DpA4IdWn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8S;`qu6`us8N)urr<&us8;rtrr<&urr`?%rr<&q
+rrrK'rrE*!!<3!#!<<'!rr2rur;Qm"s8N*!qZ-Zr!!*#u!s&B$!;uis!<3!&!<<'!s8N)urrW9$
+rrDus!!*#u!!%TMqYp`#e_]0NpA"XkV#SF6p8!3~>
+"/MGI;VD*JmK!=]rVlng!;l0d!:K7TrpBjgmd:)SmK3IWmK!7S"T[uY!:Bj`mf*:dmJm7dmK3IW
+mK!7S!!)oarrE&d!!)oa!!)ucrrDra!!*#d"p")Z!:K7TrpBjgmd:)QmJm7dmJm6<meZ>SXPVh%
+p@nRjXT(;NUa^f~>
+"3SW3<S@EMp&Y6^qYpKqPlU^T!s&&g!<2Zo!;?*drq6Eop@\Lcp&tHip&OddqY'phrq6<lrq6Eo
+p@\Lcp&G*ipAY-lp&G*ip&G*kpAY-ip&G*lp'(Njp&Og[!<2Zo!;?*dr:U*jrq6<lJbJs6"fg/1
+k3i*@rroG&IE'E<J,~>
+"98)>;Uk^J!:KR[rrJ#Xqu6`us8N)urrW9$rrE&u!s&B$!<3!%!<<'!rrDoqrrE&u!!*#u!s&B$
+!<2uu!;lfr!<2uu!;lcr!<)rt!;lcr!<3!&!<<'!s8N)urrW9$rrDus!!*#u!!%TMqYpbqe^`gE
+p@e=^"f21CpA^Y5~>
+".Z/A;YU1k!:Kje!;QTlmK!=UrVlng!;l0d!:K7TrpBjgmd:)SmK3IWmK!7S"p")Z!:BgeqsOIa
+rpC-omd:&Tmd:)CmJm7amf*:dmJm7amJm7cmf*:amJm7dmLB6bmJu\C!:K7T!:K7T!<)<c!<2Bd
+!.jS7mKBoRk3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!;QTlp'1T[p@e@VOT>:P!s&&g!<2Zo!;?*drq6Eop@\Lcp'(Njp&Odd!;lKi
+!<2["!;?*d!;?*dp@\IdqtC$irq6<lqt:!irV$6kqt:!irq6g%p@\L[p&Og[!!)`d!!)uk!!*#l
+!!%TDqXt)mf&Gi_pA"XkWrI@e`aOA~>
+"8;c6;YU1k!:Kje!;$3q!8d/3p@aCEqu6`us8N)urrW9$rrE&u!s&B$!<3!&!<<'!rr<&rs8N)u
+rsJi,rr<'!rrE*!!!)orrrE&u!!)or!!)utrrDrr!!*#u%KQP/!<<'!s8N'!s8N'!rVlitrr2ru
+JcGTH"g$82hX:+4rro4u`W,Y-J,~>
+"/MGI;VD*JmKWa[pAajdPQ:UKrr<)f!<2Bf!:K:P!!2KfrpC!kmd:)CmJm7bmf*:cmf!4cmf!1e
+mK!.PrrE#cr;clc!!)ucrrDra!!*#d"T[uY!:K:S!!2KfrpK^b!U]semJm6<meZ>SXPW+-p@nRj
+XT(;NUa^f~>
+"3SW3<S@EMp'1TSlL+*2M#dGHrr<)n!<2Zn!;?-`!!2cnrq6Qsp@\L[p&G*jpAY-kpAP'kpAP$m
+p&P!`rrE#kr;clk!!)ukrrDri!!*#l"T\8i!;?-c!!2cnrq?9j!VQNmp&G)DpA4IdWn-%hmeZ_Y
+"fhTN`l__?~>
+"98)>;Uk^O!6sB_hWBFjqu?Zr!WN0!rrN3#s8)csrrE&u#6=f(!<<'!!;uls!<)rs!<3#t!!3*"
+qu?ZrrVufrs8N'!rVultqu6Wrrr3-%s8N*!s8E!!rrE&ur;Zlu!<2uu!.k1Hrs#:Le`Q#fpA+^l
+XT-Q=s."T~>
+".Z/A;YU1k!:Kje!;QTlmKN[Rp@d>C!8-]>!8?i@!.jRimKBoRk3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!;QTlp'(NFhVuZX!8-uF!8@,H!.jjqp'%JIio]h*q#:Mts*;c,@=S~>
+"8;c6;YU1k!:Kje!;$3p!56@rZiC*Yrr<&Qrr<%Ms4@8SXOZ1ame6GU"f21;s7W7=~>
+"/MGI;VD*JmK<OH`;fnhmJm7@mJm6<mapk0XPVh%p@nRjXT(;NUa^f~>
+"3SW3<S@EMp&kB8[K$<Yp&G*Hp&G)Dp=K!AWn-%hmeZ_Y"fhTN`l__?~>
+"98)>;Uk^L!2PhZ!7q/M!8@GQ!.k1%rs#:Le`Q#fpA+^lV#S^5s."T~>
+".Z/A;YU1k!:Kje!;QTlmK*B'!.jQhmKBoRk3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!;QTlp&Y5*!.jipp'%JIio]h*q#:Mts*;c,@=S~>
+"8;c6;YU1k!:Kje!;$3l!)`fJs+11RXOZ1ame6GU"f21;s7W7=~>
+"/MGI;VD*Jmf*9<mXad0m]>:-me6DT"g%_aS>7Ta~>
+"3SW3<S@EMpAY,Dp4;oAp8Z^#k3i*@rroG&IE'E<J,~>
+"98)>;UkaH!.k0$rs/S"e^`gEp@e=^"g%aKpA^Y5~>
+".Z/A;YU1k!:Kje!;QSFmXag%mKBoRk3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!;QSFp4;r5p'%JIio]h*q#:Mts*;c,@=S~>
+"8;c6;YU1k!:Kje!.k0$s7$$lXOZ1ame6GU"f21;s7W7=~>
+"/MGI;M"k!s3^iLXPVh%p@nRjXT(;NUa^f~>
+"3SW3<It1$s3^iMWn-%hmeZ_Y"fhTN`l__?~>
+"98)>;M"k!s3^iNUt+#Xk4\NErro4uc1_1-J,~>
+".Z/A;YU1k!:Kje!:Kmd!.k0)rrf^ck3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!:Kmd!.k0)rroFRio]h*q#:Mts*;c,@=S~>
+"8;c6;YU1k!:Kje!:Kmd!.k0)rroLShVR\oq#:Mns2G$3Ujr~>
+"/MGI;UPOE!!;;Y!.k0)rrfF[k3hs;rroM(3LlloJ,~>
+"3SW3<RLjH!!;/N!.k0)rroFRhWF8&q#:Mts*_o0@=S~>
+"98)>;UPOE!!;;I!.k0)rs#:Le`Q#fpA+^lXT-Q=s."T~>
+".Z/A;YU1k!:Kje!:p0i!!MHas/Z4mrr<%Ms-3Nd[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!:p0i!!M<]s.KGbrr<%Ms-3NeWn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!:p0i!!MHas-s)]rr<%Ms-3NeXOZ1ame6GU"f21;s7W7=~>
+"/MGI;Uk^O!8daGSE?UIo`"mkJcCu7"K^J:me6DT"g%_aS>7Ta~>
+"3SW3<Rh$R!8@IDRGOJ7o`"mkJcCu7"fg/1k3i*@rroG&IE'E<J,~>
+"98)>;Uk^O!8daGSE?%9o`"mkJcCu7#,Kf"k2uC2q>UVos3:9;S:C~>
+".Z/A;YU1k!:Kje!;$3q!;<5Fs8Skpo`"mkJcCu7"LR%Jme6DT"g%_YUmrla~>
+"3/K/<VQLn!:Kje!;$3q!:l];s8SJeo`"mkJcCu7"fg/5k486@rroG&H-4-8J,~>
+"8;c6;YU1k!:Kje!;$3q!;<5Fs8S;`o`"mkJcCu7"g$82hX:+4rro4u`W,Y-J,~>
+"/MGI;Uk^O!;?G_SE?=Aqu6`urr<&urr<&us8E#ss8E#ts8;rss8E"Ls/uA)XPW+-p@nRjXT(;N
+Ua^f~>
+"3SW3<Rh$R!;?G`RGO>3qu6`urr<&urr<&us8E#ss8E#ts8;rss8E"Ls/uA*Wn-%hmeZ_Y"fhTN
+`l__?~>
+"98)>;Uk^O!;?G_SE?%9qu6`urr<&urr<&us8E#ss8E#ts8;rss8E"Ls/uA+Ut+#Xk4\NErroM(
+c1_1-J,~>
+".Z/A;YU1k!:Kje!;$3q!;<5Ns8Skpqu?Zr%0$;-s8N*!rrE*!!!)or!s&B$!;uj"!<<'!!.k0R
+rrf^ck3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!;$3q!:l];s8SJequ?Zr%0$;-s8N*!rrE*!!!)or!s&B$!;uj"!<<'!!.k0R
+rroFRio]h*q#:Mts*;c,@=S~>
+"8;c6;YU1k!:Kje!;$3q!;<5Ns8S;`qu?Zr%0$;-s8N*!rrE*!!!)or!s&B$!;uj"!<<'!!.k0R
+rroLShVR\oq#:Mns2G$3Ujr~>
+"/MGI;Uk^O!;?G_SE?UIqu6Wrrr30&s8N*!rrE&u!!)or!s&B$!;uis!<2uu!.k0RrrfF[hX:+3
+rroM(3LlloJ,~>
+"3SW3<Rh$R!;?G`RGO>3qu6Wrrr30&s8N*!rrE&u!!)or!s&B$!;uis!<2uu!.k0RrroFRhWF8&
+q#:Mts*_o0@=S~>
+"98)>;Uk^O!;?G_SE?%9qu6Wrrr30&s8N*!rrE&u!!)or!s&B$!;uis!<2uu!.k0Rrs#:Le`Q#f
+pA+^lV#S^5s."T~>
+".Z/A;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8Skpqu6Wrrr3*$s8N*!qZ-Wqr;cisrrE*!qZ)3I
+YQ"a4hWF8"p\tDus"U=>.=_~>
+"3/K/<VQLn!:Kjm!<3'!!<3'!!;ld$!:l];s8SJequ6Wrrr3*$s8N*!qZ-Wqr;cisrrE*!qZ)3I
+YQ"d+f&Gi_pA"XkWrI@e`aOA~>
+"8;c6;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8S;`qu6Wrrr3*$s8N*!qZ-Wqr;cisrrE*!qZ)3I
+YQ"d-e_]0NpA"XkV#SF6p8!3~>
+"/MGI;Uk^I!;?Bk!Ls/err<&urrrK'rrE*!!;lcr!<2uu!;uj!!<<'!JcDeN"K^JBme6DT"g%_a
+S>7Ta~>
+"3SW3<Rh$M!:K^_rrJAbqu6Wrrr30&s8N*!rrDrr!!*#u!!)rs!s&B$!.k0NrroFRhWF8&q#:Mt
+s*_o0@=S~>
+"98)>;Uk^J!:KR[rrJ#Xqu6Wrrr30&s8N*!rrDrr!!*#u!!)rs!s&B$!.k0Nrs#:Le`Q#fpA+^l
+XT-Q=s."T~>
+".Z/A;YU1k!:Kje!;$3k!:Kgc!Ls/ersAc+rr<'!rrE*!!;lcr!<2uu!;uj!!<<'!JcDeN"LR%J
+me6DT"g%_YUmrla~>
+"3/K/<VQLn!:Kje!;$3q!9X"KqY$$Oqu7!'s8N'!s8N*!rrDrr!!*#u!!)rs!s&B$!.k0NrroFR
+io]h*q#:Mts*;c,@=S~>
+"8;c6;YU1k!:Kje!;$3q!8d/3p@aCEqu7!'s8N'!s8N*!rrDrr!!*#u!!)rs!s&B$!.k0NrroLS
+hVR\oq#:Mns2G$3Ujr~>
+"/MGI;Uk^O!:KR\pA^?Wqu?Tprr2rurr;oss8Vrr!<<#urVufrJcDqR"K^J:me6DT"g%_aS>7Ta~>
+"3SW3<Rh$R!8d#/mdc27qu?Tprr2rurr;oss8Vrr!<<#urVufrJcDqR"fg/1k3i*@rroG&IE'E<
+J,~>
+"98)>;Uk^O!6sB_hWBFjqu?Tprr2rurr;oss8Vrr!<<#urVufrJcDqR#,Kf"k2uC2q>UVos3:9;
+S:C~>
+".Z/A;YU1k!:Kje!;$3p!9X"Kh>dQPrr<%Ms,I$][,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!;$3p!7K``aoDG<rr<%Ms,I$^Wn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!;$3p!56@rZiC+&rr<%Ms,I$^XOZ1ame6GU"f21;s7W7=~>
+"/MGI;Uk^L!8bZp!;QQo!.k00rrfF[k3hs;rroM(3LlloJ,~>
+"3SW3<Rh$O!62GI!;QQo!.k00rroFRhWF8&q#:Mts*_o0@=S~>
+"98)>;Uk^L!2PhZ!;QQo!.k00rs#:Le`Q#fpA+^lXT-Q=s."T~>
+".Z/A;YU1k!:Kje!;$3l!,;Lbs+11Q[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!;$3l!+c.]s+11RWn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!;$3l!)`fJs+11RXOZ1ame6GU"f21;s7W7=~>
+"/MGI;UkaH!.k0$rrrG(hVR\op\tDus#HUF.=_~>
+"3SW3<Rh'K!.k0$rs&M'f&#QWqY:'oWrILeb$ff~>
+"98)>;UkaH!.k0$rs/S"e^`gEp@e=^"f21CpA^Y5~>
+".Z/A;YU1k!:Kje!.k0$s7$$k[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!.k0$s7$$lWn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!.k0$s7$$lXOZ1ame6GU"f21;s7W7=~>
+"/MGI;VD)$mXag%mKBWJk3hs;rroM(3LlloJ,~>
+"3SW3<S@D'p4;r5p'%JIhWF8&q#:Mts*_o0@=S~>
+"98)>;M"k!s3^iNUt+#Xk4\NErroM(c1_1-J,~>
+".Z/A;YU1k!:Kje!;QTgmf!3;mY:-4[,0s5p@nRjXT(#NS1/s~>
+"3/K/<VQLn!:Kje!;QTgpAP&Cp4i8EWn-1lo(MkY"fhTJb/Rk?~>
+"8;c6;YU1k!:Kje!:Kmd!.k0)rroLShVR\oq#:Mns2G$3Ujr~>
+"/MGI;VD*Gmf*7gk+i!.mY:-4XPVh%p@nRjXT(;NUa^f~>
+"3SW3<S@EJpAY*oigg(#p4i8EWn-%hmeZ_Y"fhTN`l__?~>
+"98)>;UPOE!!;;I!.k0)rs#:Le`Q#fpA+^lV#S^5s."T~>
+".Z/A;YU1k!:Kje!;QTkmf*7ik5YI_!;l0a!.jQtmKBoRk3hs;rroM(0r1<gJ,~>
+"3/K/<VQLn!:Kje!;QTkpAY*qirB%P!;lHi!.jj'p'%JIio]h*q#:Mts*;c,@=S~>
+"8;c6;YU1k!:Kje!:p0i!!MHas-s)drr<%Ms,I$^XOZ1ame6GU"f21;s7W7=~>
+"/MGI;VD*JmKWaKs.#VAU]C;[!!%T<NU?qNhWF8"p\tDus#HUF.=_~>
+"3SW3<S@EMp'1TOs.,S7SH/Q\!!%TDNV3OUf&#QWqY:'oWrILeb$ff~>
+"98)>;Uk^O!8daGSE?%9qu6WrJcC`0#,Kf"k2uC2q>UW"s3:9;S:C~>
+".Z/A;YU1k!:Kje!;QTlmKWacUu).OU]C;[!!%T<NU?qVhWF8"p\tDus"U=>.=_~>
+"3/K/<VQLn!:Kje!;QTlp'1TgS_jDHR/m-X!!%TDNV3OUf&Gi_pA"XkWrI@e`aOA~>
+"8;c6;YU1k!:Kje!;$3q!;<5Fs8S;`qu6WrJcC`0"g$82hX:+4rro4u`W,Y-J,~>
+"/MGI;VD*JmKWacs.#VAS,iHS!<DQe!<2Ec!<2Ec!<;Kd!;u6b!<)<e!:K:S!<2Bd!<2Bd!;l3`
+!<2Ec!<;Kd!.jR`mKBWJhX:+3rroM(3LlloJ,~>
+"3SW3<S@EMp'1Tks.,S7R/m-X!<Dim!<2]k!<2]k!<;cl!;uNj!<)Tm!;?-c!<2Zl!<2Zl!;lKh
+!<2]k!<;cl!.jjhp'%JIhWF8&q#:Mts*_o0@=S~>
+"98)>;Uk^O!;?G_SE?%9qu6Zss8E#ts8E#ts8E#us8E#rrr<&trrN3#s8E#trr<&urr<&rs8E#t
+s8E#us8E"Ls3CWKUt+#Xk4\NErro4uc1_1-J,~>
+".Z/A;YU1k!:Kje!;QTlmKWacUuq^WU]C;[rrE)e&ch@f!:K7T!:K7T!:K7Tmd:&Tr9b!omd:)C
+mJu\C!!)HT!<2Bd!;Psi!:K7T!:K7Tmd:&TJaUkP"LR%Jme6DT"g%_YUmrla~>
+"3/K/<VQLn!:Kje!;QTlp'1TgS_jDHR/m-XrrE)m&chY!!;?*d!;?*d!;?*dp@\Idr:UR"p@\L[
+p&Og[!!)`d!<2Zl!;Q6q!;?*d!;?*dp@\IdJbIF`"fg/5k486@rroG&H-4-8J,~>
+"8;c6;YU1k!:Kje!;$3q!;<5Ns8S;`qu?Zrs8N]3s8N*!rr<'!rr<'!rrE*!!!)rs%06G.!<<'!
+s8N'!s8N)urr<&orsJi,rr<'!rrE*!!!%TMci40Me_]0NpA"XkV#SF6p8!3~>
+"/MGI;VD*JmKWacs.#VAU]C;[!!*#d!s%cW!<2Bg!:K7TrpBadrpBadr9aahmd:)CmK!7S!s%cW
+!<2Bd!;Psa!:K7TrpBadrpBadJaUkP'Vp).H\6ZtH\6ZtH\6ZtSGtU>Ua^f~>
+"3SW3<S@EMp'1Tks.,S7R/m-X!!*#l!s&&g!<2Zo!;?*drq6<lrq6<lr:U<pp@\L[p&P*c!s&&g
+!<2Zl!;Q6i!;?*drq6<lrq6<lJbIF`'V0MtH$ssdH$ssdH$ssdSc=,Xb$ff~>
+"98)>;Uk^O!;?G_SE?%9qu6Wrrr3'#s8N)urrW9$rrE&u!!*#u!!)rs"p"]'!<<'!rr3'#s8N)u
+rr<&orrW9$rrE&u!!*#u!!%TMci4]LF*htTF*htTF*htTF*j/Oc1_1-J,~>
+".Z/A;YU1k!:Kjn!<3'!!<3'!!<;ub#6=InhZ*VO!;l0a!<2Be!:K^as6]pgmdBrPr9aahmd:)C
+mK!7S!s%cW!<2Bd!;l3_!<;Hg!:K:P!.jRamJqV/s8VflmKIt;0r1<gJ,~>
+"3/K/<VQLn!:Kjn!<3'!!<3'!!<;uj#6==chZ*VD!;lHi!<2Zm!;?9is7QKop@e@`r:U<pp@\L[
+p&P*c!s&&g!<2Zl!;lKg!<;`o!;?-`!.jjip'Z0BqZ$EgpA4LVo'ZMB"aU,nb/Rk?~>
+"8;c6;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8S;`qu6Wrrr3!!s8)frrrN3#s8)forrrK'rrE*!
+!<3!#!<<'!rr2ruqu?Tps8N-#s8VrrJcF'r$$5h6s7Z0Sp?qYQjp'[`s2G$3Ujr~>
+"/MGI;VD*JmK!=]rVlng!;l0a!<2Bg!:K7TqsFFarpBadp[8%]rpBadrpBjgmd:)SmJm7bmJm7d
+mK3IWmK!7S!!%T<bO,Fap@e=^$23fLp3Zg"S>7Ta~>
+"3SW3<S@EMp&Y6^qYpKqPlU^T!!*#l!s&&g!;lHi!<2Zl!;H3e!<2Zl!<2Zo!;?*drq6<lr:U*j
+rq6Eop@\Lcp&G)Dp<3.3IIch&qu7$"mcNBkH2i<4b$ff~>
+"98)>;Uk^J!:KR[rrJ#Xqu6Wrrr3'#s8N)rrr<&urr<&ns8N)urr<&urrW9$rrE&u!!)rs!!*#u
+!s&B$!<2uu!.k0nrr[W9me6Y[%JKhqp?(Mfk&^RIpA^Y5~>
+".Z/A;YU1k!:Kje!;QTlmK!=UrVlng!;l0a!<2Bg!:K7TqsFFarpBadp[8%]rpC-omd:&Tmd:)C
+mJm7bmJm7dmK3IWmK!7S!!%T<bO,FYp?qbV$23NDmXtNoUmrla~>
+"3/K/<VQLn!:Kje!;QTlp'1T[p@e@VOT>:P!!*#l!s&&g!;lHi!<2Zl!;H3e!<2["!;?*d!;?*d
+p@\Idr:U*jrq6Eop@\Lcp&G)Dp<3.3H1'tkqu7#smbZsgH2i04`aOA~>
+"8;c6;YU1k!:Kje!;$3q!8d/3p@aCEqu6Wrrr3'#s8N)rrr<&urr<&ns8N)ursJi,rr<'!rrE*!
+!!)rs!!*#u!s&B$!<2uu!.k0nrr[?)k3i3Js7ZK\#h@eoHiM(bp8!3~>
+"/MGI;VD*JmKWa[pAajdPQ:UK!!*#d!!*#dr;clc!!)ucr;c`_rrE#crW)rcrVuue!;u9^!!2Kf
+rU0UaJaUkP!/(:Err2rurr3;uk2uAas#HUF.=_~>
+"3SW3<S@EMp'1TSlL+*2M#dGH!!*#l!!*#lr;clk!!)ukr;c`grrE#krW)rkrVuum!;uQf!!2cn
+rV$0iJbIF`"+BV*o)AXu!<<)qmc**gH2i<4b$ff~>
+"98)>;Uk^O!6sB_hWBFjqu6Wrrr2rurr;oss8N'!rVufrqu?ZrrVuisrr;rt!WN/ts8)csrrE#t
+r;_EKci4)ok2u+2rs\u.p@dY*e`LrQc1_1-J,~>
+".Z/A;YU1k!:Kje!;QTlmKN[Rp@d>C!8[&C!.jR<mK.b/mf*7c!<<'*p?(N*HiGgrS1/s~>
+"3/K/<VQLn!:Kje!;QTlp'(NFhVuZX!8[>K!.jjDp'#a0lLt8XrW!?+p?pesl?WDTb/Rk?~>
+"8;c6;YU1k!:Kje!;$3p!56@rZiC*^rr<%Ms/Q)&F7/2YpAb*l$hj#Ne_]/(s2G$3Ujr~>
+"/MGI;VD*JmK<OH`;fnmmJm6<m],[XKD,$=s82j(s7YU;p3Zg"S>7Ta~>
+"3SW3<S@EMp&kB8[K$<^p&G)Dp8[fhII?Oos82j(qX3A"l?WDX`l__?~>
+"98)>;Uk^L!2PhZ!8IMR!.k0Mrrd]2k3i9I!"/G^hUUb0s3:9;S:C~>
+".Z/A;YU1k!:Kje!;QTlmK*B'!.jQhmK7h0mf3+`$23NDmXtNoUmrla~>
+"3/K/<VQLn!:Kje!;QTlp&Y5*!.jipp&fU.lLt&S$1?[0l?WDTb/Rk?~>
+"8;c6;YU1k!:Kje!;$3l!)`fJs+11PF6;WQq>^iie_]G8s2G$3Ujr~>
+"/MGI;VD*Jmf*9<mXad.mXt6,p]1?V#53ED3LlloJ,~>
+"3SW3<S@EMpAY,Dp4;o>p3lAsp](TZhWfCdIE'E<J,~>
+"98)>;UkaH!.k0$rr`:Jk2uF=#i=+oF8sMYs."T~>
+".Z/A;YU1k!:Kje!;QSFmXag%mK@n1mf3=b!"/c"k2u)Ys"U=>.=_~>
+"3/K/<VQLn!:Kje!;QSFp4;r5p&o[/lLt8U!"/GfhW!gGs*;c,@=S~>
+"8;c6;YU1k!:Kje!.k0$s7$$kF7/2YpA=mtmcN'VhK/_9s7W7=~>
+"/MGI;M"k!s3^iLKD,$=s82j(s7YU;p3Zg"S>7Ta~>
+"3SW3<It1$s3^iLII?Oos82j(qX3A"l?WDX`l__?~>
+"98)>;M"k!s3^iLHfjJYs82j(p?(5^k&^RIpA^Y5~>
+".Z/A;YU1k!:Kje!:Kmd!.k0)rrd]Bmf3=b!"/c"k2u)as"U=>.=_~>
+"3/K/<VQLn!:Kje!:Kmd!.k0)rrdW8lLt8U!"/GfhW!gGs*;c,@=S~>
+"8;c6;YU1k!:Kje!:Kmd!.k0)rrdE*k3hs@!<;Hme_]G8s2G$3Ujr~>
+"/MGI;UPOE!!;;Y!.k0)rr@]Np&P-j!"/c"k2uAas#HUF.=_~>
+"3SW3<RLjH!!;/N!.k0)rrdc<mdgDU!"/SjinisGs*_o0@=S~>
+"98)>;UPOE!!;;I!.k0)rrd]2k3i9I!"/G^hUUb0s3:9;S:C~>
+".Z/A;YU1k!:Kje!:p0i!!MHas/Z48rr<%Ms2k9BHhQn'rsAD]k3dTr0r1<gJ,~>
+"3/K/<VQLn!:Kje!:p0i!!M<]s.KG-rr<%Ms2k9CH1'tkrr3H(pA4LNhW!gGs*;c,@=S~>
+"8;c6;YU1k!:Kje!:p0i!!MHas-s)(rr<%Ms2k9TF7/2YpAaj[me6)2e_]/(s2G$3Ujr~>
+"/MGI;Uk^O!8daGSE?UI^]+96JcEjl!e^4?q>Ucpk2uAas#HUF.=_~>
+"3SW3<Rh$R!8@IDRGOJ7^]+96JcEjl"+BV*o)A[fq?cTLhWfCdIE'E<J,~>
+"98)>;Uk^O!8daGSE?%9^]+96JcEjl"+01mmf*7bp'Km<e`LrQc1_1-J,~>
+".Z/A;YU1k!:Kje!;$3q!;<5Fs8Skp^]+96JcEjl!djY/q>Ucpk2u)as"U=>.=_~>
+"3/K/<VQLn!:Kje!;$3q!:l];s8SJe^]+96JcEjl"*s>"pAY($qY'dZmbZsgH2i04`aOA~>
+"8;c6;YU1k!:Kje!;$3q!;<5Fs8S;`^]+96JcEjl'Q`F!me6\Sp?qYBma^1VHiM(bp8!3~>
+"/MGI;Uk^O!;?G_SE?=Ar;Q`srVlp!s8W&urr2rurr2ruqu?Wqrr;rts8W&ur;Q`srr3'#s8N)u
+s8E#trr<&us8;rts8E#trrE-"qZ-WqrW%NLk5PF6rq?0g$23NDp3Zg"S>7Ta~>
+"3SW3<Rh$R!;?G`RGO>3r;Q`srVlp!s8W&urr2rurr2ruqu?Wqrr;rts8W&ur;Q`srr3'#s8N)u
+s8E#trr<&us8;rts8E#trrE-"qZ-WqrW%NLk5PO3mdBZB!"&)QhWfCdIE'E<J,~>
+"98)>;Uk^O!;?G_SE?%9r;Q`srVlp!s8W&urr2rurr2ruqu?Wqrr;rts8W&ur;Q`srr3'#s8N)u
+s8E#trr<&us8;rts8E#trrE-"qZ-WqrW%NLk5PO1k2u+.!"%fEe`LrQc1_1-J,~>
+".Z/A;YU1k!:Kje!;$3q!;<5Ns8Skpqu7**s8N*!rrE*!!!*'!!<2uu!;QR%!<<'!!<<'!s8N'!
+rVult'E8%4s8N*!rrE*!!!*'!!<<'!!<)p4!<<'!!<<'!!<<'!s8N*!rrE*!!!%TMkPkU1p?qbV
+$23NDmX+sgUmrla~>
+"3/K/<VQLn!:Kje!;$3q!:l];s8SJequ7**s8N*!rrE*!!!*'!!<2uu!;QR%!<<'!!<<'!s8N'!
+rVult'E8%4s8N*!rrE*!!!*'!!<<'!!<)p4!<<'!!<<'!!<<'!s8N*!rrE*!!!%TMkPkX0mcsNF
+rsehuqY'@6ip(ghH-4-8J,~>
+"8;c6;YU1k!:Kje!;$3q!;<5Ns8S;`qu7**s8N*!rrE*!!!*'!!<2uu!;QR%!<<'!!<<'!s8N'!
+rVult'E8%4s8N*!rrE*!!!*'!!<<'!!<)p4!<<'!!<<'!!<<'!s8N*!rrE*!!!%TMkPl6;mcNs2
+s7Z0Sp?q(nhVN>R`W,Y-J,~>
+"/MGI;Uk^O!;?G_SE?UIqu6j#s8N*!rrE&u!s&B$!<2uu!;QQr!<<'!rr2rurr2rur;R''rrE'!
+rrE*!!<3!&!<<'!s8N)srr<&urrW9$rrE&u"p"]'!<<'!rr2ruJcFp5!e^4?q>Ucpk2uAas#HUF
+.=_~>
+"3SW3<Rh$R!;?G`RGO>3qu6j#s8N*!rrE&u!s&B$!<2uu!;QQr!<<'!rr2rurr2rur;R''rrE'!
+rrE*!!<3!&!<<'!s8N)srr<&urrW9$rrE&u"p"]'!<<'!rr2ruJcFp5"+BV*o)A[fq?cTLhWfCd
+IE'E<J,~>
+"98)>;Uk^O!;?G_SE?%9qu6j#s8N*!rrE&u!s&B$!<2uu!;QQr!<<'!rr2rurr2rur;R''rrE'!
+rrE*!!<3!&!<<'!s8N)srr<&urrW9$rrE&u"p"]'!<<'!rr2ruJcFp5"+01mmf*7bp'Km<e`LrQ
+c1_1-J,~>
+".Z/A;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8Skpqu6j#s8N*!rrE&u!s&B$!<2uu!;lfp!<<'#
+!<<)r!;uj%!<3'!!<3'!qZ-Zr!s&B$!;uis!<3!#!<<'!rr3*$s8N*!qZ)3IkPkU1p?qbV$23ND
+mXtNoUmrla~>
+"3/K/<VQLn!:Kjm!<3'!!<3'!!;ld$!:l];s8SJequ6j#s8N*!rrE&u!s&B$!<2uu!;lfp!<<'#
+!<<)r!;uj%!<3'!!<3'!qZ-Zr!s&B$!;uis!<3!#!<<'!rr3*$s8N*!qZ)3IkPkX0mcsNFrsehu
+qY'@6ip(ghH-4-8J,~>
+"8;c6;YU1k!:Kjm!<3'!!<3'!!;ld$!;<5Fs8S;`qu6j#s8N*!rrE&u!s&B$!<2uu!;lfp!<<'#
+!<<)r!;uj%!<3'!!<3'!qZ-Zr!s&B$!;uis!<3!#!<<'!rr3*$s8N*!qZ)3IkPl6;k2u+*s7Z0S
+p?qA!hWB1b`W,Y-J,~>
+"/MGI;Uk^I!;?Bk!Ls/ds8N)urr<&urrW9$rrE&u!!)rs!!*#u!s&B$!<2uu!;QTo!<<*!!<2uu
+!;lcu!<<'!r;Q`srr3'#s8N)urrrK'rrE*!!.k11rr@]Np&P-j!"/c"k2uAas#HUF.=_~>
+"3SW3<Rh$M!:K^_rrJAbqZ$Qqrr2rurr3'#s8N)urr<&srr<&urrW9$rrE&u!!)forrE*!rrE&u
+!!)or!s&B$!;uis!<3!#!<<'!rr30&s8N*!rr@WMj8T71mdBZGqu@*#mc**gH2i<4b$ff~>
+"98)>;Uk^J!:KR[rrJ#XqZ$Qqrr2rurr3'#s8N)urr<&srr<&urrW9$rrE&u!!)forrE*!rrE&u
+!!)or!s&B$!;uis!<3!#!<<'!rr30&s8N*!rr@WMj8T7/k2u+3qu@)tk2+YNF8sMYs."T~>
+".Z/A;YU1k!:Kje!;$3k!:Kgc!Ls/ds8N)ursJi,rr<'!rrE*!!!)rs!!*#u!s&B$!<2uu!;QTo
+!<<*!!<2uu!;ld!!<<'!!<)p&!<<'!!<<'!rr30&s8N*!rr@WMj8T7/p?qt\qu@*(p?(N*HiGgr
+S1/s~>
+"3/K/<VQLn!:Kje!;$3q!9X"KqY$$OqZ$Qqrr3?+s8N'!s8N*!rr<&srr<&urrW9$rrE&u!!)fo
+rrE*!rrE&u!!)or"9AK%!!)ut#6=f(!!*'!!<3!&!<<'!s8N(Ms5X+^H1'tks82j(p?pesl?WDT
+b/Rk?~>
+"8;c6;YU1k!:Kje!;$3q!8d/3p@aCEqZ$Qqrr3?+s8N'!s8N*!rr<&srr<&urrW9$rrE&u!!)fo
+rrE*!rrE&u!!)or"9AK%!!)ut#6=f(!!*'!!<3!&!<<'!s8N(Ms5X+^F7/2YpA=mtmcN'VhK/_9
+s7W7=~>
+"/MGI;Uk^O!:KR\pA^?WqZ$QqrVuisrr;rt!WN/ts8)csrrE#tr;ccqrrE&u!!)utr;clt!!*#u
+r;cltrW)rt!!*#u!s&B$!<3#s!.k15rrduJpAb0j!"/c"k2uAas#HUF.=_~>
+"3SW3<Rh$R!8d#/mdc27qZ$QqrVuisrr;rt!WN/ts8)csrrE#tr;ccqrrE&u!!)utr;clt!!*#u
+r;cltrW)rt!!*#u!s&B$!<3#s!.k15rrdc<mdgDU!"/SjinisGs*_o0@=S~>
+"98)>;Uk^O!6sB_hWBFjqZ$QqrVuisrr;rt!WN/ts8)csrrE#tr;ccqrrE&u!!)utr;clt!!*#u
+r;cltrW)rt!!*#u!s&B$!<3#s!.k15rrd]2k3i9I!"/G^hUUb0s3:9;S:C~>
+".Z/A;YU1k!:Kje!;$3p!9X"Kh>dQOrr<%Ms,R*^HhQn-s82j(s7YU;mXtNoUmrla~>
+"3/K/<VQLn!:Kje!;$3p!7K``aoDG;rr<%Ms,R*^H1'tks82j(p?pesl?WDTb/Rk?~>
+"8;c6;YU1k!:Kje!;$3p!56@rZiC+%rr<%Ms,R*^F6;WQpA=pjmKhA"k'R-Is7W7=~>
+"/MGI;Uk^L!8bZp!;HKn!.k01rrRiHp@nXfjp(O+s#HUF.=_~>
+"3SW3<Rh$O!62GI!;HKn!.k01rrRW:me?bfinisGs*_o0@=S~>
+"98)>;Uk^L!2PhZ!;HKn!.k01rrRQ0k4eo^hUUb0s3:9;S:C~>
+".Z/A;YU1k!:Kje!;$3l!,;Lbs+11PHhQn-q>^iqk2u)Ys"U=>.=_~>
+"3/K/<VQLn!:Kje!;$3l!+c.]s+11PH1'tkq>^iihW!gGs*;c,@=S~>
+"8;c6;YU1k!:Kje!;$3l!)`fJs+11PF7/2Yq>^iae_]/(s2G$3Ujr~>
+"/MGI;UkaH!.k0$rrrFTp@eOdqu@*(p?(N2HiH*rUa^f~>
+"3SW3<Rh'K!.k0$rrrFNmdBZGqu@*#mc**gH2i<4b$ff~>
+"98)>;UkaH!.k0$rrrFLk2u+3qu@)tk2+YNF8sMYs."T~>
+".Z/A;YU1k!:Kje!.k0$s7$$iHhQn,s8E#ursAD]k3dm%0r1<gJ,~>
+"3/K/<VQLn!:Kje!.k0$s7$$lH1'tgs8W&u$ifqghW!gGs*;c,@=S~>
+"8;c6;YU1k!:Kje!.k0$s7$$lF6;WQpAb*l$hj#Ve_]G8s2G$3Ujr~>
+"/MGI;VD)$mXag%mJqn=pAY'l!<3!)p?q):HiH*rUa^f~>
+"3SW3<S@D'p4;r5p&fa2lL+ZO!!*#u$1d*8l?WDX`l__?~>
+"98)>;M"k!s3^iHHiE1,rs\u.pAaR;hWAnZc1_1-J,~>
+".Z/A;YU1k!:Kje!;QTgmf!3;mY:-4HhQn$pA4dpp?qX$s"U=>.=_~>
+"3/K/<VQLn!:Kje!;QTgpAP&Cp4i8TH1'tco(r(VpA4L_mcs4cs*;c,@=S~>
+"8;c6;YU1k!:Kje!:Kmd!.k0)rsNo9hWF8"me6)Bme6YB"`s^_s7W7=~>
+"/MGI;VD*Gmf*7gk+i!.mY:-0KDtQJs7ZKds7ZBj"ag80S>7Ta~>
+"3SW3<S@EJpAY*oigg(#p4i8GIIcsso()MBrpgBhs8)S;s*_o0@=S~>
+"98)>;UPOE!!;;I!.k0)rr[W9mcON:!9X7J#ljVlF8sMYs."T~>
+".Z/A;YU1k!:Kje!;QTkmf*7ik5YI_!;l0a!<)<c!8$W=!8$W=!.jS%mK9hCH\;<E!/(8t!/(8t
+"hjpjUmrla~>
+"3/K/<VQLn!:Kje!;QTkpAY*qirB%P!;lHi!<)Tk!8$oE!8$oE!.jk-p&MPmGm1YVH-4-8J,~>
+"8;c6;YU1k!:Kje!:p0i!!MHas-s)drr<&trr<&Nrr<&Nrr<%Ms60IbXE/H0rc8'drc8'drc87M
+s2G$3Ujr~>
+!i2>HJcC<$^]+BrS>7Ta~>
+!m8N2JcC<$^]+Ca`l__?~>
+!rqu=JcC<$^]+D\pA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>Hk3i-IhsLIEp$V_Xq!J+^jR*!Jr9jI_s6]jeddI#5s6]jei9pLCnEp8V\*a>YS>7Ta~>
+!m8N2k3i-IhsLIEp$V_Xq!J+^jR*!Jr9jI_s6]jeddI#5s6]jei9pLCnEp8V\*a?H`l__?~>
+!rqu=k2uRAhrXn=p#c/PpuVPVjQ6FBr9!nWs5j:]dcUH-s5j:]i9'q;nE']N\)me;pA^Y5~>
+!h?&@kO&<MrU'XchsLIEp?hn\oBlSYjR*!Jr9aObrpKdd!U]s9mJm7dmf*7fmJu25!!*#drrDTW
+!!'Lr"#6UA.=_~>
+!liB.kO&<MrU'XchsLIEp?hn\oBlSYjR*!Jr9aObrpKdd!U]s9mJm7dmf*7fmJu25!!*#drrDTW
+!!'Lr"*r&/@=S~>
+!quZ5kN2aErT4([hrXn=p>u>ToB$#QjQ6FBr8mtZroX4\!TjC1jo>D\k5PD^joF?%!!*#\rrDTO
+!!'Lj"3(<6Ujr~>
+!i2>HkjJHNh<k@Fmd:)KmJm7YmJm7XmJm7ZmJm7bmJm7cmK*CV!7L98!<)<e!:BjFmJm7cmJm7W
+mJm6rmK5J>Ua^f~>
+!m8N2kjJHNh<k@Fmd:)KmJm7YmJm7XmJm7ZmJm7bmJm7cmK*CV!7L98!<)<e!:BjFmJm7cmJm7W
+mJm6rmK7mWb$ff~>
+!rqu=kiVmFh<"e>k2l[;jo>DQjo>DPjo>DRjo>DZjo>D[joPPF!7L!0!<)$]!9O:>jo>D[jo>DO
+jo>Cjjo`m%s."T~>
+!h?&@kjAENq<e4_rpBgfmdC&S!:Kgds6fjdrpBdemf!1dmf!1gmJuYTrU'XcrU0[cqX4=_rpBad
+rpKacrU0L^s6fjdrU0Uar9aObrU'afmJu\S!<;Kd!<;Kd!<2Eb!<2Ec!;c-_!<2Ec!<)<c!<)<f
+!:BjTrW)udrW)udrW)rcr;cibrW)i`!!)uc!!*#drW)obrW)rc!s%cW!4qS#0r1<gJ,~>
+!liB.kjAENq<e4_rpBgfmdC&S!:Kgds6fjdrpBdemf!1dmf!1gmJuYTrU'XcrU0[cqX4=_rpBad
+rpKacrU0L^s6fjdrU0Uar9aObrU'afmJu\S!<;Kd!<;Kd!<2Eb!<2Ec!;c-_!<2Ec!<)<c!<)<f
+!:BjTrW)udrW)udrW)rcr;cibrW)i`!!)uc!!*#drW)obrW)rc!s%cW!4qS#H-4-8J,~>
+!quZ5kiMjFq;qYWroO7^k2uXC!9X7\s5s:\roO4]k5G>\k5G>_joFNDrT4([rT=+[qW@bWroO1\
+roX1[rT<qVs5s:\rT=%Yr8mtZrT41^joFQC!<;3\!<;3\!<2-Z!<2-[!;bjW!<2-[!<)$[!<)$^
+!9O:DrW)u\rW)u\rW)r[r;ciZrW)iX!!)u[!!*#\rW)oZrW)r[!s%KG!4q:p`W,Y-J,~>
+!i2>HkjAENq<e4_rpCs1md:&Tmd:&Tmd:)CmJm7TmJm7TmJu\C!:K7Tmd:)CmK!.PrW)ob&ch@f
+!!)HT!:K7Tmd:&Tmd:&TrU(-qmd:)CmJm7TmJm7TmK!1Q!!*#drr<An!!)HT!:K7T!;l0d!:K7T
+r9a[fmd:&Tr9agjmd:&Tmd:&Tr9aObrpKdd$17cnmd:)CmJm7amK3IWmK!1Q"9@lX!!)rb!!*#d
+!!*#d&-2.d!!)HT!:K7T!:K7TmJsfc"$)mI.=_~>
+!m8N2kjAENq<e4_rpCs1md:&Tmd:&Tmd:)CmJm7TmJm7TmJu\C!:K7Tmd:)CmK!.PrW)ob&ch@f
+!!)HT!:K7Tmd:&Tmd:&TrU(-qmd:)CmJm7TmJm7TmK!1Q!!*#drr<An!!)HT!:K7T!;l0d!:K7T
+r9a[fmd:&Tr9agjmd:&Tmd:&Tr9aObrpKdd$17cnmd:)CmJm7amK3IWmK!1Q"9@lX!!)rb!!*#d
+!!*#d&-2.d!!)HT!:K7T!:K7TmJsfc"+A23@=S~>
+!rqu=kiMjFq;qYWroPC)k2lXDk2lXDk2l[+jo>DDjo>DDjoFQ+!9WDDk2l[+joG;@rW)oZ&ch(V
+!!)0D!9WDDk2lXDk2lXDrT4Rik2l[+jo>DDjo>DDjoG>A!!*#\rr<Af!!)0D!9WDD!;km\!9WDD
+r8n+^k2lXDr8n7bk2lXDk2lXDr8mtZroX4\$0D3fk2l[+jo>DYjoYVGjoG>A"9@TH!!)rZ!!*#\
+!!*#\&-1kT!!)0D!9WDD!9WDDjoDsS"3pQ>S:C~>
+!h?&@p?q`SqsFFaq<e4_rpBjgmd:)SmJm7dmJm7dmK3IWmK!7S$io_`!:K7Tmd:)CmK!(NrrE&d
+!!*#d"p")Z!:K7TrpBjgmd:)QmK3IWmK!7S!s%cW!<2Bd!;u9_!<;He!<2Bg!:K7TqX+Fcmd:)Q
+mJm7dmJm7bmJm7dmK3IWmK!.PquHcb!!*#d!s%cW!;c*c!:K7Tr9aObrpBadr9jL`rU'XcrpBjg
+md:)SmKEUYmJuYTq<lL*!<;c\"#6UA.=_~>
+!liB.p?q`VqsFFaq<e4_rpBjgmd:)SmJm7dmJm7dmK3IWmK!7S$io_`!:K7Tmd:)CmK!(NrrE&d
+!!*#d"p")Z!:K7TrpBjgmd:)QmK3IWmK!7S!s%cW!<2Bd!;u9_!<;He!<2Bg!:K7TqX+Fcmd:)Q
+mJm7dmJm7bmJm7dmK3IWmK!.PquHcb!!*#d!s%cW!;c*c!:K7Tr9aObrpBadr9jL`rU'XcrpBjg
+md:)SmKEUYmJuYTq<lL-!<;c\"*r&/@=S~>
+!quZ5p?)0KqrRkYq;qYWroO:_k2l[Cjo>D\jo>D\joYVGjoGDC$ioGP!9WDDk2l[+joG5>rrE&\
+!!*#\"p!fJ!9WDDroO:_k2l[AjoYVGjoGDC!s%KG!<2*\!;u!W!<;0]!<2*_!9WDDqW7k[k2l[A
+jo>D\jo>DZjo>D\joYVGjoG;@quHcZ!!*#\!s%KG!;bg[!9WDDr8mtZroO1\r9!qXrT4([roO:_
+k2l[CjokbIjoFNDq<#q"!<;cT"3(<6Ujr~>
+!i2>Hp?hoYqZ$H\!!)i_!!*#d!s%cW!<2Bf!:K:P!<;He!<2Bp!:K7Tmd:)CmJu\C!;Q!^!!)Ha
+!<;Hf!:K^as6]jer9aRcme["amJm7dmJm7bmJm7amJm7dmK3IWmK!4Rr;cibrrE)eqZ-Q^!!*#d
+!s%cW!;l0a!;l0a!<2Bg!:K7TrU0UarpKdds6faar9aObrpKdds6]jerpBjgmd:)SmK<OXmJm7^
+m`th5;ZHIY"$)mI.=_~>
+!m8N2p?ho\qZ$H\!!)i_!!*#d!s%cW!<2Bf!:K:P!<;He!<2Bp!:K7Tmd:)CmJu\C!;Q!^!!)Ha
+!<;Hf!:K^as6]jer9aRcme["amJm7dmJm7bmJm7amJm7dmK3IWmK!4Rr;cibrrE)eqZ-Q^!!*#d
+!s%cW!;l0a!;l0a!<2Bg!:K7TrU0UarpKdds6faar9aObrpKdds6]jerpBjgmd:)SmK<OXmJm7^
+m`th5<WDd\"+A23@=S~>
+!rqu=p>u?QqZ$HT!!)iW!!*#\!s%KG!<2*^!9WG@!<;0]!<2*h!9WDDk2l[+joFQ+!;P^V!!)0Y
+!<;0^!9X.Ys5j:]r8n"[k5,/Yjo>D\jo>DZjo>DYjo>D\joYVGjoGABr;ciZrrE)]qZ-QV!!*#\
+!s%KG!;kmY!;kmY!<2*_!9WDDrT=%YroX4\s5s1Yr8mtZroX4\s5j:]roO:_k2l[Cjob\Hjo>DV
+k0Eu-;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7Pg[!;c*`!<2Bg!:K7TrpBadrpBadqsFFarpBsjmd:)CmK!7SrrDc\!s%cW!;l0d
+!:K7TqsFFar9aXemd:)PmJm7dmJm7bmJm7amJm7dmK3IWmK!7S!!*#d!!)rb!s%cW!;Ps^!<2Bg
+!:K7TqsFFaqsFFarpBjgmd:)SmJm7dmJm7bmK3IWmK!%M!!)uc!s%cW!<2Bg!:K7TrpBpimd:)C
+!64F-;ZHIY"#6UA.=_~>
+!liB.p?hr]s7Pg[!;c*`!<2Bg!:K7TrpBadrpBadqsFFarpBsjmd:)CmK!7SrrDc\!s%cW!;l0d
+!:K7TqsFFar9aXemd:)PmJm7dmJm7bmJm7amJm7dmK3IWmK!7S!!*#d!!)rb!s%cW!;Ps^!<2Bg
+!:K7TqsFFaqsFFarpBjgmd:)SmJm7dmJm7bmK3IWmK!%M!!)uc!s%cW!<2Bg!:K7TrpBpimd:)C
+!64F-<WDd\"*r&/@=S~>
+!quZ5p>uBRs7POS!;bgX!<2*_!9WDDroO1\roO1\qrRkYroOCbk2l[+joGDCrrDcT!s%KG!;km\
+!9WDDqrRkYr8n(]k2l[@jo>D\jo>DZjo>DYjo>D\joYVGjoGDC!!*#\!!)rZ!s%KG!;P[V!<2*_
+!9WDDqrRkYqrRkYroO:_k2l[Cjo>D\jo>DZjoYVGjoG2=!!)u[!s%KG!<2*_!9WDDroO@ak2l[+
+!64.%;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7G^Z!<)<m!:K7Tmd:&Tmd:)SmJm7dmJm7amJm7dmKN[ZmJu\C!<2Ed!;Gp]!<;He
+!;l0d!:K7TqsOIarU'afmd:)PmK<OXmJm7bmJm7amJm7dmK3IWmK!7S!!*#d!!)rb!s%cW!;Pse
+!:K7T!:K7TqsFFaqsFFarpBjgmd:)SmJm7dmJm7bmK3IWmK!%M!!)uc'EIRh!:K7T!:K7Tmd:&T
+md:)C!!((-!E/skmK5J>Ua^f~>
+!m8N2p?hr]s7G^Z!<)<m!:K7Tmd:&Tmd:)SmJm7dmJm7amJm7dmKN[ZmJu\C!<2Ed!;Gp]!<;He
+!;l0d!:K7TqsOIarU'afmd:)PmK<OXmJm7bmJm7amJm7dmK3IWmK!7S!!*#d!!)rb!s%cW!;Pse
+!:K7T!:K7TqsFFaqsFFarpBjgmd:)SmJm7dmJm7bmK3IWmK!%M!!)uc'EIRh!:K7T!:K7Tmd:&T
+md:)C!!((-!EK0nmK7mWb$ff~>
+!rqu=p>uBRs7GFR!<)$e!9WDDk2lXDk2l[Cjo>D\jo>DYjo>D\jothJjoFQ+!<2-\!;GXU!<;0]
+!;km\!9WDDqr[nYrT41^k2l[@job\Hjo>DZjo>DYjo>D\joYVGjoGDC!!*#\!!)rZ!s%KG!;P[]
+!9WDD!9WDDqrRkYqrRkYroO:_k2l[Cjo>D\jo>DZjoYVGjoG2=!!)u['EI:X!9WDD!9WDDk2lXD
+k2l[+!!((%!E/skjo`m%s."T~>
+!h?&@p?hrZs7>[W!<2Ec!!M]imd:)SmJm7cmem.cmJm7dmKN[ZmJm7T!<2Ed!;l3^!<)?a!<;He
+!<2Eb!<2Eb!!M]i!:K:R!<2Ed!!2Kfr9aObqsFFarpBjgmd:)SmeZtamf!4bmem._mf!4cmJm7a
+mJm7amJm7dmK3IWmK!7SqZ$WarW)obr;cc`quH]`rW)obrW)rc"9@lX!!(+.!E/skmK52>S1/s~>
+!liB.p?hr]s7>[W!<2Ec!!M]imd:)SmJm7cmem.cmJm7dmKN[ZmJm7T!<2Ed!;l3^!<)?a!<;He
+!<2Eb!<2Eb!!M]i!:K:R!<2Ed!!2Kfr9aObqsFFarpBjgmd:)SmeZtamf!4bmem._mf!4cmJm7a
+mJm7amJm7dmK3IWmK!7SqZ$WarW)obr;cc`quH]`rW)obrW)rc"9@lX!!(+.!EK0nmK7aW`aOA~>
+!quZ5p>uBRs7>CO!<2-[!!MEak2l[Cjo>D[k5>;[jo>D\jothJjo>DD!<2-\!;kpV!<)'Y!<;0]
+!<2-Z!<2-Z!!MEa!9WGB!<2-\!!23^r8mtZqrRkYroO:_k2l[Ck5,,Yk5GAZk5>;Wk5GA[jo>DY
+jo>DYjo>D\joYVGjoGDCqZ$WYrW)oZr;ccXquH]XrW)oZrW)r["9@TH!!(+&!E/skjo`U&p8!3~>
+!i2>Hp?hrZs2aU.!.jR%mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s2aU.!.jR%mK$>fp?i$2`l__?~>
+!rqu=p>uBRs2a=&!.j9rjoJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs7YmU!8QuB!.jR%mK$5cp?i#;Umrla~>
+!liB.p?hr]s7YmU!8QuB!.jR%mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7YUM!8Q]:!.j9rjoJB[p>uIrs7W7=~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7l$Y!9W_K!;l0a!:&tP!.jR8mK$5cp?i#;Umrla~>
+!liB.p?hr]s7l$Y!9W_K!;l0a!:&tP!.jR8mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7kaQ!9WGC!;kmY!:&\H!.j:0joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs7Pd[!9<JI!;Z$_!:&tP!.jR8mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7Pd[!9<JI!;Z$_!:&tP!.jR8mK$>fp?i$2`l__?~>
+!rqu=p>uBRs7PLS!9<2A!;YaW!:&\H!.j:0joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs7Pd[!:]CV!;5a[!;u6e!:K7TlL"WPJaTE'!E/skmK52>S1/s~>
+!liB.p?hr]s7Pd[!:]CV!;5a[!;u6e!:K7TlL"WPJaTE'!EK0nmK7aW`aOA~>
+!quZ5p>uBRs7PLS!:]+N!;5IS!;ts]!9WDDlK/'HJ``il!E/skjo`U&p8!3~>
+!i2>Hp?hrZs7Pd[!;u9a!<2Bh!:K7Tmf!4amf!4dmf!4cmf!1fmJu\S!<2Ec!;l0d!:BgerpBde
+mf!4dmf!4dmf!4cmem.bmf!4cmJm6<m`"Sp;ZHIY"$)mI.=_~>
+!m8N2p?hr]s7Pd[!;u9a!<2Bh!:K7Tmf!4amf!4dmf!4cmf!1fmJu\S!<2Ec!;l0d!:BgerpBde
+mf!4dmf!4dmf!4cmem.bmf!4cmJm6<m`"Sp<WDd\"+A23@=S~>
+!rqu=p>uBRs7PLS!;u!Y!<2*`!9WDDk5GAYk5GA\k5GA[k5G>^joFQC!<2-[!;km\!9O7]roO4]
+k5GA\k5GA\k5GA[k5>;Zk5GA[jo>C4k/HH`;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7Pd[!<)<p!:K7T!:K7Tmd:)CmK!1Q#6=2[!!)HT!;u6p!:K7T!:K7Tmd:)CmJm7b
+mf*7rmJm7TmJm7TmJu\C!!)oa!s%cW!;u6f!:K7T!.jRTmK$5cp?i#;Umrla~>
+!liB.p?hr]s7Pd[!<)<p!:K7T!:K7Tmd:)CmK!1Q#6=2[!!)HT!;u6p!:K7T!:K7Tmd:)CmJm7b
+mf*7rmJm7TmJm7TmJu\C!!)oa!s%cW!;u6f!:K7T!.jRTmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7PLS!<)$h!9WDD!9WDDk2l[+joG>A#6<oK!!)0D!;tsh!9WDD!9WDDk2l[+jo>DZ
+k5PDjjo>DDjo>DDjoFQ+!!)oY!s%KG!;ts^!9WDD!.j:LjoJB[p>uIrs7W7=~>
+!i2>Hp?hrZs7Pd[!<)<c!<2Bd!<2Ed!<2Bd!;u6b!<2Bg!:K7Tr9aXemd:)SmK3IWmK!7S!!)rb
+!!*#d!s%cW!<2Bg!:K7TqX+Fcmd:)QmJm7dmJm6<m_\Am;ZHIY"$)mI.=_~>
+!m8N2p?hr]s7Pd[!<)<c!<2Bd!<2Ed!<2Bd!;u6b!<2Bg!:K7Tr9aXemd:)SmK3IWmK!7S!!)rb
+!!*#d!s%cW!<2Bg!:K7TqX+Fcmd:)QmJm7dmJm6<m_\Am<WDd\"+A23@=S~>
+!rqu=p>uBRs7PLS!<)$[!<2*\!<2-\!<2*\!;tsZ!<2*_!9WDDr8n(]k2l[CjoYVGjoGDC!!)rZ
+!!*#\!s%KG!<2*_!9WDDqW7k[k2l[Ajo>D\jo>C4k/-6];ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7Pd[!<2E`!<2Ed!<2Bd!;u6b!<2Bg!:K7Tr9aXemd:)SmK!=UqZ-Q^!!*#d!s%cW
+!<2Bg!:K7TrU0UarpKdds6faaJaUDC!E/skmK52>S1/s~>
+!liB.p?hr]s7Pd[!<2E`!<2Ed!<2Bd!;u6b!<2Bg!:K7Tr9aXemd:)SmK!=UqZ-Q^!!*#d!s%cW
+!<2Bg!:K7TrU0UarpKdds6faaJaUDC!EK0nmK7aW`aOA~>
+!quZ5p>uBRs7PLS!<2-X!<2-\!<2*\!;tsZ!<2*_!9WDDr8n(]k2l[CjoGJEqZ-QV!!*#\!s%KG
+!<2*_!9WDDrT=%YroX4\s5s1YJ`ai3!E/skjo`U&p8!3~>
+!i2>Hp?hrZs7Pd[!<)<c!;c-`!<2Bd!;u6b!<2Bg!:K7Tr9aXemd:)SmK3IWmK!%M!!*#d!s%cW
+!<2Bg!:K7TrpBadrpBadr9aXemd:(+m_8)i;ZHIY"$)mI.=_~>
+!m8N2p?hr]s7Pd[!<)<c!;c-`!<2Bd!;u6b!<2Bg!:K7Tr9aXemd:)SmK3IWmK!%M!!*#d!s%cW
+!<2Bg!:K7TrpBadrpBadr9aXemd:(+m_8)i<WDd\"+A23@=S~>
+!rqu=p>uBRs7PLS!<)$[!;bjX!<2*\!;tsZ!<2*_!9WDDr8n(]k2l[CjoYVGjoG2=!!*#\!s%KG
+!<2*_!9WDDroO1\roO1\r8n(]k2lYpk.]sY;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7Pd[!<)<c!;l0g!:K7Tmd:)QmKWa[mJm7TmK!1Q!s%cW!<2Bg!:K7Tq!J@emd:&T
+md:)SmK3IWmK!7S!!*#d!!)rb!s%cW!.jRPmK$5cp?i#;Umrla~>
+!liB.p?hr]s7Pd[!<)<c!;l0g!:K7Tmd:)QmKWa[mJm7TmK!1Q!s%cW!<2Bg!:K7Tq!J@emd:&T
+md:)SmK3IWmK!7S!!*#d!!)rb!s%cW!.jRPmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7PLS!<)$[!;km_!9WDDk2l[Ajp(nKjo>DDjoG>A!s%KG!<2*_!9WDDpuVe]k2lXD
+k2l[CjoYVGjoGDC!!*#\!!)rZ!s%KG!.j:HjoJB[p>uIrs7W7=~>
+!i2>Hp?hrZs7Pd[!;u9`!"&&n!:K7T!:Bger9jOarpBadr9jRb!U]semJm7dmem.`mem.bmJm7d
+mK3IWmK!7SqZ$WarW)obr;clc!!%T<`U3b)s7Yj_3LlloJ,~>
+!m8N2p?hr]s7Pd[!;u9`!"&&n!:K7T!:Bger9jOarpBadr9jRb!U]semJm7dmem.`mem.bmJm7d
+mK3IWmK!7SqZ$WarW)obr;clc!!%T<`U3b,s7Yj_IE'E<J,~>
+!rqu=p>uBRs7PLS!;u!X!"%cf!9WDD!9O7]r9!tYroO1\r9""Z!TjC]jo>D\k5>;Xk5>;Zjo>D\
+joYVGjoGDCqZ$WYrW)oZr;cl[!!%T4`T@2!s7YRWc1_1-J,~>
+!h?&@p?hrZs1Ib"!.jR1mK$5cp?i#;Umrla~>
+!liB.p?hr]s1Ib"!.jR1mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs1IIo!.j:)joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs1Rjs!.jR6mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s1Rjs!.jR6mK$>fp?i$2`l__?~>
+!rqu=p>uBRs1RRk!.j:.joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l#5;Lqa4;?5kSmK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7l#5<In0:<<21VmK$>fp?i$2`l__?~>
+!rqu=p>uBRs7k`-;Lqa4;YT;S;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7l!^;M"k!s6]gdk4n?F;ZHIY"#6UA.=_~>
+!liB.p?hr]s7l!^<It1$s6]gdk4n?F<WDd\"*r&/@=S~>
+!quZ5p>uBRs7k^V;M"k!s6]j\joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs7l!^;M"k!s6]gdk4n?F;ZHIY"$)mI.=_~>
+!m8N2p?hr]s7l!^<It1$s6]gdk4n?F<WDd\"+A23@=S~>
+!rqu=p>uBRs7k^V;M"k!s6]j\joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs7l!^;V_9P!.k06rrD3VmK$5cp?i#;Umrla~>
+!liB.p?hr]s7l!^<S[TS!.k06rrD3VmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7k^V;V_9P!.k06s7bXV;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l!^;V_9P!.k06rrD3VmK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7l!^<S[TS!.k06rrD3VmK$>fp?i$2`l__?~>
+!rqu=p>uBRs7k^V;V_9P!.k06s7bXV;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7l!^;Z-Op!:Bdd!;HKn!.k06rrD3VmK$5cp?i#;Umrla~>
+!liB.p?hr]s7l!^<W)js!:Bdd!;HKn!.k06rrD3VmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7k^V;Z-Op!:Bdd!;HKn!.k06s7bXV;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l!^;Z-Op!:Bdd!;HKn!.k06rrD3VmK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7l!^<W)js!:Bdd!;HKn!.k06rrD3VmK$>fp?i$2`l__?~>
+!rqu=p>uBRs7k^V;Z-Op!:Bdd!;HKn!.k06s7bXV;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7l!d;ZHass8N)drr<&nrr<%Ms-*H_k4n?F;ZHIY"#6UA.=_~>
+!liB.p?hr]s7l!d<WE(!s8N)drr<&nrr<%Ms-*H_k4n?F<WDd\"*r&/@=S~>
+!quZ5p>uBRs7k^\;ZHass8N)drr<&nrr<%Ms-*KWjoJB[p>uIrs7W7=~>
+!i2>Hp?hrZs7l!_;ZH^r!ri9#rW)rtrW)rt!<E0!!<<'&!<<'!s8W#t!WN.Ns-*H_k4n?F;ZHIY
+"$)mI.=_~>
+!m8N2p?hr]s7l!_<WE$u!ri9#rW)rtrW)rt!<E0!!<<'&!<<'!s8W#t!WN.Ns-*H_k4n?F<WDd\
+"+A23@=S~>
+!rqu=p>uBRs7k^W;ZH^r!ri9#rW)rtrW)rt!<E0!!<<'&!<<'!s8W#t!WN.Ns-*KWjoJB[p>uJ%
+pA^Y5~>
+!h?&@p?hrZs7l!h;ZHass8N'!s8N)rrsSo-rr<'!rrE*!!<3&urr<&trr<%Ms-*H_k4n?F;ZHIY
+"#6UA.=_~>
+!liB.p?hr]s7l!h<WE(!s8N'!s8N)rrsSo-rr<'!rrE*!!<3&urr<&trr<%Ms-*H_k4n?F<WDd\
+"*r&/@=S~>
+!quZ5p>uBRs7k^`;ZHass8N'!s8N)rrsSo-rr<'!rrE*!!<3&urr<&trr<%Ms-*KWjoJB[p>uIr
+s7W7=~>
+!i2>Hp?hrZs7l!d;ZHass8N)urr<&rrrW9$rrE&u"T\T&!<3&urr<&trr<%Ms-*H_k4n?F;ZHIY
+"$)mI.=_~>
+!m8N2p?hr]s7l!d<WE(!s8N)urr<&rrrW9$rrE&u"T\T&!<3&urr<&trr<%Ms-*H_k4n?F<WDd\
+"+A23@=S~>
+!rqu=p>uBRs7k^\;ZHass8N)urr<&rrrW9$rrE&u"T\T&!<3&urr<&trr<%Ms-*KWjoJB[p>uJ%
+pA^Y5~>
+!h?&@p?hrZs7l!d;ZHass8N)urr<&us8;rtrr<&urr`?%rr<&ss8N*!rr<%Ms-*H_k4n?F;ZHIY
+"#6UA.=_~>
+!liB.p?hr]s7l!d<WE(!s8N)urr<&us8;rtrr<&urr`?%rr<&ss8N*!rr<%Ms-*H_k4n?F<WDd\
+"*r&/@=S~>
+!quZ5p>uBRs7k^\;ZHass8N)urr<&us8;rtrr<&urr`?%rr<&ss8N*!rr<%Ms-*KWjoJB[p>uIr
+s7W7=~>
+!i2>Hp?hrZs7l!d;ZHass8N)urrW9$rrE&u!s&B$!<3!%!<<'!rrDrr!W`6#JcCr6!9X(E!E/sk
+mK5J>Ua^f~>
+!m8N2p?hr]s7l!d<WE(!s8N)urrW9$rrE&u!s&B$!<3!%!<<'!rrDrr!W`6#JcCr6!9X(E!EK0n
+mK7mWb$ff~>
+!rqu=p>uBRs7k^\;ZHass8N)urrW9$rrE&u!s&B$!<3!%!<<'!rrDrr!W`6#JcCr6pZ;KSs7YRW
+c1_1-J,~>
+!h?&@p?hrZs7l!d;ZHass8N)urrW9$rrE&u!s&B$!<3!&!<<'!rr<&srrN3#!.k06rrD3VmK$5c
+p?i#;Umrla~>
+!liB.p?hr]s7l!d<WE(!s8N)urrW9$rrE&u!s&B$!<3!&!<<'!rr<&srrN3#!.k06rrD3VmK$>f
+p?i$.b/Rk?~>
+!quZ5p>uBRs7k^\;ZHass8N)urrW9$rrE&u!s&B$!<3!&!<<'!rr<&srrN3#!.k06s7bXV;ZHIQ
+"3(<6Ujr~>
+!i2>Hp?hrZs7l!d;ZHas!<3&urrN3#s8)csrrE&u#QXo)!<<'!!<<#us8N'!JcCr6!9X(E!E/sk
+mK5J>Ua^f~>
+!m8N2p?hr]s7l!d<WE(!!<3&urrN3#s8)csrrE&u#QXo)!<<'!!<<#us8N'!JcCr6!9X(E!EK0n
+mK7mWb$ff~>
+!rqu=p>uBRs7k^\;ZHas!<3&urrN3#s8)csrrE&u#QXo)!<<'!!<<#us8N'!JcCr6pZ;KSs7YRW
+c1_1-J,~>
+!h?&@p?hrZs7l!^;V_9P!.k06rrD3VmK$5cp?i#;Umrla~>
+!liB.p?hr]s7l!^<S[TS!.k06rrD3VmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7k^V;V_9P!.k06s7bXV;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l!^;V_9P!.k06rrD3VmK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7l!^<S[TS!.k06rrD3VmK$>fp?i$2`l__?~>
+!rqu=p>uBRs7k^V;V_9P!.k06s7bXV;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7l!^;V_9P!.k06rrD3VmK$5cp?i#;Umrla~>
+!liB.p?hr]s7l!^<S[TS!.k06rrD3VmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7k^V;V_9P!.k06s7bXV;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l!^;M"k!s6]gdk4n?F;ZHIY"$)mI.=_~>
+!m8N2p?hr]s7l!^<It1$s6]gdk4n?F<WDd\"+A23@=S~>
+!rqu=p>uBRs7k^V;M"k!s6]j\joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs7l#5k(2[\k4n?F;ZHIY"#6UA.=_~>
+!liB.p?hr]s7l#5k(2[\k4n?F<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7YmY!<;He!8?l?!:]CV!:&tP!.jRRmK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7YmY!<;He!8?l?!:]CV!:&tP!.jRRmK$>fp?i$2`l__?~>
+!rqu=p>uBRs7YUQ!<;0]!8?T7!:]+N!:&\H!.j:JjoJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs7bp]!;c*`!8?i@!:K7T!:&tP!.jRRmK$5cp?i#;Umrla~>
+!liB.p?hr]s7bp]!;c*`!8?i@!:K7T!:&tP!.jRRmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7bXU!;bgX!8?Q8!:JtL!:&\H!.j:JjoJB[p>uIrs7W7=~>
+!i2>Hp?hrZs7bp]!;c*`!:]CV!:oOX!;u6b!:fIZ!:K7TlL"WPJaU>A!E/skmK5J>Ua^f~>
+!m8N2p?hr]s7bp]!;c*`!:]CV!:oOX!;u6b!:fIZ!:K7TlL"WPJaU>A!EK0nmK7mWb$ff~>
+!rqu=p>uBRs7bXU!;bgX!:]+N!:o7P!;tsZ!:f1R!9WDDlK/'HJ`ac1!E/skjo`m%s."T~>
+!h?&@p?hrZs7bs]!;l0b!:KgdrpKacrpKX`s6fgc!U]semK!=UrW)rcrW)udrW)rcrW)rcrW!#f
+!:KgdrpKacqsFOdmJm7dmK!=UrW)udrW)udrW)rcr;cibrW)rc!!%T<hsLMCs7Yj_0r1<gJ,~>
+!liB.p?hr]s7bs]!;l0b!:KgdrpKacrpKX`s6fgc!U]semK!=UrW)rcrW)udrW)rcrW)rcrW!#f
+!:KgdrpKacqsFOdmJm7dmK!=UrW)udrW)udrW)rcr;cibrW)rc!!%T<hsLMFs7Yj_H-4-8J,~>
+!quZ5p>uBRs7b[U!;kmZ!9X7\roX1[roX(Xs5s7[!TjC]joGJErW)r[rW)u\rW)r[rW)r[rW!#^
+!9X7\roX1[qrRt\jo>D\joGJErW)u\rW)u\rW)r[r;ciZrW)r[!!%T4hrXr;s7YRW`W,Y-J,~>
+!i2>Hp?hrZs7Ym[!<)?c!<;I"!:K7Tmd:&Tmd:&Tmd:)CmJm7cmJm7dmK3IWmK!1Q$NTV_!:K7T
+!:K7T!;u6p!:K7T!:K7Tmd:)CmJm7bmf*7rmJm7TmJm7TmJu\C!!)oa!s%cW!;u6f!:K7T!.jRn
+mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7Ym[!<)?c!<;I"!:K7Tmd:&Tmd:&Tmd:)CmJm7cmJm7dmK3IWmK!1Q$NTV_!:K7T
+!:K7T!;u6p!:K7T!:K7Tmd:)CmJm7bmf*7rmJm7TmJm7TmJu\C!!)oa!s%cW!;u6f!:K7T!.jRn
+mK$>fp?i$2`l__?~>
+!rqu=p>uBRs7YUS!<)'[!<;0o!9WDDk2lXDk2lXDk2l[+jo>D[jo>D\joYVGjoG>A$NT>O!9WDD
+!9WDD!;tsh!9WDD!9WDDk2l[+jo>DZk5PDjjo>DDjo>DDjoFQ+!!)oY!s%KG!;ts^!9WDD!.j:f
+joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs7GaZ!<2Bd!<2Bg!:K7TrpBjgmd:)SmK3IWmK!1Q!!*#d!s%cW!;u6e!:K7TrpBjg
+md:)PmK3IWmK!7S!s%cW!<2Bd!;u6b!<2Bg!:K7TrpBjgmd:)OmK3IWmK!1Q!!*#d!!%T<h!P2@
+s7Yj_0r1<gJ,~>
+!liB.p?hr]s7GaZ!<2Bd!<2Bg!:K7TrpBjgmd:)SmK3IWmK!1Q!!*#d!s%cW!;u6e!:K7TrpBjg
+md:)PmK3IWmK!7S!s%cW!<2Bd!;u6b!<2Bg!:K7TrpBjgmd:)OmK3IWmK!1Q!!*#d!!%T<h!P2C
+s7Yj_H-4-8J,~>
+!quZ5p>uBRs7GIR!<2*\!<2*_!9WDDroO:_k2l[CjoYVGjoG>A!!*#\!s%KG!;ts]!9WDDroO:_
+k2l[@joYVGjoGDC!s%KG!<2*\!;tsZ!<2*_!9WDDroO:_k2l[?joYVGjoG>A!!*#\!!%T4gu\W8
+s7YRW`W,Y-J,~>
+!i2>Hp?hrZs7>[Y!<;He!<2Bg!:K7TrpBjgmd:)SmK3IWmK!1Q!!*#d!s%cW!;u6e!:K7TrpBjg
+md:)PmK3IWmK!7S!<DQb!;u6b!<2Bg!:K7TrpBjgmd:)Rmem.bmf*:eme[!8mbI42;ZHIY"$)mI
+.=_~>
+!m8N2p?hr]s7>[Y!<;He!<2Bg!:K7TrpBjgmd:)SmK3IWmK!1Q!!*#d!s%cW!;u6e!:K7TrpBjg
+md:)PmK3IWmK!7S!<DQb!;u6b!<2Bg!:K7TrpBjgmd:)Rmem.bmf*:eme[!8mbI42<WDd\"+A23
+@=S~>
+!rqu=p>uBRs7>CQ!<;0]!<2*_!9WDDroO:_k2l[CjoYVGjoG>A!!*#\!s%KG!;ts]!9WDDroO:_
+k2l[@joYVGjoGDC!<D9Z!;tsZ!<2*_!9WDDroO:_k2l[Bk5>;Zk5PG]k5,.0k1o)";ZHIQ"3pQ>
+S:C~>
+!h?&@p?hrZs75R[!:K7TrpBjgmd:)SmK3IWmK!7S!s%cW!;u6b!<2Bg!:K7Tr9aXemd:)SmK3IW
+mK!.P!s%cW!<2Bg!:K7Tq!J+^rpBjgmd:)SmK3IWmK!7S!!*#d!!)rb!s%cW!.jRjmK$5cp?i#;
+Umrla~>
+!liB.p?hr]s75R[!:K7TrpBjgmd:)SmK3IWmK!7S!s%cW!;u6b!<2Bg!:K7Tr9aXemd:)SmK3IW
+mK!.P!s%cW!<2Bg!:K7Tq!J+^rpBjgmd:)SmK3IWmK!7S!!*#d!!)rb!s%cW!.jRjmK$>fp?i$.
+b/Rk?~>
+!quZ5p>uBRs75:S!9WDDroO:_k2l[CjoYVGjoGDC!s%KG!;tsZ!<2*_!9WDDr8n(]k2l[CjoYVG
+joG;@!s%KG!<2*_!9WDDpuVPVroO:_k2l[CjoYVGjoGDC!!*#\!!)rZ!s%KG!.j:bjoJB[p>uIr
+s7W7=~>
+!i2>Hp?hrZs7>[Y!<;He!<2Bn!:K7Tmd:&Tmd:)SmK<OXmJm7cmKWa[mJm7TmK!1Q$39M^!:K7T
+!:K7TqsFOdmd:)SmK3IWmK!%M#6=2[!!)HT!<2Bg!:K7TrpBadrpBadr9aXemd:(+mb$q.;ZHIY
+"$)mI.=_~>
+!m8N2p?hr]s7>[Y!<;He!<2Bn!:K7Tmd:&Tmd:)SmK<OXmJm7cmKWa[mJm7TmK!1Q$39M^!:K7T
+!:K7TqsFOdmd:)SmK3IWmK!%M#6=2[!!)HT!<2Bg!:K7TrpBadrpBadr9aXemd:(+mb$q.<WDd\
+"+A23@=S~>
+!rqu=p>uBRs7>CQ!<;0]!<2*f!9WDDk2lXDk2l[Cjob\Hjo>D[jp(nKjo>DDjoG>A$395N!9WDD
+!9WDDqrRt\k2l[CjoYVGjoG2=#6<oK!!)0D!<2*_!9WDDroO1\roO1\r8n(]k2lYpk1Jes;ZHIQ
+"3pQ>S:C~>
+!h?&@p?hrZs7bsZ!<2Bd!<2Bd!<2Ec!<2Bd!<2Ed!<;Kc!!)Hd!!Vcjmd:&TrU'XcrpKacrpBad
+qsOIa!U]semJm7dmem.`mem.bmJm7dmK3IWmK!7SqZ$WarW)obr;clc!!%T<hsLMCs7Yj_0r1<g
+J,~>
+!liB.p?hr]s7bsZ!<2Bd!<2Bd!<2Ec!<2Bd!<2Ed!<;Kc!!)Hd!!Vcjmd:&TrU'XcrpKacrpBad
+qsOIa!U]semJm7dmem.`mem.bmJm7dmK3IWmK!7SqZ$WarW)obr;clc!!%T<hsLMFs7Yj_H-4-8
+J,~>
+!quZ5p>uBRs7b[R!<2*\!<2*\!<2-[!<2*\!<2-\!<;3[!!)0\!!VKbk2lXDrT4([roX1[roO1\
+qr[nY!TjC]jo>D\k5>;Xk5>;Zjo>D\joYVGjoGDCqZ$WYrW)oZr;cl[!!%T4hrXr;s7YRW`W,Y-
+J,~>
+!i2>Hp?hrZs.\o]!.jRKmK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s.\o]!.jRKmK$>fp?i$2`l__?~>
+!rqu=p>uBRs.\WU!.j:CjoJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs.\o]!.jRKmK$5cp?i#;Umrla~>
+!liB.p?hr]s.\o]!.jRKmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs.\WU!.j:CjoJB[p>uIrs7W7=~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0U@m^W>imK$5cp?i#;Umrla~>
+!liB.p?hr]s+0UDmeuF]!<)3XmK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs+0=<k5F/I!<(dLjoJB[p>uIrs7W7=~>
+!i2>Hp?hrZs+0UCmf!3ss8E#mmK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s+0UDmJuPO!4i./!!)<ZmK$>fp?i$2`l__?~>
+!rqu=p>uBRs+0=<joF9;!4i./!!(mNjoJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs+0UDmJm6qs8I'>!;Ps_;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0UDmJm6qs8I-@!;Ps_<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0=<jo>Cis8Ha5!;P[W;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0UDmJm6ss86p<!;Ps_;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0UDmJm6ss87!>!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs+0=<jo>Cks86U3!;P[W;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0UDmJm7bs1VA2s86p<!;Ps_;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0UDmJm7bs1VJ5s87!>!;Ps_<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0=<jo>DZs1VA2s86U3!;P[W;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$2`l__?~>
+!rqu=p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#;Umrla~>
+!liB.p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$2`l__?~>
+!rqu=p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#;Umrla~>
+!liB.p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs7l$\pA=mep9O,bpA=mep8[N\!;uis;SVW"s86p<!;Ps_;ZHIY"$)mI.=_~>
+!m8N2p?hr]s7l!bo'Z):o)/Ljo'Z):o!.Tco'Z):o)/Ljo'Z):nu;$W!;uis<PRf!s87!>!;Ps_
+<WDd\"+A23@=S~>
+!rqu=p>uBRs7kaSmem+^m]u!Qmem+^m],CL!;uis;SV&gs86U3!;P[W;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7bp`p?qtSr;Zca!qu'UZ0h_fmf3"Ys8MEfp?qXSmJm7brr>s3mK!:bErZ48mK$5c
+p?i#;Umrla~>
+!liB.p?hr]s7bpao'ZPGpAY'rqWdA6o'Z(RmKE+Ks6fU[rs&>blL+62nuD*X!;uis<PRf!s87!>
+!;Ps_<WDd\"*r&/@=S~>
+!quZ5p>uBRs7bX]mcOQ3p@eO[pAX1UmcNrBjp:D;s5s%Ks7Z0cjoXu5m],CL!;uis;SV&gs86U3
+!;P[W;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l!mp?pf*p>4ZVhVRtohX:+2ZL/7smb[C*hVQf>hY-Bome6@SmJm7brr>s3mK!:b
+ErZ48mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7l!co'4fcmahBc"kN,(f';h2mKN1Hf&H,KrmCu$mcN*cnu;$W!;uis<PRf!s87!>
+!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs7k^ZmcMdNk5<I-mbZ4Nmd@CC"RbEshWFa\"n(6lk3hZ;jo>DZrr>s3h>mTRC&e8/
+joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs7bs\h@%SmMh?B,`TH%6me6PG!!)rb!!'b$rn\%-P`(0@e]$\-hX:+5med'omJm7b
+rr>sbmJm7bmJm7?mK!:bErZ48mK$5cp?i#;Umrla~>
+!liB.p?hr]s7bpkf%Sj'NJW47cGJ;hf'`,+mJm7bmJm7$mLIh%g<P\7JUPh\g=k-Go(h_O!4V@r
+!;uis<UT,P!;u*^!86W;s87!>!;Ps_<WDd\"*r&/@=S~>
+!quZ5p>uBRs7bXce]lX`Mh?Y/`P'gHc0"Hkjo>DZjo>Cqjpoqde]!H!K6tSNe]lA$meQ#C!4V(j
+!;uis;XWBA!;t[R!863/s86U3!;P[W;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l!mk0;c%Pa(n8s7YTgk0;cVqsOIarU'Xc^[;Wpc/-F(PkOhNp?''Nc//0jmJm7c
+mJm6rmJm7brr>sbmf*:cmJm7?mK!:bErZ48mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7l!dhT"9dM2gs&nc[s`g;_kCmf*:cmJm7%mKVOfg;8]+mf)b[ik!j`gA1.:!<)<c
+!4V@r!;uis<UT/P!<)0_!86W;s87!>!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs7k^[hS%IHMi7Q%"l?W:^")QJk5PG[jo>CrjosVTe[16mrU'jG[+2k?meZ&G!<)$[
+!4V(j!;uis;XWEA!<(aS!863/s86U3!;P[W;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7l!b^#$GLPl(I_c+Vu@qX4=_rpBad^[;6<hS"9#qu6cC^#$-mmf*:SmJm7-mJm7b
+rr>sbmf!4cmJm7?mK!:bErZ48mK$5cp?i#;Umrla~>
+!liB.p?hr]s7l!c]$e04NV<;M"3S4'[efFk!<2Bd!5Iq*]$e04NV<;M"3S4'[efFl!:B1S!6=L-
+!;uis<UT/O!<26`!86W;s87!>!;Ps_<WDd\"*r&/@=S~>
+!quZ5p>uBRs7k^[[*>[nMt[)K"3%XlXSV)Y!<2*\!5IY"[*>[nMt[)K"3%XlXSV)Z!:AnK!6=4%
+!;uis;XWE@!<1gT!863/s86U3!;P[W;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l!dUun2"s8NB(!<<'$SE?@(qsFLcmK!7S!!*#drW)rc!<DQe!<2Ec!7U?<Uun2"
+q>UPek+(T2mJm7_mJm7dmK*CVmem+cmf!4dmf!4cmK!=UqZ,::!!)rs!)i7Q!W_WgrpBadrpKac
+rpBdemf!4cmf!4RmK!:bErZ48mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7l!mS`6&gpAY6q"9AK%RGsXsqsFLcmK!7S!!*#drW)rc!<DQe!<2Ec!7U?=S`6&g
+pA4dkRGsXsqsFFaq<e4_rpBgfmdC#R!:Kgds6fjdrpBdeme[":mJm7brr?'el2gtN!<26`!<29_
+!<26a!:'O`rp'I_mHO]Or,hu>q!J/_s7Yj_IE'E<J,~>
+!rqu=p>uBRs7k^\SDKKWpAYEt!<<'$PhqY]qrRq[joGDC!!*#\rW)r[!<D9]!<2-[!7U'5SDKKW
+pA4dkPhqY]qrRkYq;qYWroO7^k2uUB!9X7\s5s:\roO4]k5,/2jo>DZrr>sbh?!]6!<1gT!<1jS
+!<1gU!8d\TrndVSmG7jCr+Z33puVTTs7YRWc1_1-J,~>
+!h?&@p?hrZs7l!cKE$jfs8W#ts8N1Zs+B2*mMc/o!!)HT!:K7Tmd:&Tmd:&Tmd:)CmJu\C!!(O:
+",$W3Mu!ATMuSFdqsFFaq<e4_rpBjgmd:)QmL]HemJu\C!!)HT!!)HT!:K7Tf^8_>r;Qapmd;"o
+mJm7TmJu\C!:K7T!:K7T!:K7Tmd:)CmJm7TmK!:bErZ48mK$5cp?i#;Umrla~>
+!liB.p?hr]s7l!cIK,.Xs8W#ts8N1XqL.5tmMc/o!!)HT!:K7Tmd:&Tmd:&Tmd:)CmJu\C!!(O:
+"+C3+L&(`NM>DYWqsFFaq<e4_rpBjgmd:)QmL]HemJu\C!!)HT!!)HT!:K7Tf^8_>r;Qasmck_k
+l2UhLl2^,7!:&hL!:&hL!:&hLlKSB7l2UhPl2^k^FT;F:mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs7k^[F7t6=pAb'ks8N1Rp2f*fjr4<_!!)0D!9WDDk2lXDk2lXDk2l[+joFQ+!!(O2
+"EX9hKD,0A",$;ghYZF8!;YaW!<2*_!9WDDr8nRkk2l[+jo>DDjo>DDjoFQ+!8-E6!;uis;XWB\
+!8[\UhVJ7hh>lEh!!(m4!!(m4!8cQ4hVJ54mbRsDr+Z33puVTTs7YRW`W,Y-J,~>
+!i2>Hp?hrZs7l!mMrpgVs8N'!#QXo)Uum<[qsFajmd:)CmJu\C!<2Bg!:K7TrpBjgmd:)SmJm7:
+mK8C0UiZA3"/P(3ebeb7!;Z$_!<2Bg!:K7Tr9aXemd:)SmK3IWmK!7S!s%cW!8-]>!;uis;XWrZ
+!:K7Tmd:)CmK!7S!s%cW!<2Bg!:K7TrpBadmd:)Tr,Vi<q!J/\s7Yj_3LlloJ,~>
+!m8N2p?hr]s7l!mL"`);s8N3%"9AK%S_AA?qsFajmd:)CmJu\C!<2Bg!:K7TrpBjgmd:)SmJm7:
+mK80sST4K*".e.kf)+k8!;Z$_!<2Bg!:K7Tr9aXemd:)SmK3IWmK!7S!s%cW!8-]>!;uis<UT,Y
+!:&hLlKSB7l2^hK!s%WO!<26c!:&hLrosI`mcjfPr,hu>q!J/_s7Yj_IE'E<J,~>
+!rqu=p>uBRs7k^eK@QK,s8N'!#QXo)SCMu2qrS1bk2l[+joFQ+!<2*_!9WDDroO:_k2l[Cjo>D2
+jo^7dS8.m"".[ngc26W'!;YaW!<2*_!9WDDr8n(]k2l[CjoYVGjoGDC!s%KG!8-E6!;uis;XWBJ
+!8cQ4hVJ7hh>mQ3!s%37!<1gW!8cQ4rn[VTmbRsDr+Z33puVTTs7YRWc1_1-J,~>
+!h?&@p?hrZs7l!cSAiI3s8W#ts8W,<!INAomJm7dmKEUY!:K7TrpBjgmd:)SmK!=UqZ,.6".[?L
+Pkk@Z`;t>9qsFFaq<e4_rpBadrpKddrpBjgmd:)SmK3IWmK!7S!s%cW!8-]>!;uis;XWrQ!<2Bi
+!:BjTmK!7S!s%cW!<2Be!:K^amd:)Tr,Vi<q!J/\s7Yj_0r1<gJ,~>
+!liB.p?hr]s7l!cQ+F\ds8W#ts8N28\p`$(mJm7dmKEUY!:K7TrpBjgmd:)SmK!=UqZ,.6"-pI3
+M>@/R^:Ja@qsFFaq<e4_rpBadrpKddrpBjgmd:)SmK3IWmK!7S!s%cW!8-]>!;uis<UT,P!<26e
+!9sRLl2^hK!s%WO!<26a!:'F]mcjfPr,hu>q!J/_s7Yj_H-4-8J,~>
+!quZ5p>uBRs7k^[PdIfMs8W#ts8W,+!HZN_jo>D\jokbI!9WDDroO:_k2l[CjoGJEqZ,.."-g1"
+KDGQIZiP6mqrRkYq;qYWroO1\roX4\roO:_k2l[CjoYVGjoGDC!s%KG!8-E6!;uis;XWBA!<1gY
+!8[_4h>mQ3!s%37!<1gU!8dSQmbRsDr+Z33puVTTs7YRW`W,Y-J,~>
+!i2>Hp?hrZs7l!a`Jabtq>UQjMj2chmJm7dmf!4dmJm7dmK3IWmK!7S!s%cW!7:-9`Jabtq>UQj
+Mj2chmf*:`mJm7dmJm7bmKN[ZmJu\C!<2Bg!:K7TrpBjgmd:)-mJm7brr>sbmJm7dmf!4dmJm7d
+mK3IWmK!7S!s%cW!:&tPs86p<!;Ps_;ZHIY"$)mI.=_~>
+!m8N2p?hr]s7l!a_MRu_q>UQbM36BdmJm7dmf!4dmJm7dmK3IWmK!7S!s%cW!7:-9_MRu_q>UQb
+M36Bdmf*:`mJm7dmJm7bmKN[ZmJu\C!<2Bg!:K7TrpBjgmd:)-mJm7brr?'el2Uh`lM^e`l2Uh`
+l2q%Ol2^hK!s%WO!:&hLs87!>!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs7k^Y]n?$Kq>UQZK8\"Ojo>D\k5GA\jo>D\joYVGjoGDC!s%KG!79j1]n?$Kq>UQZ
+K8\"Ok5PGXjo>D\jo>DZjothJjoFQ+!<2*_!9WDDroO:_k2lZrjo>DZrr>sbh>dQThYmNTh>dQT
+h?*c7h>mQ3!s%37!:&D@s86U3!;P[W;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7bp`Mlcrlqu6feUiWp"qsFFarU0[cs6^*lmd:&Tmd:)SmK3IWmJtT$",j8\^&.g4
+m\Fp2hYQX?!<)<j!:K7Tmd:&Tr9b!omd:)CmJu\C!!)HT!<2Bg!:K7Tf^8_>r;Qapmd:&TrU0[c
+s6^*lmd:&Tmd:)SmK3IWmJuP?!<;t<!!)f^!E/skmK52>S1/s~>
+!liB.p?hr]s7bp`M5BpSqu6f]TlIBpqsFFarU0[cs6^*lmd:&Tmd:)SmK3IWmJtT$",WlJ[ep(-
+k+Qe#hYQX?!<)<j!:K7Tmd:&Tr9b!omd:)CmJu\C!!)HT!<2Bg!:K7Tf^8_>r;QasmcjcPrTaC_
+s69ghlKS?LlKSBKl2q%Ol2^,7!<;t>!!)f^!EK0nmK7aW`aOA~>
+!quZ5p>uBRs7bXXK:MA2qu6fUS9(dgqrRkYrT=+[s5jOdk2lXDk2l[CjoYVGjoE`i",!-3XS`##
+hOJYghYQ@7!<)$b!9WDDk2lXDr8nFgk2l[+joFQ+!!)0D!<2*_!9WDDf]E/6r;QapmbRpDrSIPS
+s5!t\hVJ54hVJ83h?*c7h>lit!<;t3!!)fV!E/skjo`U&p8!3~>
+!i2>Hp?hrZs7l!ap<?L2rq?Bls7QSk;O#/_qsFFarU0[crpKacrpBadrpBadrpK^beF!G4bu1A:
+pAb0mp&q0hPf;e\mem.bmf!1gmJu\CrW)rcrrE)erW)rc!!*#d!s%cW!8-]>!;uis;XWrQ!<)?c
+!<2Ec!<2Bd!<2Bd!<2Eb!:K7Ts86p<!;Ps_;ZHIY"$)mI.=_~>
+!m8N2p?hr]s7l!mo$1(*mdBZ>qX3X>:m&WWqsFFarU0[crpKacrpBadrpBadrpK^beF!k<c;:5&
+mdg)Jmcp?>Oi$8Vmem.bmf!1gmJu\CrW)rcrrE)erW)rc!!*#d!s%cW!8-]>!;uis<UT,P!<)3_
+!<29_!<26`!<26`!<29^!:K+Ps87!>!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs7k^em`eY"k2u+"p?(M-;N&NNqrRkYrT=+[roX1[roO1\roO1\roX.ZeE.;0bu1(o
+k3h[2k2r13MoFQKk5>;Zk5G>_joFQ+rW)r[rrE)]rW)r[!!*#\!s%KG!8-E6!;uis;XWBA!<(dS
+!<1jS!<1gT!<1gT!<1jR!:J\Ds86U3!;P[W;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7bpjp;LcfXNg1`Zu]]7[,/%T%JIbUF0*XSe[0C,MmV??mJm7brr>s3mK!:bErZ48
+mK$5cp?i#;Umrla~>
+!liB.p?hr]s7Yjh_J+"db3%!PEFk!4g99oQ_J+"db3%!PEFk!4g8XK?!;uis<PRf!s87!>!;Ps_
+<WDd\"*r&/@=S~>
+!quZ5p>uBRs7bXbm_*(EUqPX(UhX@kXOXQ;%IUo=C8AQ"`M@6XK<3V&jo>DZrr>s3h>mTRC&e8/
+joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs7l$^p'pH?Mc)hq5uMco[+4U<r9j=[_!_6r%IVc);F*$';KJA8eaE/&meQpumJm7b
+rr>s3mK!:bErZ48mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s7l!lo'YekKiL5d4A^$cZI8%8me?dtmLJgUlI(Ad4=iTkELF,\lLOB>!5Iq%!;uis
+<PRf!s87!>!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs7kaUmL7?m;E60d;KJ)(c0k#tk4eqlk5OcWc%AnS.61:IPcW-tmdoT;!5IXr!;uis
+;SV&gs86U3!;P[W;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs7bpkp?qA*`N5SoS?0]dmdBeRmLJsYmbYpaS<TPF`SU%Np8[N\!;uis;SVW"s86p<
+!;Ps_;ZHIY"#6UA.=_~>
+!liB.p?hr]s7bpko'Yes^876[RAIXOlL+5JmLJgUlIrtKR?<o6^=ql?nuD*X!;uis<PRf!s87!>
+!;Ps_<WDd\"*r&/@=S~>
+!quZ5p>uBRs7bXcmcNZ^]qh0VPbc"Ck2u*:jpphAk1./@S;WW-^")9-m],CL!;uis;SV&gs86U3
+!;P[W;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs7l$[pAa:Sec4e1p9O,apAa:Sec4e1p8[N\!;uis;SVW"s86p<!;Ps_;ZHIY"$)mI
+.=_~>
+!m8N2p?hr]s7l!lo'Z):mcNBWdam:;mdBYNmLJgUo'Yr.hU^-+hWF7onu;$W!;uis<PRf!s87!>
+!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs7kaSmf2,Hc.1(qhYllJk5=ZIh?;*Rc/.=Um],CL!;uis;SV&gs86U3!;P[W;ZHIQ
+"3pQ>S:C~>
+!h?&@p?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#;Umrla~>
+!liB.p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$2`l__?~>
+!rqu=p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#;Umrla~>
+!liB.p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$2`l__?~>
+!rqu=p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs+0UDmJm7brr>s3mK!:bErZ48mK$5cp?i#;Umrla~>
+!liB.p?hr]s+0UDmJm7brr?'6l2^k^FT;F:mK$>fp?i$.b/Rk?~>
+!quZ5p>uBRs+0=<jo>DZrr>s3h>mTRC&e8/joJB[p>uIrs7W7=~>
+!i2>Hp?hrZs+0UDmJm6ss86p<!;Ps_;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0UDmJm6ss87!>!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs+0=<jo>Cks86U3!;P[W;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0UDmJm7_s1<=P!;Ps_;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0UDmJm7_s1<CR!;Ps_<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0=<jo>DWs1<"G!;P[W;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0UDmJm7as1*1N!;Ps_;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0UDmJm7as1*7P!;Ps_<WDd\"+A23@=S~>
+!rqu=p>uBRs+0=<jo>DYs1)kE!;P[W;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0UCmf!1ds13:N!;Gm^;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0UDmJuPO!!*&1FoD@@lM0cJ<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0=<joF9;!!*&1CAn25hY?46;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0U@m^W>imK$5cp?i#CS>7Ta~>
+!m8N2p?hr]s+0UDmeuF]!<)3XmK$>fp?i$2`l__?~>
+!rqu=p>uBRs+0=<k5F/I!<(dLjoJB[p>uJ%pA^Y5~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?hrZs+0Thmb."/;ZHIY"$)mI.=_~>
+!m8N2p?hr]s+0Thmb."/<WDd\"+A23@=S~>
+!rqu=p>uBRs+0<`k1Skt;ZHIQ"3pQ>S:C~>
+!h?&@p?hrZs+0Thmb."/;ZHIY"#6UA.=_~>
+!liB.p?hr]s+0Thmb."/<WDd\"*r&/@=S~>
+!quZ5p>uBRs+0<`k1Skt;ZHIQ"3(<6Ujr~>
+!i2>Hp?mK0JPt&s!<;c\"$)mI.=_~>
+!m8N2p?mK3JQ:9$!<;c\"+A23@=S~>
+!rqu=p?$p(JPt&s!<;cT"3pQ>S:C~>
+!h?&@p?mM3JcF:#p?i#;Umrla~>
+!liB.p?mM3JcF:#p?i$.b/Rk?~>
+!quZ5p?$r+JcF:#p>uIrs7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+!i2>HJaS*W^[;1aS>7Ta~>
+!m8N2JaS*W^[;2P`l__?~>
+!rqu=J`_OG^ZGXCpA^Y5~>
+!h?&@JaS*W^[;1YUmrla~>
+!liB.JaS*W^[;2Lb/Rk?~>
+!quZ5J`_OG^ZGX;s7W7=~>
+"JhPs@VYmOrFu=Arb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrG)=@"DVDAS2#N~>
+!QrFYV1GXtWlh@=V#nfZ@=S~>
+"98)gmf)n[mXb(_p;Ze0me6ASp8!3~>
+!M#taF8]hRF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fqQ@KN'q.=_~>
+!QN:\Xok],WiCQOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)Wii@OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)1p3j]WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)Wil?$rM9S8b$ff~>
+!quZ^rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq?B[#PRTZme6ASS:C~>
+"f.Z'@VTZVEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEs-6!F)#Ih@KN?q.=_~>
+"Nn`\V5f*LJZctps/Q'p!m8MkJ,~>
+!<7WDJbHeN"7H3_Ujr~>
+$(Reh>$>BEC1:Y%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peIqiG-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@QnO9C1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:pe@VT@]>$@Gl.=_~>
+$-(,YTqS<ZWhlPAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lJ#]?FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV*:oUWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lV5gAcSY='G@=S~>
+$24Dep?qYBp?q?up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBJ+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmQU@4p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBme6)Bme6ASS:C~>
+"/MGb;Z0f!@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO=@TlrE>%1Z=;P]g;J,~>
+!QrF\SUmJcTuE]0V4F<Nb/Rk?~>
+#QOMkme6)BmeuhZmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mec\]me6)Kp8!3~>
+!M#tb8d&$a;G'Q2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8iT^@;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ8lA:\;?EAa.=_~>
+"NJTLR?`>kJXOED"eD'P`l__?~>
+!VZQmmJutZmJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mK<1Nme6YJs7QKnS:C~>
+$)F)eS>;[NS>;s1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NJ"3=)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUct<ES>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NUn"6NUn"6N.=_~>
+$-L91`lc<D`lcGR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<DJ&]XNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb!*hf`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<Db/VTDb/VTD@=S~>
+$30`!pAajdpAb/BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds$$/VpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajds7ZKds7ZKdUjr~>
+JLQ.!\1)q~>
+JRO+<\7'm~>
+$(Rf]Un"6NUn!s)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NJ#&U1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS3Ea=Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NS>;[NS>;[NS:C~>
+%%EndData
+showpage
+%%Trailer
+end
+%%EOF
diff --git a/doc/kmouth/kmouthedit.png b/doc/kmouth/kmouthedit.png
new file mode 100644
index 0000000..38d28b1
--- /dev/null
+++ b/doc/kmouth/kmouthedit.png
Binary files differ
diff --git a/doc/kmouth/kmouthmain.eps b/doc/kmouth/kmouthmain.eps
new file mode 100644
index 0000000..5eb9f17
--- /dev/null
+++ b/doc/kmouth/kmouthmain.eps
@@ -0,0 +1,2284 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: GIMP PostScript file plugin V 1.15 by Peter Kirchgessner
+%%Title: /local/src/kde32/kdeaccessibility/doc/kmouth/kmouthmain.eps
+%%CreationDate: Sun May 30 15:13:10 2004
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%Pages: 1
+%%BoundingBox: 14 14 399 321
+%%EndComments
+%%BeginProlog
+% Use own dictionary to avoid conflicts
+10 dict begin
+%%EndProlog
+%%Page: 1 1
+% Translate for offset
+14.173228 14.173228 translate
+% Translate to begin of first scanline
+0.000000 306.000000 translate
+384.000000 -306.000000 scale
+% Image geometry
+384 306 8
+% Transformation matrix
+[ 384 0 0 306 0 0 ]
+% Strings to hold RGB-samples per scanline
+/rstr 384 string def
+/gstr 384 string def
+/bstr 384 string def
+{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
+true 3
+%%BeginData: 132079 ASCII Bytes
+colorimage
+JcC<$JcC6~>
+JcC<$JcC6~>
+JcC<$JcC6~>
+JcC<$JcC6~>
+JcC<$JcC6~>
+JcC<$JcC6~>
+g]%?3[%r82qhkQ@XMsmas0VfV~>
+g]%NDd`T;<]"Yn-]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"YcU^&u6thYMg'[/YX~>
+f`)*Js7ZKmIeNg8s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds8N)mJcE"TJ,~>
+h>[fLUk=SXMh?q?K78`2Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?MuSD4Mh?qGc%5o&s*t~>
+h>[NHb(7.s\cKP)JcE.XJ,~>
+g])iuo_*k9[/YX~>
+hZ!r-Mh?q?Mh?q?Mi3%:Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?MhD%f#(qhdMh@hnJcE4ZJ,~>
+hZ!W5^4Eld\cKtEJcE4ZJ,~>
+h#@EKs8M]os7Z0drq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq?Blrq6Bmp4<7Os*t~>
+q>UNQ[&!)I"-iNZ]n(h)K*.&"s3:P$!/#i\bDQImUs8W.s*t~>
+q>Vc+d`T;<]"Yni^:M%i^:M%i^:M%i^:M2Ts44ci]!f2Y]!f2Y[XPfr]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y])T2H]!f2Y]!f?H
+s5LW$J%iM.]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi\i[X;^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M>,iqE0IJ,~>
+pAYj#s7ZKmpAajdpAajdpAajdpAaj[rr7QCme6Y[rUta@pAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAahFs7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKdpA]X~>
+qu7W'Uk=SXMh?q?K8YA?K8YA?K8YA?K8YA?ec4KWKC+9mSH&V=P`(0PK8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?5(ecGMh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?r,rr2u3rVqB~>
+qu6]fb3QVL^?5I\]!f2Y]!f2Y]!f2]I^Zhr]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Ys1/ZJ]!f2Y]!fWYs1Z(U^4El:\cKP%rr2uP
+rVqB~>
+q>]aRrr<#l!<<&l!<<&l"98)gs8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8DWks8M]ms7ZHlrq6?lJbI.Xq#>j~>
+r;Rb]Mh?q?Mh?q?Mi34GK8YA?K8YA?K8YA?MuWg8JU?a1"jR(lH\6s#Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?5Dt/PK8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?V"XigPlC]5~>
+r;QfS^?W9?^An5IZF7'IZF7'IZF7'EI^ZPjZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'Is0<*BZF7'IZF7'us5(&m[Xl$0\cg1Ls8Tt8
+s*t~>
+qYpTis8M]os7Z0drq6?lrq6?lrq6?lrq?BlJbJF'rr3)gp@eOcp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lpAY'lpAY)B~>
+rVlr4K7!QL"+,[%hZ!3Lc(t>k!.4Wr"FIi^eT:_:!-A-d!-A$a!-A-d!-A-d!-A-d!HWVc!!@Rh
+H[GYj!-A-d"ESp:s8W(Fs8W+Grr3"GF8l1>F8gLdF8gLdF8gLdF8gLdF8gOds8REGF8gLdF8gLd
+F8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8^FcF8gLiF*iiFk'R&Z!.4]t
+!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t
+!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t!.4]t
+&:9&SpAajdpAajdpAajdp<ESh'RPIbc1_22s7ZKds7ZKds7X]iK7!TM%aF_IpAajdpAajdpAaj2
+rdtE5pAb.bs8RT~>
+rVm5U]!f2Y[^roYcKbE&%c5LB[^roY[^roY[atK@jKe[`rNc>$qQg/$rj)S(s0DY(s0DY(mBZcl
+`3Om,s73>$]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f1@[^roY[^t>hqY'dZqY'dZqY'dZhR^/,[^rp(pA4LZpA4LZpA4LZp>3Bh[^roY
+hY-g>qY'dZqY'dZqY&dW[^s'Ds8SAas*t~>
+r;ZTdqZ$<`rr;'QquH]hquHTes8W)ls8W,mrr<#lrr;BZs8U"1s8N)eJbK-;o)JU\o)JU\o)J[^
+rr3&fs8RT~>
+rr3GXK6r5tK7eNHc0kW*mf)>W`M@j5H\6ZtH\9TCUucXt!;ulq!;uis!;gj;rrrIEs8N'!F8l1?
+!-A/>!!)S2s8W+?s8N'!`,btIs8I@pK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5t
+K6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5t
+K6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5tK6r5t"m5jYs7Z0bmel2TH\6ZtH\:J\pAaj[rU0UG
+$[[MYH\6\-s7ZKdpAOFWjp?BeH\7R_s1LGmJ,~>
+rr2u\qR-RIhX:72mf)JPg;`rs*od4BZECL9ZECL9ZECL9Y-P49Y-P49Y-P49Y-P49nGj'%ZECL9
+ZN'q)ZN'q)!3Z>$!<BG)s&T3'ZECL9ZECL9ZECL9ZEF6-ZEF6-!3WW1ZECL9ZECL9ZECL9ZECL9
+ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9Y-P49Y-P49Y-RWuZEf%i&%:cspAb!_o()5:
+lK[NslMJ""lLsrOqY'LNmdBB*k3D7/[LVTrpAb!_o()5:lK[NslM\-p_Z0YeM>r)~>
+rVuWc!<<#k!:KUTs8W&k!:Kj[!:Kj["7GmVmf)n[mf)n[mf)n\me6/Ns7QH\rq?Bl"p"Asrr<&e
+rr3!!pAY'o!;?-Srq6?[rq6?[rq6Wcs8Vf\s8N)erq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rUp6Zrq6?[rq?Bl!VYr4pAajarrMinrUp<\p?qeNr;Qfks8DWm
+me6)FpAFpkpAb*b!q,dMr:^-i!TsE4~>
+rr2tVqg/aAhWFP3s7YmCk2+XQqKiD>s+>B6CAr8SCAr8VC3+H2rc8'Src8'Src80VF)q?QrrN1A
+CAr8\CB+;6s8N'!C30CS!<@3?rrN1ACAr8SCAr8SCAr8[C30FT!-A2?!<.$>CAr8SCAr8SCAr8S
+CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAi2RCAr8SCAr8WC=W?KF+JZ@He%9HpAFsj
+pAX1TeT:Y8"4cQ%pAFsjpAX1TeT:Y8"4cQ%pAFsjpAX1TeT:\9"O6uH3WFU~>
+rr4"QZF7'IZEh@(lLt8Xo'Yf.inhPX[^*?I[^,W,]&g*p!<<)p!<<*!!;ir!rrrK'rr<&%Y5\G%
+!3Z>$!!)Sms8N3%Y5eM%`3+UPs2(eEZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7%F[^*?I[bg<;pAb*f&GG\[lK6s/ZF7'IZJOm7pAb*f
+"nqNPlK6t&Z3RhD[bg<;pAb*f&,,SZlK6s/ZF7'IirB%8s*t~>
+rr;ff!Uf[[s8M`lmeQSUs5itS!<<)p!<<*!!;lKirrrK'rr<&mpAY'm!;?El!!)T`s8N3%pAb-m
+`:j31!9Sk+!qu'Uq#CBfrpK^X!Uf[Vs8VflmelbZme6GUs7ZH[rV$6j!TsE4~>
+s8N,MF8gLjF*i88hX9h2rsA,UhWE@iHZOOTrd4\FjD"bss'f1-rrZ_6rrDq2rVultrbDH4!<?m6
+rrE+7r;Ze3s8W+6qu6Y2r;XcO"MOi*F*%>-!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d
+!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d!-A-d"`qB>k3hs@rrDKdjoN/)rd+ijHbJS(me6SY
+!:KjK$b^"rHZOO\^#nJFpAFpjmf)>U]jc>0H[C\Ns/\52~>
+s8N)]qQ^4ChX9t6q??<Pk3Cg?qQg/$+KDTEY,\Y)Y,\Y)Y,\M)WiiA)WiiA)WiiA)Wic=%?!7"'
+$!g[6!333%Y,\Z's8N'#WiiB$rrE,&rr3!!Wr2l#WilC%Wil7!!35ts5H:ldY,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\M)WiiA)WiiA)f)NadY(<khb3J9[qZ$El
+qYKdJk2sg[r3?jUlK[g6s8)clqXWq6k/sCqZ4G+ClL+NKqZ$Ego'5B"b+\d>"MXp9c@LK~>
+rr;ig"6T%FpAY*lp&jaVk2uO6s8W,m*q&aip?qYBp?qYBme6)Bme6)Bme6)Bme6)B!!$J3q>Ub1
+=o\Qjp?qYBpAP$k!!;T^mf*4e!;?El!<DQcrrqias8VN\qu6Zar;T"Lp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBme6)Bme6)Bme6\\p?(dop&NYBpA=mip&jaV
+hVS2(!7h)Bqu?]i"7Gm>hYd'Iec,:>s8Vcpme5MorV$3i!7cT~>
+s8N(pqf;mm^#nJNrVm&hhVRD.KDT`irrHkDrb;FBrb;FBqe?+?rb;FBrb;FBrb;XHC&n;6>$Cn)
+s'#I&!<?U.C'%jZCAn/5!+PqBrVlk,rr3*$CB+;6rr3@8s8N(.s8N*!rr<&rs8Qg6@fC*B@fC*B
+@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@fC*B@f:$A@fC*H@VTYBs35;0Erg?`roO4S
+r;QrohWEt%@f19IXT%>ipAb-m!<;cLk2raSr,Vk>roX4\rVults5j?`@f19Lmf2u0J,~>
+s8N)AqlUC6`ocRWqZ$Ecmc*6k`qlk<s5U-Z!!<1'=oJC#=T\U'!;`_orr<&tWr;qtWrE#$!36)!
+!<3!+WrN)!WrN)!s8N'!qu=^:"2b)tSUmpEY.FVp$hjGsqZ$E_io]C7Q2Icb])Lh"pA4dh!;c9G
+k2s7?r2p%2roX4\$30l%q>^NXk.6iUXonCtp1]$~>
+s8W&k#4D3Ymb[[2r;QromdBf*k5=oSmf3=IpAY*os&rV)s8Q7(rr<&qpAP!k!<)WirrDclrr`>q
+s8N)ursSQ#rrDcmrrE*!!!)ora7fN4!8d_K!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj["n)*7p@dqNrseDim`j;Up?qYJeb8_)rr;uu
+s8N;kp?p2Up?qqR"kE>?mJm7cs8N'$p?p2UrUp6Zrr2u"J,~>
+s8NX_C3+-2C3,$PhWF8+pAaj[rn[t#HYRV:F)#drs5RPg!<)p"@Tm5ErVlitqI9L)!W`9#rF5g,
++9;HA@fQH.s8N'!@fQH.s8N(.s8N*!rr?O.rr<'!rrC,LJ#r[?@VTt!F)#c2F)#c2F)#c2F)#c2
+F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2
+F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F)#c2F!#.<C3+-Jk1/>Vs7ZKd
+s6eaok)3DaC3+-2MrrRHmf34c%dr3(k)3DaF)#c2MrrRHrW!!!pAP%#e`McnF)#c2F3Xab0n9~>
+%KH:9WiiA)Wii2Lk2u76q@<5iio9+GTrP8qY,\Z)s5TsT!<<'&?!1H9s8W&uqPF5l!W`9#rMBPo
++9;HAV>pPqs8N'!V>pPqs8N(qs8N*!rrAnqrr<'!rrC-:J("A6RAI'dY,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Xrj[HWii@qk1\hcqY'dZ
+qXWY"k+Rp?WiiA)U#t(go(r:b%eAW5k+Rp?Y,\Y)U#t(grVuuqpAP%#g?,)kY,\Y)Y2]K]@=S~>
+rr;lh"O6)sp@eFarpBgDc2757ruLP$me6)Bme6)Bme6):p?qYBp?qYBp?qYBp?qYBrW)uu"_(YE
+>6"X%!-%Z"p?qYBpAb-ms8Vf\p?qt\!<<)es8N*!rr<&es8N*!rrDcmrrE*!!:Kme!!*'!!:KRK
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBme6)Bme6)Bme6ASp=8S^
+p&r)&k3hs@rrr,ak4ZL=r:U<-p?(f:s8;p$p?q):^"*&S"24Ejmf!4ds8E!#k4ZL=r:^-i!2P,~>
+s7ZJ-!+PqB"(HW6k4ep+k1+ff@VT@eCB+<C>%1ZE>%1ZE>%1ZE@Tm5E@Tm5E@Tm5E@Tm5E@Tid+
+s)S0L>%1ZE>%1\8rr?7&s'f/@s8N*!rrE*!!<<'!>%7O3!<<'!>6"U&s8N(.s8N(.s8N(.>%1ZE
+>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1rE@Tm5E@Tm5E^&O!oC1@0W
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB!+PqB
+!+PqB#(,4WeaE/2rq6Qae^`N'>%7JG"_)i8e^a*b!<:RXhKrF8C2.3mHf!<'me["aeHOfV>%25U
+rbDK5!%EE~>
+!VZBdWWJIFk4eoYk1Z)or2Tes*i5R,Tr"HZTr"HZTr"TZV4j`ZV4j`ZV4j`ZV4j`Zr;cfrr;^i6
+Tr"HZTr"I_rrAbms.uEcs8N*!rrE*!!<<'!Tr%eh!<<'!U&Y,ms8N(qs8N(qs8N(qTr"HZTr"HZ
+Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"TZV4j`ZV4j`Zf)NILV1GWLQ/^NS
+melb^mbZ[WQ')!E"I8!#hX:7@"Q%klQ')!E"I8!#hX:7@"Q%klQ'(sDs8N(-J,~>
+s8NDnp?qYBp?o<Up@nUpp?''Vme6)Bmf3=dp&OO[p&OO[p&jaVp?qqR!:Kj[!:Kj[!:Kj[!:Kdc
+rVufrrq6?[rq7o2s8N)es8Vf\pAb-ms8N*!rrE*!!;?-drrE*!!;?Hm!<<'!pAb-mpAb-mrq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rUp6Zrq6?[rq6Qas8VfCmd>Su
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme4$emeZt_mK^,Lme6)Bm^2u]!<;orrpC#ueaDl!me4$emK!:a!<2Bn[+4U<me6)Bs8SU>~>
+%/0+(@VT@e@VTB7hVS)/rn[oi>&%M]@VYrCiE?3]q>UEppfd^t'*)3>s8Q8+s8N*!rrE*!!*]F&
+>5nO(!<<'!rr3?+s8N(&s8N(&s8N)?=p1r,PZh7>C1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:rX@MdnGe`QSnp?qY:e]lr[;JKZU
+@VTB/c.2Ui%aEj>;JKrUC1:Z/c.1tMr;[>ie]lr[;JKZU@VTBPs!`H~>
+s7Qf"V5gAlV5f73injM3/)K:JKpes;Whl`qs.,jSTq.mJTq.mJTq.aJSY;UJSY;UJSY;UJSY;UJ
+SbE+*Tq.mJTq.mJU&Y,mTq25`Tq25`!<<'!s8N(is8SelrrW9$rrE&u3ro<\!1j/i!1j/i!1fgS
+Tq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJTq.mJSU[?(Tq.mJTq.n&s2'nh
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhh&BV5gAl
+V5gAlV5gAlV1mp[g?S8"p@@e>g=G8;NN/hTV5f7/f%Tp"%bBWnNN0"TWhkF/f%TE[r;[>mg=G8;
+NN/hTV5gBlqI+m~>
+s8Vrh!2TV^q>gN_!MnlUpAb.7me6)Bme6)Bme6)BmdBf:p?qYBp?qYBp?qYBp?qYBpAc9.me6)B
+me6)Bs8N)mmf3=\mf3:es8N*!rrDKes7ZHl!s&B$!<3!i!<<'!mf3:emf3:eme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6):p?qYBp?qYBp@eO[e`MGV&#AXUme6\S
+s7ZKdmcNr5ebo+CV!dC5q#CNZm\JD2p'%8[k3hsCr;[#pmcNr5ebf(?rrAjF~>
+%Hd(^@Tm5E@Tlslk1/Vl!&*cjk06e->%1ZE>6"V3;Hct%;Hct%;Hct%>#JO%>#JO%>#JO%>#JO%
+>#JO%!!)utrr=$B;Hct%;Hct%;ZHas;Hj,#!*]F&!<<'!s8N(&r;Zcs!*]=#!!*#u2d67]!*]F&
+!*W9(;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%;Hct%>(9FR;Hct%;Hcu3
+s*IXQ>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE
+>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%1ZE>%/g^
+@Tm5E@Tm5E@Tm5E@TqX=eaDl!me6):e^`M[;HdO5@Tlsle^aHq%b9E>;Hd75>%1[le^a*Ur;[>q
+e^`M[;HdO5@Tm7/p*kL~>
+s7-PkV4j`ZV4i=ok2,D$!%mWqk14g?Tr"HZU&Y.hSY;UJSY;UJSY;UJTq.mJTq.mJTq.mJTq.mJ
+Tq.mJq#DD.SY;UJSY;UJScA]iSY?)`!29Gm!<<'!s8N(mr;Zcs!29>j!!*#u7\Tk^!29Gm!25sW
+SY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJSY;UJTq.mJTq.mJTq0p;[ZR8W
+J#/j8Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZ
+Tr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZTr"HZ
+Tr"HZTr"HZI0AQ`g?S,*ndk0Rg=kP7NM32BV4i=sg=l?&%bfojNM3&BTr!1sg=ki[r;[>mg=kP7
+NM32BV4jaZp0iI~>
+s8NJpp?qYBp?o$Mp?))H!%mp4p?&1-me6)Bmf3=\me6)Bme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+p?qYBq#DE.me6)Bme6)Bmf3:eme6\\!;?Hm!<<'!s8N)mr;Zcs!;??j!!*#u7eZl^!;?Hm!;>jS
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bp?qYBp?qYBp?qt\p=8U!
+J+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)BU_iI]k4\NKpAaj[k3hZ5eaE/!p?naEk2uI>s6^;keaDl!me3IEk2uC2r;[?$k3hZ5
+eaE/!p?qYSs."T~>
+s5j;jr`TS:>$=P"hUU0ErW!/jk2+sr5t_)Z"(L-eF8f&;9)_]g9)_]j8lAPZr_`_gr_`_gr_`_g
+r_`_gr_i[p!)!5g!)!5g!)!5g'1r6);G'ge!(p,h!(m4k;?-\p;Z$Oo;Z$Lp;Z6Y$;?-\h;?-\h
+r_`_gr_`_gr_`_gr_`_gr_`_gr_`_gr_`_gr_`_gr_`_gr_`_gr_`_grDEVfr_`_gr_a!Gs&r;u
+>$>D7=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=pAG>60?GBk5=WXk1.`=5tY<a@Tlr$k0;H=r9agPe]m5B8m5^'=p..Rc.1tR!!Lisk!;W<
+=p/;<md;f[~>
+s6f`W"b",EhVRPs!!`#Zio[shNVoIqlMn/\R@Tb:R@Tb:R@Tb6SXH%:SXH%:SXH%:SXH%:SXH%:
+Sc&O1R@Tb:R@Tb:R@Tb:R/d5XR@O<XR@O<XR/d5X!!&FXqu?ehR@X6U!1j)h7%F;XR@O<XR@Tb:
+R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb:R@Tb6SXH%:SXH%:S`9[CNL>?k%
+rLI_hWjOso'Yr2hV.+/NVoI\D<BR/lL+*2mdBAsg?*73r1O71k1\\WqZ$cUg?*73qk4)bnmR%~>
+s8W)l!:Kj[!OUDVmJut[!!`JsmdAVihZ!3Rme6\\p?qABrpBd[rpBm^mdBfJmJut[mJut[mJut[
+mJut[mJutZ!<2BdpAXI[pAXIop?hn\p?q>K!:K7T!:Bgep&G*\pA=pjmJutY!!)Hd!!_ik!:K7T
+!<2BdpAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAOCZpAXI[pAXIbpAb0\
+e`QSnrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq7&op@aa=k3hsCpAajdp?q)2Ph#Kqrq6kemcNs2s7ZKds7YmCmZc9#p''lKmcNs2qZ$ce
+k3eJarq6N`p@eOdUjr~>
+s5"&[>#JO%>#It-k5O3YmJutKmcNYH0iCnQ;Hcu*s/\gj8lA8Z8lA8Z8lAQ98lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA:];@H/q
+8lA8Z8lARes%5n5>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%>#JO%
+>#JO%>#JO%>#JO%>#JO%>#JO%"BmhBhUVE%s5")C8lAhj>#IB;hUVE%s5")C8lAPj;Hc*;hUVT*
+s6fjds5")C8lAhj>#JPdjsbf~>
+s6BHOs+q3Iinihc!;?!Ok2qY7NVo=Kf)O$HRHp7DScA_<NIdW'SRpg?hY@0OiW3VIr1*q$io8hj
+!<;$ZAVp>U"(gKOhYmKUmdg>Ws5F&jM>NkDmJp[G~>
+s8NDnp?qYBp?pJ4pAXIirrE)mp?qXUPhtj%me6)Jrs\>hme6)Bme6)Bme6@'me6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Kp($Na
+me6)Bme6)Ks2EOVmXOrup?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp6>REq#LH_#F*d,p?qYBPlC+H!<;HlPh#3ip?qX=rpKac!VZQm
+!<;HoPh#3qme6)Bs8SU>~>
+!T)B&;@Y^Ok2+tWmdBf2k05>89)MQiHiN5#62jIV62jIY5tXa8r^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr_!2Vr^m/Vr^m>[MuUIN
+8qBk@;CVV%q#CNRjs`Uo;?/0FhY@-RhW?7Qr)*MDrndYTrpC!a!!(m<.7*i/!p8>gJ,~>
+!UAhCSITM:k2PC_mdfr:lIK*TOo1a\[f>c`Q'mo*Q'mo*Q'mo&I[QIhQ'mo*Q'mo*Q'mo*Q'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*
+Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*Q'mo*s-4%]Q'mo*Q'moO
+s4VaXR=Un2<T`<#q#LHW!EG!SSHDmSio9b6s5j>^M>WnJ<T`<#!!*#d#4_`ok2o[#qjdfVl=#2~>
+s8NE!me6)Bme6@U`Vo6)p(.2sp?%:7hY-C2me6ASs7ZH[!;?E[!;?<X!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?BZ!;?E["SV9W
+s8RSUhX:+*p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qVVme6($rpKR^s6^,Ec1^T!me2;4meHk_mK\Bhp@dqJmXtN,rr<]*s7ZHm!:K9-
+c1^T!me6)Ks.k/~>
+/^;g<;G'hZ;G'PI0pLhWk2uC2mZ]FK3D)nA8lA8Zec1P"5tXF85tXF85tXau5tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXHC8q0-!
+5tXF85t^;>C-bHi8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8l?<p;G'hZ;G'hZ;G'hZ;BXiYhWEu!mL]*[k2mdP8lA8Z8g*!QhWEu!mL]*[k2mdP8kMuR
+;BXiYhWEu!mLJsYk2mdP8lA8Z8lF3r.=_~>
+!TN8;R1=pVWoiI/lLsr>Wa/GHOo(OJk5W/HQ0jh?RI:*TI>rfG&=H5Ok2tsomdBZ:p?q5.9SND4%
+nu!Fk3D7"mdfrBmcrq.L&@>L9]G3slK[g*o()MBlK1coqjIKH!+CB~>
+s8W)d!;?BZ%b6KVp?qYJs8Vf3MhA_*rpCBlme6\\p@dqJme6)Bme6)Bp3uH'me6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bmf2tkme6)B
+me6)Bs8Vf3hX9h*rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpC!amd>_qp?qnQrr<#l"R^oeme6YJ",$%8meukYs8VcomXrd_mKE69me6)I
+pAY*lp&aZ7c2R,7p?qAKs."T~>
+s3:=2$ooG.PeH4uUfnTP0gYY.%[@"e;F*</3C,Yk3C,YcIR,t[3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yks#CNS3C,Yk3C0J@ZnXR5
+6%MW/&E`uKrT=.J"SV9O&4-4d!>+DmhYlU:mKE7OmLV\^8c]LcrndV9s6^$`md:WPqapq?bqX_~>
+,3%IIQ'mo*Q'n&*I8G'_b3%-XI7-b?KpA'kR?a2*^An&#JW]A_J'.fBD1Rh7R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R1#:JQ'mo*Psjco
+k2uX-&FT,_md`bsR?a2*R7-2sk2uX-&FT,_md`bsR@0>.Psjcok2uX-&+9#^md`bsR?a2*R?cpo
+@=S~>
+s8O27me6)Bme6ABc&8+2hY-*VS9'=QhX:+*p?qYBpAb/Dmd9FlpAaifc0"Hfme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B#O_<Rp?qYBF8bM-
+p?qnQ$NKi"F3XFHp?qWqrU'^[meuhds7ZJ6c1^l!p?m##mK*%LrUp^#pA]3Yp?qYBp?qt\Ujr~>
+s2>")9)_*V9)LsU+;"MX#S7h%.60[d5t_,B"\M)"s5lrQ5l`qE5m',55rnp1!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1!D!'1$E#rt;0
+s8PAF5s\-B5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV
+5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV5laOV
+5laOV5laOV5laOV5ljS#oEYF.rBUKW5p5e*!"f,q"%kjF+S5pA&4&TSr]pWY`Q]i^~>
+%bfd%Q'%>oQ'%2oNIb5#r]CcX6rdfLNKoWkOd2&oQ/;Q/R=ULiOTN,os*p/RM34'cQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ&u68Od2&o
+?1^5a7"LJcOd2&7oK3@HJWZ([Od05E4:4K-Od2&oOd4e_@=S~>
+s8Vi]!nEffrc86XF,Qj=k54QIp?qq[!Uf[\mJut[mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?BZ!;?E[s7ZKm"R`t[me25"
+!2T7.!IN)hmJs'TErgX4r9aQ\oQ(%[c26r/rrAR>~>
+!QDbG5liu#r$_Y$3VPfK9%Et(>!Y/73C,Yk3B;OS3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C3[*$UHd=3C0J@s&q-;3IsKq5litp
+p)jAb3Vu)C3@XYE!@^&+5litpp)jAb3Vu,B`;h?;~>
+s4RpIOd2&oOd22oQ&UK?C&VBMBm#,hQ'%>oQ'%>oOd5)/m\,2ko8O'=b5_L8D1RP+OaiXYQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>oQ'%>o
+Q'"CuJSA+e<EW=)<EW=)<G@#LOd2&oQ%<XL=]JU)=]JU)=]K0eQ'IJsOd1K3<EW=)<EW=)<EW=9
+JX)@_Od2'cg0oL~>
+s8O&3me6)Bme6ABp?peNXIPNFXM*KYp?qYBp?qYRmf*7dmK_nBk3hC"k2q-\k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3i93%IWBH
+k3hsCs7WPEk3hYep?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYB6MAs2Mj0-aMj0-aMj0.$eb8G)me6A)XG`=$P`(caP`(caXO[%<
+me6)BeZ=[nMj0-aMj0-aMlbJ&me6)Bmf3<_J,~>
+*ONL?5rh4k5rgqk3C,Yc0f^sK0f_6[3C,Yk3C,\)5n$ZAs8TH03C,Yk3C,r[3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,\*5mfV<
+6%e>"s&pj33W;<o3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk69.=d3AENK3AENK3AENK5rh4k5rgqk0f^sK0f^sK0f^sK0gRf[
+5rh4k5qtAS3AENK3AENK3AEf[5rh4k6+sr\J,~>
+s4/-KOc>K_Oc>?_NKK3[JUr6#JW5YONKK3_NKK5"OTh04s8UN@JW9D`#a)R`s8Sd,I>.Z_IuTSM
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_OoLCQJUMflH$ssdH$ssdJW5YONKO4"%"WhPI<g6dI<g6dI=_BW)j-,BNK&L;H$ssdH$ssd
+H$t7'NKK3_NKMfG@=S~>
+!VZQdmK)J,rm_&+k4n?EpAXLYrrDcljob&6k3i62!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjKs6fpL!Uf[\rr_trc/+$>r9aR8p<<Tf
+q<e75p<<Tfq<e75p<<TfqX4C`!1\Q~>
+s0O:B3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh4k5rh4kXS2\om]<LBMh?Y3Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?!gL(2
+rr3203@Q[;3B;RT3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yn5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rl<Z0n9~>
+*S/Z$NKK3_NKK3_NKK3_Oc>K_Oc>K_Oc>K_Oc>M%N<b<cqZ$TdcH_!PrON?Qdbaj#s43$@H%GpR
+J!#_QNKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NC&beOc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc@r?@=S~>
+s8W)d!9X:K!9X:K"6T%>k5OcKk5OcKk5OcQk3hC"k3hC0rrMinJbK$8r;R,thQ4]Hk2u*omcON:
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K"m57@s8SmF~>
+s/Z5]62ikE62ikE62NYB62ikE62ikE62ikM5rh4k5ri,MhLY_#rsHGS0ek[K5rh4k62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikH6*..:J,~>
+s3;R?NJWXONJWXONJWXOM2d@OM2d@OM2d@OM2dAiN<>$*cK]u\pAYBKV.FLlJVf6_NIQeEM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2aiYNJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWY?dU@Y~>
+!VZQRjoFiKjoOoDJcGBB"R`@uc.2dT!:GF#_<(gms."T~>
+*NZ&&3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh713<2AD3<M!.F*iJ.rL=(EC.^300erVe!($TE
+ImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C6"l5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rl$B.=_~>
+.F-(qM2d@OM2d@OM2d@ONJWXONJWXONJWXONJWXONJWXONJWLCQ*.Fl`dbkF_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_Suu#[]5U4
+BlS9HKo(Y9NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXO7ZE7aM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM9a7PJ,~>
+!WVlTjoF9;jp0c*hVQfFmd>Z"rV$9Z$Kf%']uAOPk2,7WJ`a`0!rqtiJ,~>
+-Cgkd3AENK3AENK3AENK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKpb;atr\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%pb@7Y0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^s[
+3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK3AENK
+3AENK3AENK3AEOaUa^f~>
+.`TVVI<g6dI<g6dI<g6dH$ssdH$ssdH$ssdH$ssdH$ssdH$ss`F`h\Drb[*uD/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/'#e#&.pk
+EH-8LIslTjH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$ssdH$ssdH$ssdGtEF0I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6dI<g6d
+I<g6dI<g6dI<g6dI<g6dI<g6dI<g6dIE'E<J,~>
+*VTNPc,IrHc,IrHc,IrH`QcBH`QcBH`QcBH`QcBublu)2`PoO(rj7-U[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&j24s1SHOqTXN/
+c,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrH
+c,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrHc,IrH
+c,IrHc,Ipo`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBHpA^Y5~>
+!i2>HJ`_OGM<4r[3LlloJ,~>
+!m8N2J_kt7M;ABTIE'E<J,~>
+!rqu=J^o>%M:DaBc1_1-J,~>
+!h?&@J`_OGM<4r[0r1<gJ,~>
+!liB.J_kt7M;ABTH-4-8J,~>
+!quZ5J^o>%M:DaB`W,Y-J,~>
+!i2>HJ`_OGM<4r[3LlloJ,~>
+"3SW3idos;hMU.m`dPkL@=S~>
+"98)>hLX4.eV_l[^!69NS:C~>
+#+VJDk3hC"roO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4K
+roO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"I
+roO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4K
+r8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8rLsk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3h@BmcNs"mcNs"mcNrV0r1<g
+J,~>
+J&]WVhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhLFPAini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oinf1EhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhVuP#b/Rk?~>
+J+io]e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5eUQH+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUR,4e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\!Ys7W7=~>
+"/MGImf)?umcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"C@:6Pk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"roO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4K
+roO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4K
+roO4KroO@&3LlloJ,~>
+"Nn`4inf7GPi@2Lini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oini\OiniZ(hW!DOhW!DOhSsu`b$ff~>
+#64DAhUUK5rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*
+rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(
+rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*
+r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8)qRhUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUHne_\j5e_\j5e_\iic1_1-
+J,~>
+J"3;hk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k'ug]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcK#ek3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3g2CUmrla~>
+"NJT0ioYgOPi@2Tio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]50k2PO_k2PO_k/M\h`aOA~>
+!quZ5qq_>'rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*
+rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*
+rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(
+rn[Y*rn[Y*rn[Y*r8%G(rn[Y*rn[Y*rn[Y*r8%G(J_p+W"MMeSp8!3~>
+"JhPJmcK)gPjX%`mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNpHk3hC"k3hC"k/B?NUa^f~>
+"Nn`4k2LsSPidJTk2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PM4io]7_io]7_il6Ddb$ff~>
+!rqu=J_lLF!7h)*!7h)*!7h#(!7h)*!7h)*!7h)*!7h#(!7h)*!7h)*!7h)*!7h#(!7h)*!7h)*
+!7h)*!7h#(!7h)*!7h)*!7h)*!7h#(!7h)*!7h)*!7h)*!7h#(!7h)*!7h)*!7h)*!7h#(!7h)*
+!7h)*!7h)*"kC<2pA^Y5~>
+!h?&@q!S"Z"RZ9XmJu\CqZ-N]!s%cW!:oRU!<;He!9!;C!:]CV!:0(N!:oOX!9*>G!<)<c!;Ps^
+!.jS'mKCK`Umrla~>
+!liB.pu_GR"Qf^HjoFi3qZ-NU!s%KG!:o:M!<;0]!9!#;!:]+N!:/eF!:o7P!9*&?!<)$[!;P[V
+!.j:tjoi\Lb/Rk?~>
+!quZ5ptklJ"Ps.8h>m!#qZ-NM!s%37!:o"E!<:mU!8u`3!:\hF!:/M>!:ntH!9)c7!<(aS!;PCN
+!:enGk5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;
+k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;k5O3;k5='9k5O3;k5O3;
+k5O3@k.Sb6p8!3~>
+"/MGIpAXI[pAXI_p&OOKpAXIap?qVSmdBfJmJut[mJut[mKWCQp?q>KpAXI[pAXIap?q>Kp?qYR
+mJut[mJut[mJut[mKrs^p?hn\p&OOKpAXI[pAXI]p?qYRmJut[mJut[mJut[mL&[Up?q>Kp?q>K
+!<2BdpAXI]p?qYRmKE7OmJut[mJut[mK3+MpAXI[pAXI_p?q>KpAXI]p?qYRmJut[mJut[mJut[
+mK3+MpAXI[pAXI[pAXI[pAXI]p?qYRmJut[mKE7OmJut[mK*CVpAXI[pAXI[!<2BdpAXI]p?qX*
+me#oM`AsHa.=_~>
+"3SW3lMfpblK7Bol2^,3lK7BolK7@3lK7BolK7BolK7BolK7BolK7@3lK7BolK7BolK7@3lK7Bo
+lK7BolK7BolK7BolK/*/lK/'Hl2^,3lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7@3lK7@3
+!-dSjk3D*ok3D*ok3D*ok3;s3k3D*ok3D*ok3D*ok3D*ok3D*o!:&_3k3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3;s3k3D(/k3D*ok3D*ojoFQ/k3D*ok3D*o
+k3@N[p>uLtIE'E<J,~>
+"98)>k5O4Vk2,7WjoFQ#k2,7Wk2,5#k2,7Wk2,7Wk2,7Wk2,7Wk2,5#k2,7Wk2,7Wk2,5#k2,7W
+k2,7Wk2,7Wk2,7Wk2$*pk2$(<joFQ#k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,5#k2,5#
+!-d;^hWE\WhWE\WhWE\WhW=h#hWE\WhWE\WhWE\WhWE\WhWE\W!9W/#hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhW=h#hWEYphWE\WhWE\Wh>lEphWE\WhWE\W
+hWBCGp>,qcc1_1-J,~>
+"Iu8Bme6MF!!)f^!!)HT!!)`\!!)rb!!)][!!)uc!W_Wgi9gRFrU'Xcna6AWm-XiRoBl\\md:)3
+mJm7cmJm7^mJm7YmXOrup?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?iC`me6)Bme6)B`A+0Y.=_~>
+J&]WVk3D*ok3D*ojoFQ/k3D*ok3D(/k3D*ok3D*ok3D*ok3D*ok3D(/k3D*ok3D*ok3D(/k3D*o
+joFQ/k3D*ok3D*ok3;s3k3D(/joFQ/k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D(/k3D*o
+!:&_3k3D*ok'u[YlK7BolK/*/lK7BolK7BolK7BolK7BolK7Bo!9WS/lK7BolK7BolK7@3lK/*/
+lK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK/*/lK7@3lK7BolK7Bol2^,3lK7BolK7Bo
+lK7BolK7BolK7BolK7BolK3T]k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3Bs3b/Rk?~>
+J+io]hWE\WhWE\Wh>lEphWE\WhWEYphWE\WhWE\WhWE\WhWE\WhWEYphWE\WhWE\WhWEYphWE\W
+h>lEphWE\WhWE\WhW=h#hWEYph>lEphWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEYphWE\W
+!9W/#hWE\WhLF\Ek2,7Wk2$*pk2,7Wk2,7Wk2,7Wk2,7Wk2,7W!8ckpk2,7Wk2,7Wk2,5#k2$*p
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,5#k2,7Wk2,7WjoFQ#k2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2(UMhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWDMjs7W7=~>
+)5Nc_p?qYBp?qYBp&OgSp?qYB!:KO\p?qYR!#>4qp?qYBp?qYBp?qVSp?qYBp?qYBr;ZrnmJu\S
+!#+eome6)Bme6)BmJu\Kme-YS!;?Bl!VYs\!!2N]rW!#nme6SZ!q,dMrW!Grp?qYBp&OgSp?hqK
+p?qn["7GmNpAP$tp?qVSp?hqKpAFt*me6)Bme6)Bme6)B!!)H\me6)Bmf!1eme6MX"muBYp&Ogc
+!!;l^pAFslme6SZ'^k\_p?qYBp?qYBp&OgSp?hqKp?qn[&+9/Z!:KO\p&G*\p?qYBpAXI[pAXI[
+pAXI[pAXI]p?qYRmJut[mJut[mJut[mK3+MpAXI[pAXI[pAXI[pAXI]p?qYRmJut[mJut[mJut[
+mK3+MpAXI[pAXI[pAXI[pAXI]p?qYRmJut[mJut[mJut[mK3+MpAXI[pAXI[pAXI[pAXI]p?qYR
+mJut[mJut[mKWCQ`AsHa.=_~>
+!m8N2q!%hZqs"7`lKSBKlM^eUl2Uh[lMU__l2^nMrW)ZW!!)u_!s%TdlM^e`lM^e`lM^e_lMU_^
+lM^e\l2Uh_l2Uh`lM^e^lM^e_l3.1Ql2^,7r;cNUrrDo\rW)u`qZ$fb!:&hLlM^e_lMU__lMU_U
+l2Uh_l2Uh`lM^e_l377Rl2^)L!.jG)l3,+T`l__?~>
+"TS2?k2-+"!8d_;!!*#\#2\M)!8ci<roX1[!Tr8<joF9;jp'])hW=h#hYuX=hWEu!!!DB?!8d\T
+!8d_;!8d_;$f:%.!8ckpjoFNDk5GA\k5GA\k5GA[k5>8]hWEu"!<;0ihWE\W!9W/#joF9#k5GA\
+joO?$rW!5dhW=h#h>l^#r;ZoUk2-+"!8d_;"Q&8@!8d_;!oE(rrVuuUk5,,^h>l^#!9X7\!p8A%
+r;cl[r;ZoUk2-+"!8d_;$JsnFk2,7_!8ckprW!Gbk2l[#joFND!9WG#k2-+"J)9>Ek2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wjpg20
+hWE\WhWE\.c1_1-J,~>
+I[m2gme6)Bme6)BmJu\Kme6)B!;>g\me-YSmJm7\me6)Bme6)Bme6&Kme6)Bme6&K!;>g\me-YS
+mJu\Kme6)Bme6)Bme-YSme-V\mJm7\mJu\K!!)H\me6)B!;>g\me6)BmJu\K!!)H\me6&Kme6&K
+me6&Kme-V\+7Ah&p?hn\p?hqK!:KRK!:KRKp?qYBp?qYBp?qYBpAP%dp?qYB!:KO\!:KO\p?hqK
+p&OgS!!)`\!:KO\!:KO\p?hqKp?qYBp?qYBp?qYBp?hqKp?qVSp?hqKp&G*\p&OgS!!)]m!:KRK
+p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[
+rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[
+!:Kj[!q,dMrq6?[rq6?[rq6Qap;Jb^S1/s~>
+"NJT0lL+N6!!)o]$39AV!:&hLlKS?Lp$)MWqWe(\s69dglKSB7l2^MB!!*#`rr<Aj!!)<L!:&hL
+!;l$`!:&hLr9=CblKS?Lr9=7^rosI`rot$plKS?LlKSB7l2UhLl2^)LrosI`n`p)RrTYF(lKS?L
+lKSB7l2^,7!:&hL!:&hLlKS?LlKSB7l2^D?!!)u_&HM+]!:&hL!:&hLlKS?Ll2Uh\l@86emcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mck8LlL*s*lL*s*`d,_H@=S~>
+"8;c6hYuX;hYuX?h>l^#hYuXE!9W,<k2l[+jo>D\joF9;jp'])hWEr#hYuXIhWEr#!9WDDhW=h#
+joF9;joF9;joF9;k"5X9hW=e<h>dQ<h>l^#!!)0DhWE\W!9W,<k2tO_joF9#!!(m<hWEr#hWEr#
+hWEr#hW=e<hW=h#jo>DDjoF6<k2tM#k2tO_hYuX;hYuX;hYu[:!%6pck2$+#jo>DDjoFQ+!8ci<
+k2$(<k2l[#jo>D<joFQ#!9WG#k2-+"!8d_;"Q&;'!8d_;'EI:P!9WDD!9WDDk2lXDjo>D<k2([O
+o]?:i`W,Y-J,~>
+"JhPJp?qeNquHcj"p"Aj!;?*drq6<lp%J7_s7QEmrq6Nrp@\L[p&OdZquHcj!!*#l!s&&g!;cBk
+!;?*dr:U*jrq6<lr:^'hrUp3krq6Eop@\Lcp&tHip&Oddrq6<ln+Qb]rq6<lrq6a#p@\L[p&Og[
+!;?*drq6Eop@\Lcp&b<gp&O[WqZ-Zi!!*#l"p"Aj!;?*drq6<lqY#F,p?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qV`me6)Bme6)B
+m_q2VUa^f~>
+$d-J;mcs6*mcs6*med&%mcjf;mJu\?!:'";!:'";mcs6*mcs6*meZu$lL"Z?lL"Z?l2^,;!:K.?
+lL*s*lL*s*lMLW,lL"Z?lL"Z?l2^,;lL*s*l2^,;!:K.?lL"Z?lL"Z?lL*s*r;^-gmcs3?mcs3?
+mcjf;mcjf;mJuYTmcs3?mcs6*mcs6*mcs6*mcs6*mcjcPmcs3?mcs3?mcjf;mJu\?!:&tPmcs3?
+mcjf;mcjf;mJu\?mcs6*mcs6*mcs6*me[!6lL"Z?lL"Z?l2^,;!:K.?!:K.?lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*-0jp`mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcqf?`l__?~>
+!rqu=pu_JSs5jLck2l[+joGDC!!)]SqZ-ZY!!*#\"p!fJ!9WDDp#c/Ps5j:]roO:_k2l[?joYVG
+joG>A!!*#\!!)rZr;cfY!!*#\!s%KG!<2*a!9WDDjoGDC!!)KMrrE&\!!*#\$ioGP!9WDDk2l[+
+joGDC!s%KG!<2*_!9WDDo&ffLs5j:]roOCbk2l[+joGDC!!%T4n`Btfc1_1-J,~>
+!h?&@qt:0\p@\LSrq6Qap&Og[!:K^a!VYs\p&OOYp&sd`p@dqRp($Kjp@dnSp@\L[mJutSmf)n[
+mf)n]me-Y[p($Nap&OOSp&OOS!;>jSpAG!jpAY-mpA4jgp)<?!p@dnS!;>g\p@dnSp@\L[me-YS
+mJm7\mf)q[!<)Tkmf)n[mf)n[mf)n^mJm7\qZ%8sp&OgS!;?*dp@\L[p?hqSp&P*c!!*#lrrE#k
+!:Kj[!:Kj[#OVTcp?qVSpA4grme-YSmJutSmK!4Z!:GF3p@\X.0r1<gJ,~>
+!liB.q!J+^qsFRemd:)CqZ-<W!!)l`!!*#d"p")Z!:K7Tp$Me[qsFFarpBjgmd:)Rmem.bmf*:e
+me["^mJm7dmf*:emJm7dmK3IWmK!7S"9@lX!!)rbrrDQVrr<&eqZ-Za#lsD]!:K7Tmd:)SmK3IW
+mK!7S!!*#drrD]Z!!)uc!<DQb!<;Hh!:K7TrpBadJaW'r"NG`0`aOA~>
+"SVl7k3i*.!!)oY"9@TH!9X.Yp#Z5SqW7bXroOCbk2l[+joG):!!)oY!!*#\!s%KG!<)'Y!<2-\
+!<;3Y!;tsZ!<2-\!<;0]!<2*_!9WDDroO=`k2lXDr9""ZnE0`N!9X.Ys5jUfk2l[+joFQ+!<2*_
+!9WDDroO1\roX4\o]?,RrT4+\k5,/YjoYVGjoGDC!!)lX!:KjK!:KjK!:KjK!q,4=roO4KroO4K
+roO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK
+!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroOIRk2s@rs7W7=~>
+!i2>Hqt:0mp@\Ldrq6^!p&Og[!<;`mpAb-c!<<&l!<;uj"TJJqpAb-c%fZP&pAY-dp&Ogd!;?-d
+rq6?lrq6Enp&P*c%fc7r!<;cd!<;`mpAagdrq6<lrq6Wtp&Ogd!;?-dr:V'/!;?-dp&Ogd!;?-d
+!;?*dpAagdpAY-d!<<&l!rqrorq6?lrq6?lrq6?lrq6Qrp&Og[!<<&l'*%Y*pAY-dp&Og[!;?-d
+!;?*drq6<lrq6Enp&P*c!<<&l!<<&l$NC,"pAagdp@\Ldrq6Zup&Ogd!;?-d!<)Tks+0n;p&r>p
+S>7Ta~>
+"3SW3o)A',o'Z):nc87Ko'Z):!:KCXo'QMGo'Z):o'Z):o'Z):o'Z&Ko'Z):o'Z&Ko'Z&Ko'QMG
+nc87Ko'Z):o'Z):o'QMGo'Z):nc87Knc87K!:KFG!:KFG!:KFGo'QMGnc87Ko'Z):o'Z&Ko'Z):
+!:KCXo'Z&Ko'QMGo'QMGB^u/o!:oRKmdfcGmdff:mdff:mdff:mdff:mJu\G!:oRKmdfcGmd^AK
+mJu\G!:oRK!:oOXmdfcGmdff:mJu\Gmdff:mdff:md^AKmdfcGmd^AKmdff:mJu\G!:oRK!:oRK
+mdbqsp?i('IE'E<J,~>
+J,f5emcNs"mcNs"mJu\;mcNs"!9W\LmcFN3mcNs"mcNs"mcNs"mcNp;mcNs"mcNp;mcNp;mcFN3
+mJu\;mcNs"mcNs"mcFN3mcNs"mJu\;mJu\;!9W_3!9W_3!9W_3mcFN3mJu\;mcNs"mcNp;mcNs"
+!9W\LmcNp;mVh4fk3h@3k3`6;!:K";k3h@3k3hC"k3hC"k3hC"k3hC"joFQ3!:K";k3h@3k3`6;
+joFQ3!:K";!:JtLk3h@3k3hC"joFQ3k3hC"k3hC"k3`6;k3h@3k3`6;k3hC"joFQ3!:K";!:K";
+k3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4K
+roO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK
+!:KjK!q,4=roO4KroO4KroOFQk.T%5s."T~>
+"Iu8BpAb!_!!)oi"p"Aj!;?*dnb)q_qXt6rp@\Idp@\L[p&OdZ!!)oi!!*#l!s&&g!<2Zl!<2Zl
+!;uNm!;?*dq"=[frUpp*p@\L[p&G*dp&Og[!!)`d!;6Bmr:U*jnb2t_s7QEmqt:<rp@\L[p&Og[
+!<2Zs!;?*dp@\Idr:U*jp%A@crUp<np@\L`p'1Tkp&Og[!!)lhJ,f6BpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdp'q&qs7ZKds7ZK3
+0r1<gJ,~>
+"3/K/mf)d+mdff:mJu\Gmdff:!:oOXmd^AKmdff:mdff:mdff:mdfcGmdff:mdfcGmd^>Xmd^AK
+mJu\Gmdff:mdff:md^AKmdff:mJu\GmJu\G!:oRK!:oRK!:oRKmd^AKmJu\Gmdff:mdfcGmdff:
+!:oOXmd^>Xmd^AKmJm6$o'QMG!!)TXo'Z&Ko'Z):o'Z):o'Z):o'Z):!!)TX!:KFGo'Z&Ko'QMG
+nc87K!:KFG!:KCXo'QJXo'Z):nc87Ko'Z):o'Z):o'QMGo'Z&Ko'QMGo'Z):nc87K!:KCX!:KFG
+o'V)"p@8@+H-4-8J,~>
+IeNf\k3hC"k3hC"joFQ3k3hC"!:JtLk3`6;k3hC"k3hC"k3hC"k3h@3k3hC"k3h@3k3`3Lk3`6;
+joFQ3k3hC"k3hC"k3`6;k3hC"joFQ3joFQ3!:K";!:K";!:K";k3`6;joFQ3k3hC"k3h@3k3hC"
+!:JtLk3`3LCZb$bmcFKLmcFN3!!)HLmcNp;mcNs"mcNs"mcNs"mcNs"!!)HL!9W_3mcNp;mcFN3
+mJu\;!9W_3!9W\LmcFKLmcNs"mJu\;mcNs"mcNs"mcFN3mcNp;mcFN3mcNs"mJu\;!9W\L!.X/!
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3`rGmcNs"mcNs"mcNs"mcNrN`W,Y-J,~>
+"/MGIs8M^)s7ZKdrrE)ms7ZKd!;?Ems7ZKk!"8N#pAajdpAajdpAb!i.e`o9!!*$!s7QHdrr<&m
+s7ZKds7ZKds7QHds7ZKdrrE)mrrE)m!;?HdqZ$WrrW!'#pAajb!!N>qs7ZKj!!E8ps7ZEl"8;cg
+s8E!(s7ZHms7QEms8E!,s7ZKds7ZKds7ZKds82j!s7ZKdr;[]7p&G*m!!)]mpAY-mpAY-mpAY*m
+p&OgdrW!]5pAajdpAajdpAajd!<;cmp&OgdpAFsos7QHds8;p&pAajdpAajdrq6?lrq6?lrq6?l
+r:U-jrq6?lrq6?lrq6?lr:U-jrq6?lrq6?lrq6?lr:U-jrq6?lrq6?lrq6?lr:U-jrq6?lrq6?l
+rq6?lr:U-jrq6?lrq6?lrq6?lr:U-jrq6?lrq6?lrq6?lr:U-jrq6?lrq6?lrq6K63LlloJ,~>
+!m8N2q!nCbqsjgho'ue[o)/R]o(rFdo)A[qnc87O!:o[\!;>s`!;l<e!<2Nk!:o[\rpopd!:p*h
+rUTmer:9acrUTpfrUTpfrpg3mo'ub\o)8X]o)&Ldo)/Rgo)A[pnc/[\!:o[\rpg$hrpp'h"7cH_
+o)8X]nc/[gnc/[ho)/RgncAg^o)/Q>o'l2Q`dPkL@=S~>
+#64DAmcNs"rpBpOmJu\;rpC$R!:K7TmcNs9!<;Hek5OcKk5=ZE!<;Hsjo>DL!:K7Tmd:&TmdB6:
+mJuDKmK)GMrU(*VmJu\;mJu\;!:K:;qZ$WarW)rc!9X4[r9jI_rpBdKrVur\rpKacrpBpimd:&T
+mf!4amJuDKmJuDKmed(`mem+nmcFKLmJm7T!9W\LrpBadrpKdd"7?0Omf!4amJuDKmJuDKmJm7d
+mK)GMrpK^b"RbCPmdC#R!9X4IJ*-1]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mLSIJk3hC"k3hC"k.T%5s."T~>
+".Z/ApAY)ApAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdCA.]$s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7QEms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd!;?Hds7ZKd
+s7ZKdrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ul
+rr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ul
+rr2ulrr3,?0r1<gJ,~>
+"NJT0o(IY*`q'-0h=:OGp@<_,o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MV`p@@qJp@@qJp;VC#`aOA~>
+!quZ5qsFIHrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdK
+rpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdK
+rpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBpOmd:&TrpBdKr9aRI
+rpBdKrpBdKrpBdKr9aRIrpBdKrpBpO!:K:;r9aRIJaW7""MMeSp8!3~>
+"JhPJs7Z?iq>fg\q#K^[q>dl%q#K[Zr;c<dq#L-g!!)`mJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKdrse]%pAajdpAaj*3Lllo
+J,~>
+$HgA:p@@qJp@@qJq>_<%p@@qJp@@qJp@@qJp@@qJp@@qJp@A"Z(A@=mo(MYJo(MYJo(MYJo(MYJ
+o(MYJq>a7`o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(`8%p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJr;[H'o(MYJ
+o(MYJo(MYJo(MYJo(`98p@@qJp@@qJp@@nWp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ,kgg&o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo#?*t
+b$ff~>
+!rqu=q<n(ZlL+HJlL+KKZgRVhl0eKMn*]uOp?hn\JaVpn"MN(Rs."T~>
+".Z/ApAY'lpAY'lpAY'lpAY'npAajcrrDclrrDclrrDclrrVoopAY'lpAY'lpAY'lpAY'npAajc
+rrDclrrDclrrDclrrVoopAY'lpAY'lpAY'lpAY'npAajcrrDclrrDclrrDclrrVoopAY'lpAY'l
+pAY'lpAY'npAajcrrDclrrDclrrDclrrVoopAY'lpAY'lpAY'lpAY'npAajcrrDclrrDclrrDcl
+rrVoopAY'lpAY'lpAY'lpAY'npAajcrrDclrrDclrrDclrrVoopAY'lpAY'lpAY'lpAY'npAai;
+s7H<o`A+0Y.=_~>
+!liB.JbFZgM=q(lH-4-8J,~>
+"SVl7me25"PjX%pme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6&Xp?qYBp?qYBp:\HFp8!3~>
+!i2>HJcC<$M>m^t3LlloJ,~>
+J',cZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqLA58pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA0:4qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY%pW`l__?~>
+J,f5ep?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp4)N(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme2.up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?oW=pA^Y5~>
+!h?&@JcC<$M>m^t0r1<gJ,~>
+"3/K/pAXo<pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZB_M;rqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY#L:pA+p3H-4-8J,~>
+"8;c6mf)p0me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)BC@:f`p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[
+rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[
+rq6?[rq6K.`W,Y-J,~>
+!i2>HJcC<$M>m^t3LlloJ,~>
+!m8N2JbjroM>@@pIE'E<J,~>
+!rqu=rq6?[rq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[
+rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Y
+rq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[
+r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[
+rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[
+rq6?[rq6?[r:U-Yrq6?[rq6?[rq6?[r:U-Yrq6?[rq6?[rq6N`^!69NS:C~>
+!h?&@JcC<$M>m^t0r1<gJ,~>
+J&]WVqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqLAPAs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8%6FqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ"Q\b/Rk?~>
+"8;c6mXb(_p58PH]uC$FUjr~>
+!i2>HJcC<$M>m^t3LlloJ,~>
+J',cZs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls*snFqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqYu'As8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8'```l__?~>
+!rqu=JbFZgM=q(cc1_1-J,~>
+!h?&@JcC<$M>m^t0r1<gJ,~>
+J&]WVqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqLAPAs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8%6FqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ"Q\b/Rk?~>
+!quZ5JbFZgM=q(c`W,Y-J,~>
+!i2>HJcC<$M>m^t3LlloJ,~>
+!m8N2JcC<$M>m^uIE'E<J,~>
+"98)>s+0lpp58PH^!69NS:C~>
+!h?&@JcC<$M>m^t0r1<gJ,~>
+!liB.JbjroM>@@pH-4-8J,~>
+!quZ5JbFZgM=q(c`W,Y-J,~>
+!i2>HJcC<$M>m^t3LlloJ,~>
+!m8N2JbjroM>@@pIE'E<J,~>
+!rqu=JbFZgM=q(cc1_1-J,~>
+!h?&@m/I0&@U`O)rr["F@Tr!q");:S>2K8[e]mXaq:,J8l2LasrN$"4JcE7["N<*kS1/s~>
+!liB.m.UEY!(c>Ir`&qhkk>!U!(c#@!qOdZnb2e,!1iBJ"hL_1Whm:Xp:0f!`d,_H@=S~>
+CA.\HmdBf:p?qYBp@dqJme6)Bme6)BmRfc23VMn7me6)Bme6)Bme6):p?qYBp?qYBp?kO=5rnZ,
+p?qYBp?qYBp?qYJme6)Bme6)Bme6'@5s[O)me6)Bme6)Bme6)Bme6)Bme6):+85-rme6)Bme6)B
+me6)2eb8G)me6)Bme6)Bp?qYBpA*i&^%Umfme6)Bme6)Bme6)BmdBf:p?qYBp;O_Y`P'Oap?qYB
+p?qYBp?qYBp@a"(p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qW<me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme4?5s7W7=~>
+!i2>HmJdAgeb7Op!!)?b##a"FeZ8`Nli./eeb7Op!!)!X!nI=qnc&U>rVm#omdAVqli.!eSGiHg
+PdH#A\c2fO3LlloJ,~>
+!m8N2mIg`D[bA0P!!)?Y"us'F[ZLOilh1NB[bA0P!!)!O!m:P_nb)t2rr3/up?LqkSa5tMWgWhc
+!L9[9p:9l"`dPkL@=S~>
+CB+"Pp@dqJme6)BmdBf:p?qYBp?qYB3L%4AErZ4.p?qYBp?qYBp?qYJme6)Bme6)BmQ$NFP]Hg)
+me6)Bme6)Bme6):p?qYBp?qYBp?jr*]p*R<!:KRKp?qYBp?qYBp?qYBp?qYJ+R\skp?qYBp?qYB
+p?pf;eaE/!p?qYBp?qYBme6)BmcOHIs7R>m[.`q]me6)Bme6)Bme6)Bp?qYBp?qXf[/L"8XM+&q
+me6)Bme6)Bme6):J+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)BmQU@4p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYB^!69NS:C~>
+(S%9Up@eO*s2G#Ws8VfmpAajdpAajd;Z?\6k1,u2!<;cmpAajdpAaj[s7ZKds7ZKds&/jr)<TJ>
+@K?H%s7ZKds7ZKmpAajdpAajdpA\%is#0#iS72KupAajdpAajdpAajdpAaj[s7ZKds7ZKds7ZKd
+s3:SWs7ZKdk/IAos7ZKmpAajdeboFcme52fSH&<_pAajdpAajdpAaj[s7ZK\m];ZOs8Vd&Mlc(/
+pAajdpAajdpAb/BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajd55,$Ms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZK30r1<gJ,~>
+C<"DAo()h#s2P)Yp@e(No(MYJo(MYJ39KMod^k-+!;?!Wo(MYJo(MYFp@@qJp@@qJp,M4"maA\#
+9E=eWp@@qJp@@qNo(MYJo(MYJo(G'*lL**3KhML?o(MYJo(MYJo(MYJo(MYF+SPC"o(MYJo(MYJ
+o(L6+](Y^go%qC[o(MYJp@@qJp<rp>0`(5*daju_o(MYJo(MYJo(MYJo()MFo"M8pNW8kKqY'K>
+RBFEtp@@qJp@@qJp@a",p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@o@o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(L(Kb/Rk?~>
+$MOM=mdC+gs1SHGp$N)G`RWhaS8(%amHt6?`RWhaS8(%amHt6?`RWhaS8(%aj6d!!s3:N1!Tqr,
+mJuDIrri&qk3fqPmKD[)@Y:c[rri%kK3EnYm_%rj]uC$FUjr~>
+!i2>Hrr3VMs2G#Wp@eO[s7ZKds7ZKd;YL%g(Y)DU;YL.as7ZKds8VfmpAajdpAahapAFq,eP]";
+pAajdpAaj[s7ZKds7ZKds7T@ar;SS';G'j\s7ZKds7ZKds7ZKds8VfmpAajdpAajdpAaj2s0VM"
+p>4'VpAajdp@eO[s7Y"@ruLh$Un"6Ns7ZKds7ZKds7ZKds8VfmeaE-q`TH=NroO^8MuW5%pAajd
+pAajdp@a"9pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAahMs7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7XDlS>7Ta~>
+C<FPEp@eO+s2P)Yo()MFp@@qJp@@qJ39'N"qY'?c845l:p@@qJp@@qNo(MYJo(MYJni5Y"o(r(J
+[R`eSo(MYJo(MYFp@@qJp@@qJp@:3&o()YNm^>YS7.U'Bp@@qJp@@qJp@@qN+S,6sp@@qJp@@qJ
+p@?B+Y4D;Wf$<:Gp@@qJo(MYJo$[L:!rDKQrLGD2o(MYJo(MYJo(MYJp@@pJb2S8tk2PO_k2OC7
+k/Nt_p@@qJp@@qJnpgB(p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@:E@o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo#?*tb$ff~>
+$NKhEmdC+gs1SHGp$N/Ic0"Hfk1,\^0fe^j$9?Anme5enPX.#an*UNCc0"Hfk1,\^0fe@`!oEsr
+rpKgCp?hqCqu6fm]sPJ[na6NPC5\##qsFU;K8X22JaU5>"MN(Rs."T~>
+$_4"Ip@eO*s2G#Ws8DWks8M]os7Z.aqYpfohLe^0p@eO`p&P-lp&k?gp/:be#PR#,;Hiefs82Ki
+s8M]os7Z.aqYpfohLe^0p@eOcp&P-lp&P-kp&P-lp&P-lp(%,rp:^L%p@d%Us4-i:s82Kjs4.&I
+s7QQ_hT_kop&P-lp&P-ip(GpUs+AS8c,IrHc,GV@s3:92s8M]ls8DWks8M]ls8;Qjs8M]ls8M]l
+s8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]l
+s8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qj
+s8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]qs2?^gS1/s~>
+)90gEmdC+ps2P)Yo()5>mdff:mdff:3:?YArttIh\nOE#o'Z):o'Yr:mdff:mdff:3:?YArttIh
+\nOE#o'Z):o()5>mdff:mdff:3:?YAs"jB.\nOE#o'Z):o'Z):o'Z):mdff:mdff:mdff:mde*l
+U%7Ws_Z/'Tmdff:o'Z):o$[I9)=m4Xg<,uSo'Z):o'Z):o'Z):mdfe6s8RfK`XRY%s-<0Co'Z):
+o'Z)>J*umqo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):nilL4mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:`d,_H@=S~>
+)>=*Lk2u]Ws1SHGmdB6*k3hC"k3hC"3Tg&6rtt1CS6A3NmcNs"mcN["k3hC"k3hC"3Tg&6rtt1C
+S6A3NmcNs"mdB6*k3hC"k3hC"3Tg&6s"j)^S6A3NmcNs"mcNs"mcNs"k3hC"k3hC"k3hC"k3gLo
+^$b%5ec4Lok3hC"mcNs"mcOBG(\[:R^#nbFmcNs"mcNs"mcN["k!=oiKDF%,K8YXJmcNs"mcNs"
+md>SemcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNq$k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3fq%s7W7=~>
+!i2>Hrr35Bs2G#Wp@eOcp&P-lp&k=eXS2Pk$heX65uJ9fpAaj[s8M]ls8M]os%9Bdqu7&tF%S_r
+&GGhtp@eOcp&P-lp&k=eXS2Pk#ki=35uJ9fpAb-c!<<&ls8W)l!<<&l!<<&l$NKh,p71j$^&RfF
+rq6Hop@eOcp&NY@rs8>dhTaT@s7ZKlp&P-lp(dW$s8Vfd`W,t_K8YA?K8YA?c2[ggrq6?lrq6?l
+rUp6krq6EnpAb-c!<<&l!<<&l!<<&l!rquorq6?lrq6?lrq6?lrq6EnpAb-c!<<&l!<<&l!<<&l
+!rquorq6?lrq6?lrq6?lrq6EnpAb-c!<<&l!<<&l!<<&l!rquorq6?lrq6?lrq6?lrq6EnpAb-c
+!<<&l!<<&l!<<&l!rquorq6?lrq6?lrq6?lrq6EnpAb-c!<<&l!<<&l!<<&l!rquorq6?lrq6?l
+rq6?lrq6K63LlloJ,~>
+)p60Ko()h#s2P)YmdBZ6o'Z):o'Z'.L$JO2s8Mj4k%-M36k&YSo'Z)>mdff:mdff:3/-YoqZ$Qk
+)<PKi3(+2Gmdff6o'Z):o'Z):ni2?gqYL6kqD.2E3&j;7o'Z):o'Z):o'Z)>mdff:mdff:mdff:
+m]u8Gm`*!@o"shcmdff6o'Z):des+_p?pe_cCOOoo'Z):o'Z):o'Z)>mdcY>p;Zo^%Dqu0Om_f.
+o'Z):o'Ypqo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):54\.4mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdfecIE'E<J,~>
+$ifqFmdC+gs1SHGk5F]Jk5OcQk3b6EhY-[Brs8>T=ueT/#k$jPmJuDKmKVhA3GRFEpAY'tp>/t5
+3C*r=k54QHk5OcQk3b6EhY-[Brs8>T=ueT/#k$jSmJuDKmJuDJmJuDKmJuDKmLJCIm`"n,ma]S^
+p=8U!k54THk55/]p?peo[/B=lk5OcKk54QI6&YGh"cI^nmdB6:mJuDJmJuDKmJuDImJuDKmJuDK
+mJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDK
+mJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDI
+mJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmKMadc1_1-J,~>
+$CmnHp@eO*s2G#Wp@\Mbmf!1a!!I%/K>f;2p't!gs8P)63Mc]CF%V)(.J*66;XXG^#%Cb>6%d-*
+kk57WmXrKlp?&IMp&NY@s8VfgeGu-5p&N)-s7t1FS:UCKp&r>hUmrla~>
+$HC56mdC+ps2P)Yp?i)HcLUi3qY^Bs=Ysuu+S5"'4O3Nor\OkRo&<q7D6>#QmLDA)o(rC_s7SuO
+82P%`+R&5!V<3KC^@p]clM']Hdes+Gp?qb)!1iiO!0R*Jq9f86JaU;@"NG`0`aOA~>
+%efqAk2u]Ws1SHGk3hC"roO4KroOAMXQK6VpAFso=ug&V+TCL*mcN["roO4KroO\VXQK4:0fc&t
+hHDpKPT]tfs6]pMmf)>Kmf)>Y6*05Bs7ZKd5rgq[@[&#7joFiKjoFiJjoFiKjoFiKjoFiKjpLOi
+p8#sXs6dS_mf)AKmK)J<roX(Wq;qdmk2u+2jpgb@k3h@tH\6ZtH\6Ztq;qdmk2u+2k5XlKjoFiK
+joXu5mf)>Kmf)>Kmf)>Kmf)>MmcNs:joFiKjoFiKjoFiKjoXu5mf)>Kmf)>Kmf)>Kmf)>MmcNs:
+joFiKjoFiKjoFiKjoXu5mf)>Kmf)>Kmf)>Kmf)>MmcNs:joFiKjoFiKjoFiKjoXu5mf)>Kmf)>K
+mf)>Kmf)>MmcNs:joFiKjoFiKjoFiKjoXu5mf)>Kmf)>Kmf)>Kmf)>MmcNs:joFiKjoFiKjp1>:
+k.Sb6p8!3~>
+$Da1Pp@eO*s2G#Wp@\MbpAY*l!!'_2!!6=(.J*6C;YL,oS5PSd0fc$a@^ITUp&S(br;R"*s8Tc9
+>-'1:p'.&DH`ZYcSFuRUec#LMp?q(nrVm#omdAVqp\"Toq>UHFrVm#omdAVqJbHnQ"N<BkUa^f~>
+$HgA:mdC+ps2P)Yp?i/FlLOfJ!!'>'!!5ss,kLF639p';SQ1ed1c1mO<M:i4mK,B5o)AIkp.55`
+SOc;>.-U((RG)qdk0fO[p?hq/rr3,tp?LYcrr3/up?LqkSbMOYJaVgklL*s*lI,\3"o@rXlI)5S
+m_J5n`dPkL@=S~>
+$NKhEk2u]Ws1SHGrT4+JroORUk2n\dk4\KK!3H,!"%iP1mf)>NmcN["roOj]k2n\dk$"9QP\Mp5
+U``9^+R]-h!:KjK"n(O83TfK'p'L.Is8R.#3I;n:roO4KroO4KrT4+JroO4KroO4KroOElk+'EY
+hR*:E!:KaH!q,45r;QilmcOHIs7QTX[-$N=qrS7R3I>goF*htTF6<E#s7QTX[-$N=rT4+JroO4K
+r8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4K
+roO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4K
+roO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroOFQk.T%5s."T~>
++.T,]mdC+os2G#Wp@dqJme6)Bme6'HpAb-mm_uQiV#:9F^#o%Vp?qABme6)Bme6'HpAZk*C>T!j
+hJ+c*V!d[Eme6ABp?qYBp?qYB;YL(h!+Pj*/m;`Hp?qYBp?qYBp?qABme6)Bme6)Bme6)BPbb,3
+`J`mPme6)Bme6ABp?qY)rVlunmdAX'rsnJje_Zhime6)BmdBf:XSMkreboFSme52fSG)CEme6@(
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)B548.4p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qXn0r1<gJ,~>
+$HC56lK\Dhs2P)Yp?DrHlLsoOhR9T<RJd*d[bgZA%Qs%M1kfMps8Uqe1c1o_oBHiKlLsrJp.4WO
+qZ$TX84_V%l3<6AS_D)?iq;R:df07Lp@@A2df'1LqX3e"et)U$$%:t$k3D*ok3CCnrrr8emaB[W
+Ja1):"NG`0`aOA~>
+$MOM=k2u]Ws1SHGp>uZAhX9e3e[2-sPl1R_[,1H;%QWD60oKf's8Uqj0fc&doB$'6hYljC614^O
+"5YauhWa/+XM)"'eYMg!r;Zfj!9X4Z"SVlXk.UQP#ruaAC3+-2C3/P8rri&qk2s@.k/$0_]uC$F
+Ujr~>
+(8RH\p@eO*s2G#WmdBf:p?qYBp?kPKrr32re`Q<"hB;dt'VsmZp?qYJme6)Bme6'@V#Qr>PdL>f
+&aigW3UZV/me6)Bme6)BmRj;Qrr?7#s"F*GjoFiCme6)Bme6)Bp?qYBp?qYBmb[*gp?m!Sc*VQS
+p?qYBp?qYBme6)Bma_=:!;?E[!7h#I(\[9mS>;\Kme6)Bp?qXEs7ZKds7ZKdeboFSp?n`HUn%/H
+p?q?up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYB55+F<me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6(f3LlloJ,~>
+$HgA:lK\Dhs2P)YpZ`,CL$%t"lGhE3lI$[O!!/YEp$)`<L$"dSOg=la"6s#G2"g,91kk)_rq6Xh
+qYL6cp?LeW!:T1\`jWIulKW57b-lHPo]c_1s8VrdmdBAgrVlrqo'61Eq<A9+ini\Oini\Odf'1I
+qXWqMSUp(Cl3,+T`l__?~>
+$NKhEk2u]Ws1SHGpZ;i4C=V2'e\/rHe\rC)!!/VHp#ZH-C=Sh/PdL>f"7B>I3VDM:.;IDiroO28
+rr3/qs5qk%!:T%WXF#Sik2qSlhSk`Mk5G>Zp&O7Prri&/[(WjBjp<bW@VT@e@VTB7qu6fm]sPJ[
+J`ai3"MN(Rs."T~>
+$CmnHmdC+os2G#Wp[/&Bmf!.gpAajdhYdETSDNr,#!),O>)S<qqYpV<blIG)!BKTIrrGDhqYpWj
+`;oGr!p7bqrr32bm\J*SF6<)^!7h)Ks7QN^p=9*@s7QQ_hT_klmKoEWs7ZKds7ZKCr;Zfj"7G$j
+Uk.sNmKCK`Umrla~>
+(WOUCk2u]`s2P)YlK[Nsk3D*ok3=ACqYp$gio]7_^AS$GS_EAklK76ok3D*ok3=ACqH8Z/gA:hJ
+ER"^Pk3D6olK7BolK7@[de`P*4@o&:s7Z0Smc'o?lK7BolK7BolK76ok3D*oer?ullH5gCQ-OYt
+hWj7gk3D*ok3D6olK7B[s8Vf`o'Yqor;RT(mcN6GS`]5"lK76ok&&i/g>:Q?g>:9UrsJ>bk1[tK
+k3D*ol@7s]k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3>.mlK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolGe+l`aOA~>
+(\[mJhVS:Gs1SHGk2tO_hWE\WhW>r^k5O6:blQ@br;[P%c0!mFhVRDOk2,7Wjrgbf>)S<qqYq=P
+blHn_k2tO_hWE\WhW>r^k2+r\3VNFO([gG9HN<3bk2,7Wk2,7WhWE\WhWDdC)#bs!6(EkiS<VRd
+hWE\WhWE\Wk2,7Wk2uUA!quZVqYq<(mbYY6k2,7WhWEZT>%1ZE>%1ZEk5,)`p?peNhWE\Wk'u7M
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhW@#Yk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk.Sb6p8!3~>
+$Da1PmdC+os2G#Wp[/Sjp/4L\9()E@p&O6gUnk*Sp$Mu]pAZRg@f$*,mQ%sYp$NAhpAahHS6G@\
+pAajdmd:(>na6e(s6f%Cs7Z0"K6-2GmK1r=s8DWlma_78"nqB@c./?[mK8^IpAb'a!7h#I"nqB@
+c./>8m_\Ap`AsHa.=_~>
+2p0-glK\Dhs2P)Yk2tsklK7BolK1@k1b^a?f&#-;!8b/TSYb3*lK7Bsk3D*ok3D(oipnLC@J^"'
+l9)d\k3D*klK7BolK7Bo5iV@o4Io%*o'Z5:mbYq`OlkrklK7BolK7Bsk3D*ohLWDDS[R\'d^FR0
+hWj7gk3D*ok3D*klK7Bodf9@<o'Yr2des+Tp?pe_cCO7_lK7Bsk3?[[ecj45^:q2,r;R,tmbZ77
+Sa,A&k2q0Yk3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D(mlK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7BolK7Bo
+lK7BolK7BolK7BolK6*7`l__?~>
+(]X3Rk2u]Ws1SHGhVRDOk2,7Wk2%i;+T<5X^&Q%g!7eH@S>>#uk2,7_hWE\WhWEZLc.+7i@f$*u
+mQ%sYhWE\Ok2,7Wk2,7W1!S7f3Li+[p?qY:k09\%Mr*UQk2,7Wk2,7_hWE\WeK>D?(a'qM.:SNN
+e`P`NhWE\WhWE\Ok2,7Wk5G;^pAajKqu76$mb[*5k2,7Wk2tO_0j7IYrCR)Vk55/bp?pf"[-$6-
+hVNbEhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWEZYk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2*erpA^Y5~>
+%@j4Kk2u]_s2G#WmdB6:mf,QX3USn*k5YJLqGR@D#3P@Ak3h["rpKeP#<D34hP;lQhYR6XF-Kk(
+mcNs*k5OfK5nl?I3Ss0iUgh%2mf3"\p@_ZnSF5P=mJuDKmf2GKmKVgmp=7^]mf!.fmcNs"rpBdK
+rpBmNmdB6:mK;#>pAb*b!7h#Is7ZKL$Its?mcNs"k3hZ-q=Xg=r;Zfjs5!n/V!d[5rU'[JrpBjM
+mcON:!9X:K!9X:K!9X:K!p8q5rpBdKrpBdKrpBdKrpBjMmcON:!9X:K!9X:K!9X:K!p8q5rpBdK
+rpBdKrpBdKrpBjMmcON:!9X:K!9X:K!9X:K!p8q5rpBdKrpBdKrpBdKrpBjMmcON:!9X:K!9X:K
+!9X:K!p8q5rpBdKrpBdKrpBdKrpBjMmcON:!9X:K!9X:K!9X:K!p8q5rpBdKrpBdKrpBdKrpBp.
+0r1<gJ,~>
+)TKpFio:!Xs2P)Yk2t[cioW'S/ESK?V:NYdqD9#6db<^Cio]7[k2PM[1b@c?_OW6+g@kC@s&<j#
+<MAR7k2t[cioW'S/ESM#ei]L/RE!P;io\tK=\P+Cio]7_io]7_io9+[k2MMsM7Vip_WpjWY+`_L
+io9+[k2PO_k2t[cio\\hp@e(JmdAO$rtkCsf%/9?io]7_io9+[C!P#8]!f2Y]$gNV$MNo=f$^,K
+k2POcJ)]VMk2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k!%eeio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_`d,_H@=S~>
+$MOM=hVS:Gs1SHGqqh?%&KopQ+DR^1C)A'1+;c4<`Qcs.hZ##0+Pn6:UbR5QqYpY=PZjmYhZ##;
++Pn6:X?iXkF.B>oe_\iq=tu94h@=9+(mNmY+=T#o.3OP5eb%\uk5>5\pAa:Os8M-\^%pLd0iCpH
+5lg'Ds8M-\]n,%Wh?:O2s7W7=~>
+$`':QmdC+os2G#Wk5F]P6-[ZnK7ceirr`>YmdB67mL2D+c,G<fUf)hlK5/*trrb@4!0lXCmM8+5
+c,G<fUcFsHUhTnKme6):h>k5ek5OcKk5OcKk5F]Nk3fVV^&@C!rrD3[rrV'Fk5OcKk54QJk10M2
+p&jaVma_:9#km]Kk2+sbmcOE7$'b/Op?qYBp?pK0rs8>dk2tOWSF5P<mJuDKmJuDImJuDKmJuDK
+mJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDK
+mJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDI
+mJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmKMal3LlloJ,~>
+)9TsIk2u]`s2P)Yio9+[jtOft[Uj#(f#G`*Y&OHiio]7_io]C_jtOft[Uj$,:k<nCBtF?@s8VpT
+c2`j`k2PC_ioVr7b-kkmM*.?&Tk+4l_U?lP_>pl4io]7_io]7_io]C_k2PN?Tp=d"ij.RpU$C(W
+d[etKk2PO_k2PC_io]7Ks7Z$SmdBAgrr3l4p?LYog=i+[io]7_k2PN7b-nUYZECL9df07TqY'46
+hV-\Sk2PO_id^+Mk2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2JSeio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_il6Ddb$ff~>
+$NKhEhVS:Gs1SHGr8%`/`PnWN=r<cfKDAsW!6t;q$n907Uf(B;;M0=KC;'QF"$+m3Mu)9F.E09%
+;He-%S?/N$!.0X2]qgkm8h'>f"qV&ThVQd"rZM4i"!B$A^%L4^k5G;^pAajKr;QcjrU'Zmq;)-$
+9)UaP0f_8Vr;QcjrU'ZmJ_n9#"MN(Rs."T~>
+&=fONk2u]_s2G#WmdB6*k!AtG#/*q7s&*#ur`T;"r`]:$#O^aBk2u*o62gg#]n7b\F+]+'K6)\F
+K2SLKPj[]%mcNs"62gg4]g8HqS?/6f@K:/^]fF&8Pj[]%k3hC"k3hBomcNs"eaCE=m`ke3eaEA8
+(#JB@mcNs"mdB6*k3ge"pAaj[me530rttItmcNZgUuq+-mcN["k+(l5me6)Bme530rsSPgmcNZg
+Uuq+-md>SemcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNq$k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3g2CUmrla~>
+$HC56io:!Xs2P)Yr8J5DqZ$ESV)6?71f."K=]J;t<W3!piY=<Hs8(lSBde7LI=6g#D1V_<:n:UO
+qVi5HqZ$ESV*(<FSY_m[AH6;8R4tp?NUl'>FbugOigmg'RBl,?f&#DSp#68*s7Z0Wo'Yqorr35s
+o&f5sing7%iX'2)Y,\Y)Y,\YQrr35so&f5sing5Wikj[X`d,_H@=S~>
+)>=*Le^a]5s1SHGhVQf>eLBqdma[OEMi/GO;?0nu;Z6YqhUUK5e_\h*mf2_*PZfM_F+]+'K6)\F
+K2SLKMr*"@hUUK5.IR6(eW`@qXIQA^Zsj#MHZM2>.>-L-hUUK5hUUK5e_\j5eIW"Ee_XaP(dT8n
++T<f!3Sr<Ce_\j5hUUK5hWFb9!quZVr;Zfj%IWrX^"(uihUU05eM0)\0`^A6s8Vcume6(^e_\j5
+hLF)4e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_WL?hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hS$o.p8!3~>
+&u;$XmdC+os2G#Wk2u*omQn5Jrr3j.s2@n0s6f=3hTa<Y]sKNVmcNs*k3bOBmf!.h3I=qV>$Co?%
+oQ#X;P]iFmcN["k3bOBmf*5R3VNL@Uo^)^S?-0"@T%OQk3hC"k3hC"k3h["mcNrNs/`o@mf18gm
+f2_;k5Y/3mcNs"mcN["k3hB-S>;[NS>;\*rr2ulrU0^J%%QbJmcNs*k3eK%me6YJ!qu'4rr2ulr
+U0^J"e>#CmcNY]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"m
+cNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"m
+cNs"mcNs"mcNs"mcNs"mcNs"547S$k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k
+3hC"k3hC"k3hC"k3hC"k3hBN3LlloJ,~>
+$HgA:io:!Xs2P)Yr8JGFRF_67qCopC;"jVNk2+\3`kJme0`'cD0U^Mgs8)";H!,Dq=`%ke<ChsH
+Tp>K6'el',qZ$COmf2RGTq.aBTk+488::L/iXfglAW_P7[Z0.Dg82fh_R@>Tiq],Qdf9@Do'Yr2
+k2PBkq;N)sV4j`ZV4j`Zdf9@Do'Yr2k2PBkJ`=Q+"NGl0b$ff~>
+3WJfthVS:Gs1SHGe^`O,hB70Ymf2\lK1]&8s6f=3hTa<Y]sKNEhUUK>e_VEq^$bpgbrL,SHWjVP
+C0"5)Mc-@8e_\j,hUUI*HbJkImQ("@m\HqSUn"Mq!+IC(!7frVhUUK5hUUK>e_\j5#QP]V8f/+*
+bodiPMcpr?SDMfQe_\j,hUUK5]sPJ[]sPJ[k5G;ipAaj[me4$Ee_\j5hUUKX.0/N/rsSQ#p@dqJ
+[,0?ie^]0+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\h?hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUT<apA^Y5~>
+$CmnHk2u]_s2G#WqrSS(#gN)C;ZBYOk3h["hTa$HUm+c8q;rA&#gN)C>(^"Cs6be2;Gp[ah?]%8
+q;rA&#gN)C6-\9SpAaiVUl1IiMh>I=o&]tSpAY'mhTc&^#63QBk2--gmcFN"rr<#l"n)*PmcL>@
+joCqNmJut[mK*%3rr<#l"n)*PmcL<rk/-6``A+0Y.=_~>
+$HC56hVS:Ps2P)Yqq`"u#dW1H1r;*+ip,ggf#k_0Tp8<.q;)es#dW1H=b0_@s5o##<E30aedRD+
+q;)es#dW1H4Nc+7mf2RCTo"b[Kmd5,o%jq#JXN47NLAMWS\hhlhOVN`mbS?"s8Vf`o'Yr.k2Ms-
+h@s7dTq.mJTq.n*s8Vf`o'Yr.k2Mq_hSS+P`d,_H@=S~>
+$MOM=e^a]5s1SHGqpk]P&rX`J+G1fnk3h["e]l(7Um+K(q:5KN&rX`J>(^"Cs6be2;Gp[ah?\b(
+q:5KN&rX`J6-\9SpAaiVUl1IiMh>I=o$m_4rW!?4&7Wo7(a+I]eN"InmaV="r;Qros7Z0S^%p1Y
+.JY(dk5>5_pAaj[m_+2%_USe&`W,Y-J,~>
+$Da1Pk2u]_s2G#Wq;r;49%?PI;Vp9mhVQMr[&g'<+I)W_$Qr'l0gSG*k4[s;s8GUmPZ!ajpZ<)2
+9%>r'^"(BXk4\iCH]*5S5lgH;"K];U[*AU4#M&P)k2sY_c0j]sec5[CpAOFZjoCqIjoUe8k5OcR
+k3hZfs8VfdrU0^J!1\W&_WD!?3LlloJ,~>
+$HgA:hVS:Ps2P)Yq;)`(4L-Yh:u9pchV-,h[]6$8+HcET$QM:71dFIsk3hC3s8GOkO]@O`pYHN&
+4L-r?[`Zb@ipQj3I=ZfL6icf7"kJ6=D0`;`h?T1C_VX.+_P-DS$e#(To()5:lK[NkSb_+V=dbPC
+Q'mo*Q.#^4o()5:lK[NkSUoY7h?:iH`l__?~>
+%KH.HhVS:Gs1SHGe^`OUeJ[5o&2BCd8kRssk2+t>`O)_:C*8GbhUU05rm_J7eIXI"0gSG*k4[s;
+s8GUrPZ!FQe_\j,hYu%@hUN/lPW>hYe]lY,pAaQ-MgJVn!7fs*eH"J*ec4M*eIp``@MfY2Mq-\7
+(_Ee!hF\?#hYu%-hUU05rm_#*rm_#*rm_#2rVmE%s7Z0Sp9`B#hUUK>e^Yf<(]`^srsAE!p@dqJ
+[+3^`rRCo)rm_),e_^;U!8d_*!8d_*!8d_*!oDJarm_#*rm_#*rm_#*rm_),e_^;U!8d_*!8d_*
+!8d_*!oDJarm_#*rm_#*rm_#*rm_),e_^;U!8d_*!8d_*!8d_*!oDJarm_#*rm_#*rm_#*rm_),
+e_^;U!8d_*!8d_*!8d_*!oDJarm_#*rm_#*rm_#*rm_),e_^;U!8d_*!8d_*!8d_*!oDJarm_#*
+rm_#*rm_#*rm_.bc1_1-J,~>
+)4[KWmdC+os2G#Wk2u*omcNs"mcFLI9%D2chZ(iB]sOT*8rKe5mcNs*k3hC"k3h@3K/!Aop?qYB
+5uL=->,7\Fk3hBomcNs"mcNs"!*T@&>-,]ne_]`os'eS\!9W_3mcNs"mcNs*k3hC"k3hC"k3hC"
+k0<q>k3gLf`U;mVk3hBomcNs"mcNs"mcNs"ec,UIpAaOgk+qG-mcNs*k3dlarpBdKrpBd:rr;rj
+s6^*RV!dC5k2q0]k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3h@qmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcMJCUmrla~>
+$HC56io:!Xs2P)YpYl_a1bdA#g=Fj#`k&ILR7N1.p#6M_JM[Almcs6*5Yt..<M>]/p#6M_6i[3i
+V7OgpdcUT0>spXPl/Dr%Wf?#lJYf(.iX=37p@e(JmdBB*igoo)'MOLOOd2&oOd4App@e(JmdBB*
+igkY[_Vt^<H-4-8J,~>
+$hjV>hVS:Gs1SHGec">)ec+D<eGp^/e]lt$e]l@P[%s3aMk&>ph>l+*h@e?=K/!Aop?qYB5uL=-
+>,7D-ebe2'ec+D<eGqT0!*ZJCe^`OEs8QP#3<7V/h>l+*h>l+)h>l+*h>l+*h?qfihD#RNhUN_S
+HiDk%ebe2'ec+D*ec+D+e`Q`.rq6E,hUVM[!\"ZtrX]/K&.n"#s8M]n^#%<<h>l+*h>l+(h>l+*
+h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*h>l+(
+h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*
+h>l+(h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*h?DHC`W,Y-J,~>
+$Da1PmdC+os2G#WrU'[JrpCE]md<\Nc,IZH`Po3kUni&CSB_'$"6T%>k5Oc]k3h["!2MV03Tg#i
+;E<8EPcWa=mJuDKmJuDKmf*7qMZ<`\XM*-abs=>iMuN,Ek5OcKk5F]Jk5OcKk5OcKk5OcU^&QWY
+V"W?qmdB67mJuDKmJuDKmKD\?ec5[JpAaR\joM"7qsFOJmX+ep!nI>NrV$9Zs5j?Pk5F]Jk5OcK
+k5=WIk5OcKk5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5OcKk5OcK
+k5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5OcK
+k5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5OcKk5OcKk5OcQk3g2KS>7Ta~>
+$HgA:k2u]`s2P)Yp>ul><R/J$b/2$(ZDF73'U?u9joX6:U&HkTk3ap"4OP4/V:tP'rr<IQ!!$/q
+[`\Wm6oY1+l/i51SUl'#Q%@6KjpTW;p@@eBmcs*"igol,'1c,+<EW=)<RUp@o()5:lK[NkSUoq?
+joi\P`l__?~>
+$NKhEhVS:Gs1SHGp>-;s;U*2"c,IZ/[%sL4&<t0+h@J-:UcC.ik4UN-3Rnt)SCR5frr<I:!!$3(
+^"!,-5req'l.uY[!"`$_!"cj3h>l^:rrMinrUp5uptc!"qB,e#rVlols8DWk["7)Nh?:O:pA^Y5~>
+)4[KWp@eO*s2G#WmdBf:p?qYBp?qWP]r\=7Zo+q\S=Gg9PcX<@p?qYJme6)Bme6)BmdAU2&>V<@
+3C-iE>,9^Bme6):p?qYBp?qYBp?qY:rX^:s!!$3(`Amp_XR>fMp?qYBp?qYJme6)Bme6)Bme6)B
+md@I\s$F*\p?qYBp?qABme6)Bme6)Bme6)!s7ZKdp?qYBmcL>=me6)Bp?qYBp?qYBp?qYBec5@C
+p@dqJmdB55p?qYBmXOrup?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?k-<me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bm_poVS1/s~>
+$HC56lK\Dhs2P)Yp?E/F^8e3=Y-+e$R?`b*Oepq+l3,tl#RI.'1^-!ESQ2*+n`g,2rX9)Q!!$/u
+\i9\PV<R7Lg23+GR>ldbl3l&?p@e(JmdBB*igoT($e#(Kp@@eBmcs)sSUp(Cl3,+Pb/Rk?~>
+%efqAk2u]Ws1SHGk2,7WroO4;roOq<]r\<BXL,()S=GL0Mk&Ydk2,7_hYuX;hYu[;h@.X7#c'I8
+3C-iE>*R#*k5X9=k2-+"!8d_;'&Md-#S77Y!!$3(`AmpVUupgrroO4;rT4+:roO4;roO4;roO:=
+boluc":/2nk2-+"s5!e=hYuX;hYuX;hYu[8rrr,rp@dpfroO=>k2tP"joF9;joF9;k5>5_pAaj[
+m_/V^s5*b;!8d_;!oE(rroO4;roO4;roO4;roO:=k2-+"!8d_;!8d_;!8d_;!oE(rroO4;roO4;
+roO4;roO:=k2-+"!8d_;!8d_;!8d_;!oE(rroO4;roO4;roO4;roO:=k2-+"!8d_;!8d_;!8d_;
+!oE(rroO4;roO4;roO4;roO:=k2-+"!8d_;!8d_;!8d_;!oE(rroO4;roO4;roO4;roO:=k2-+"
+!8d_;!8d_;#N"V*]uC$FUjr~>
+"JhPJmdC)J!:KgZ!:Kj[!:Kj[#jrg-8lA8Z8kT(K#rrimhY-[2p@dqRp&OO[p&OO[p(?HThR')S
+3AEOYXR>fUme6ABrq6?[rq6?[rq6Qap?qA![&![$"I-"Ep?qqR!:Kj[s6fm[!:Kj[!:Kj[$L[W]
+k+ou0XS2AUrq6H^p@dqRp&OO[p&OO[p(=*jUn"6NUn"6NUn%/Pme6):rq6?[rq6?[rq6htS>;[N
+S>;[NS>;\Kp?qnQ!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[
+rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[
+!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]
+p?qqR!:Kj[!:Kj[!:Kj["N<BkUa^f~>
+!m8N2md:-!9M#.Vs%*/X"@+d`S_!;us5F.3WhH-c1]if>ipQ77iW@]2U&G#nOfI.!mKM$QD.SRd
+mI'Y<nF#t?JaUDC"NGl0b$ff~>
+!rqu=mcFTo8kN"[9)_*Y3>e"*nE0c-$-f99UcC.iMko4tk5X9>c(pm/!!8(Se`c-!`A%W0@c$M7
+$b`p\[(Wi[[(Wi[[.*2c]sPJ[]sPJ[]sPJ[J`ai3"MN(Rs."T~>
+C7M(Ss8VfmpAajdp@eO[s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmpAajdpAajdpAajdpAajd
+pAajdpAajdpAaj[s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKm<VHIds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0ds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7Z/9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd56(?VpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAaj*0r1<gJ,~>
+!liB.Jb"B_M=LehH-4-8J,~>
+!quZ5rU'[JrpBdKrU'[JrpBdKrpBdKrpBdKr9aRIrpBdKqsFIHrpBdKrpBdKrpBdKr9aRIrpBdK
+qsFIHrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKrU'[JrpBdKrpBdKrpBdKr9aRIrpBdKqsFIH
+rpBdKrpBdKrpBdKr9aRIrpBdKqsFIHrpBdKrpBdKrpBdKr9aRIrpBdKrU'[JrpBdKr9aRIrpBdK
+rpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRI
+rpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdK
+r9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBsP]uC$FUjr~>
+!i2>Hrr2ulrr2ulrVllkrr2ulrr2ulrr2ulr;Qcjrr2ulrr3)os8VflrrDclrrDclrrDcjrrDcl
+rrDcirrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDckrrDclrrDclrrDclrrDcjrrDclrrDci
+rrDclrrDclrrDclrrDcjrrDclrrDcirrDclrrDclrrDclrrDcjrrDclrrDckrrDclrrDcjrrDcl
+rrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcj
+rrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDcl
+rrDcjrrDclrrDclrrDclrrDcjrrDclrrDclrrDclrs&2s`AsHa.=_~>
+!m8N2JbFZgM=q(lIE'E<J,~>
+!rqu=JaS*WM=(M[c1_1-J,~>
+!h?&@JcC<$M>m^t0r1<gJ,~>
+!liB.JbjroM>@@pH-4-8J,~>
+"nqu8p@dqRp''mXp?qYBrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj["7GmVmf)n[mf)n[mf)n[mf)n]
+me6)Jp&OO[pAaO]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rUp6Zrq6?[rq6?[rq6?[
+rq6E]p?qqR!:Kj[s6]p]mf)n[mf)n[mf)n[mf)n]me6)Jp&OO[p&jaVp?qqR!:Kj[!:Kj[!:Kj[
+!q,dMrq6?[rq?B[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR
+!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[
+rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[
+!q,dMrq6?[rq6?[rq6Tbp@c2=s7W7=~>
+!i2>HJcC<$M>m^t3LlloJ,~>
+!m8N2JcC<$M>m^uIE'E<J,~>
+!rqu=JbFZgM=q(cc1_1-J,~>
+!h?&@JcC<$M>m^t0r1<gJ,~>
+!liB.JcC<$M>m^uH-4-8J,~>
+"8;c6s+0lpp58PH]uC$FUjr~>
+!i2>HJcC<$M>m^t3LlloJ,~>
+!m8N2JbjroM>@@pIE'E<J,~>
+!rqu=JbFZgM=q(cc1_1-J,~>
+!h?&@JcC<$M>m^t0r1<gJ,~>
+!liB.JbjroM>@@pH-4-8J,~>
+!quZ5JbFZgM=q(c`W,Y-J,~>
+!i2>Hmf3:eSH&ThZiC%*U]:>o[JpBK3LlloJ,~>
+!m8N2me6Y\SG)s_ZhFD!U\=]f[IsaCIE'E<J,~>
+IfK,dmdBf:p?qYBp@dqJme6)Bme6&K!;>jSme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmdBf:
+p?qYBp?hn\6MBj@me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)BrpF%bme6)Bme6&K!;>jSme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BrpEt`me6)B
+me6&K!;>jSme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6):p?qYBp?qYBp?qYBp:\`Es."T~>
+!h?&@oDe^g!dgF;q#C6lYlFV$!dgF;q#C6la8c&;!dgF;q#C6l\,Z@+!dgF;q#C6l`;]tZ0r1<g
+J,~>
+!liB.oCi(^!dU%2q"FUcYkItp!dU%2q"FUca7fE2!dU%2q"FUc\+]_"!dU%2q"FUc`:a>RH-4-8
+J,~>
+&GH.Cp@dqJme6)BmdBf:p?qhY$[\BDp?qYBp?qYBpA=nep?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp@dqJmed%m
+H^k*0me6)Bme6)BquAPHme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Jp&a[Umed%mH^k*0me6)Bme6)BquB+Xme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Jp&a[Umed%mH^k*0me6)Bme6)B
+quB%Vme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6ABp?qYBp?qYB
+p?qYB]uC$FUjr~>
+FJPEep@eO*s2G#Ws8VfmpAY,6Pf895s-s)hpAajdp&G)_hMZFTpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdp@_2[
+pAY,6Pf895s-s)hpAajdp&G)_hMZFTpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdrq9UspAY,6Pf895s-s)hpAajdp&G)_hMZFTpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdrq9OqpAY,6
+Pf895s-s)hpAajdp&G)_hMZFTpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAaj[s7ZKds7ZKds7ZKds2@!gUa^f~>
+FNVUOo()h#s2P)Yp@e(No(E&/NOjClp6bpSo(MYJnc/ZTeqkXPo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(#KJ
+o(E&/NOjClp6bpSo(MYJnc/ZTeqkXPo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJrpj=fo(E&/NOjClp6bpSo(MYJnc/ZTeqkXPo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJrpj7do(E&/
+NOjClp6bpSo(MYJnc/ZTeqkXPo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYFp@@qJp@@qJp@@qJp;VO#b$ff~>
+$NKhEmdC+gs1SHGqsF^iF,R,@KD(N0qsOIa"J"##Er`H4#QSq(XE0$fPQ:UKrr<1leVeJKa6j35
+F,R,@KD(N0qsOIa"J"##Er`];#QSq(XE0$fPQ:UKrr<1leVeJK`9mcAc1_1-J,~>
+!h?&@rr3bQs2G#Wp@eO[s7QG-Mq*0]s8SShs7ZElA!H-UmZ_Gds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds8Vfm
+p&JiceU+\'s-s)hpAP%QPii#6P\L3upAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajcrsnc&p&JiceU+\'s-s)hpAP%aPii#6P\L3upAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajcrsnc&p&Jic
+eU+\'s-s)hpAP%_Pii#6P\L3upAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAb0ds7ZKds7ZKds7ZKd`A+0Y.=_~>
+*6--Hp@eO+s2P)Yo()MFp@82#M8FP@qY$<Wp@A1_@u]LJif+cTp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@e(N
+nc0M`_Ki<\p6bpSo)8VMNT0utN>MZho(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYRp($Zenc0M`_Ki<\p6bpSo)8V]NT0utN>MZho(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYRp($Zenc0M`
+_Ki<\p6bpSo)8V[NT0utN>MZho(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MeJp@@qJp@@qJp@@qJ`d,_H@=S~>
+$MOM=mdC+gs1SHGqsFglC5]H?V#U.H!:K:S!!\\Ms5&ZK!3kl!!,@G!F/8j0MZE25rW!.ek5X:r
+C&l<B$NOq"Zu`&Cp58q=mf!1jPii#&MeW7$mL'#0MmRQ$s7V?NmdC&S#*e9MhMZ+K`9mcA`W,Y-
+J,~>
+$`':Qp@eO*s2G#Ws8DWqrr?Mmc%ED&rrASg!!97is8MEfP\L3tp&P-lp&P-jp&P-lp&P-lp&P-l
+p&P-jp&P-lp&P-lp&P-lp&P-jp&P-lp&P-lp&P-lp&P-jp&P-lp&P-lp&P-kp'1Ns@[,,i[/U(*
+SGiKiXR?,fmK/Vf!<2Zls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8;Qjs8)En
+rr?Mmc%ED&rrASg!!97is8MEfP\L3tp&P-lp&P-jp&P-lp&P-lp&P-lp&P-jp&P-lp&P-lp&P-l
+p&P-jp&P-lp&P-lp&P-lp&P-jp&P-jp'1Ns@[,,i[/U(*SGiKiXR?,fmK/Vf!<2Zls8M]ls8;Qj
+s8M]ls8M]ls8M]ls8;Qjs8M]ls8M]ls8M]ls8DWks8M]ls8M]ls8M]qs2@!gUa^f~>
+)Tp'JmdC+ps2P)Yo()5>md^>lNP]tDs8)/CrW$H)lMBf2k)C2Xmdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdBZ6
+nc0A`_Ki<aqX0@B!'I+CqWdA.N>MZ`o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z)JmL8[Snc0A`_Ki<aqX0@B!)06SqWdA.N>MZ`o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)JmL8[Snc0A`
+_Ki<aqX0@B!(s*QqWdA.N>MZ`o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Yr:mdff:mdff:mdff:`dPkL@=S~>
+)ZTNUk2u]Ws1SHGmdB6*k3`4YMmRi,s8V56rW$H0mf2_Ck)3sSk3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2u*o
+mJp^S[!SVKs5nt5!'I@Ns6f=;MeW7SmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs:jp^\?mJp^S[!SVKs5nt5!)0K^s6f=;MeW7SmcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs:jp^\?mJp^S
+[!SVKs5nt5!(s?\s6f=;MeW7SmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcN["k3hC"k3hC"k3hC"^!69NS:C~>
+!h?&@rr35Bs2G#Wp@eOcp&tG*Mp6U^rr3GqMhC0cp?n00k*0<Ts8M]ls8M]ns7ZKlp&P-lp&P-l
+p&P-lp&b9fs8M]ls8M]ls8M]ls8M]ns7ZKlp&P-lp&P-lp&P-lp&b9fs8M]ls8M]ls8M`ls8M]q
+!+Ll2HbKFY%IT.,k4\N:Pa(<p@K?H-p&P-lp&b9fs8M]ls8M]ls8M]ls8M]ns7ZKlp&P-lp&P-l
+p&P-lp&b9fs8M]ps7Z0ds8M]q!+Ll2HbKFY%IT.,k4\N:Pa(<p@K?H-p&P-lp&b9fs8M]ls8M]l
+s8M]ls8M]ns7ZKlp&P-lp&P-lp&P-lp&b9fs8M]ls8M]ls8M]ls8M]ns7ZKlpAY*kp&tG*Mp6U^
+rr3GqMhC0cp?n00k*0<Ts8M]ls8M]ns7ZKlp&P-lp&P-lp&P-lp&b9fs8M]ls8M]ls8M]ls8M]q
+s7ZKdpAb-c!<<&l!<<&l"N<*kS1/s~>
+J&]WVo()h#s2P)YmdBZ6o'QJlM8FPDs8VZDI<j];p?Id&ie\3Ho'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o()5>
+mJmrX_KiHes$?50I<j];p?Id&ie\3Ho'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):rpj=^o'QJlM8FPDs8VZDI<j];p?Id&ie\3Ho'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):rpj7\o'QJl
+M8FPDs8VZDI<j];p?Id&ie\3Ho'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z)>mdff:mdff:mdff:m`'Op`aOA~>
+$hjV>mdC+gs1SHGk5F]`joAkCZu`>Ks5q:0F6<2imZ`smMdc\cmJuDKmJuDImJuDKmJuDKmJuDK
+mJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDJmM=pb@Y;%/XT/=_
+`F<oNp@dp=Phq=-!<2Bdk5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5+K]
+joAkCZu`>Ks5q:0F6<2imZ`smMdc\cmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDK
+mJuDImJuDKmJuDKmJuDKmJuDImJuDImM=pb@Y;%/XT/=_`F<oNp@dp=Phq=-!<2Bdk5OcKk5=WI
+k5OcKk5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5F]Jk5OcKk5OcKk5OcPk.Sb6p8!3~>
+$Da1Pp@eO*s2G#Wqt:0n@[,,i^&J$?p>,fLs.#>(s6beS!3l/#!+M2;K>%9a%//NXs8SURec5&q
+@K=IB"TW"rc%E_/rs\VX!<<(hPh#g%Mdc[qp&tG*Pg+iorr3E#h>mTUS<VS(mYbNS`:a>Q3Lllo
+J,~>
+$HgA:mdC+ps2P)YqsG1!&;e8L[efjkhS'!`qN[2os5JkH!3kl+!"b"(H+*SGo%q(\pA1&:f)O`d
+&-0c='`\f%_KiTdqXWLW!;?8SOk0QlM%BZrmM,^5M8FPHqYKd>^&[m'Q''Ytie\3H`9mcJIE'E<
+J,~>
+.0'"ck2u]Ws1SHGk3hC"k2lYQMl_!$s7YToS,iThS<VS(k(@+Ck3i62!:KjK!q,4=roO4KroO4K
+roO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KgJ)XcbM
+!+LkfF0,E8k/Ehjs8SURec4ca@K>QYroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=roO4KroO4K
+roO4KroO:Mk3i62!:KjK)XcbM!+LkfF0,E8k/Ehjs8SURec4ca@K>QYroO4KroO:Mk3i62!:KjK
+!:KjK!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK!q,4=r8npck2lYQMl_!$
+s7YToS,iThS<VS(k(@+Ck3i62!:KjK!q,4=roO4KroO4KroO4KroO:Mk3i62!:KjK!:KjK!:KjK
+!:KgJ!:KjK!:KjK#O^a:^!69NS:C~>
+$CmnHp@eO*s2G#Wqt:a)@Z/KX`W,u3p&K^Fs5s@]p?%9:!3l/3!+Ll2Hc?$bp@\K=!<;3]s7YT5
+=ocV:'`_^$c$RG0s7Z-dK)kr6s8VfTMcp+ip([R:Mp6Ufs8Vfd!.t:Ok5YJTk)3CC`:a>Q0r1<g
+J,~>
+$HC56mdC+ps2P)YqsG1!&;@uH]))9oh>hg$s5s1So&>K7!3kl+!"ak$H+NkKo%j@l!<;3XqXWX&
+$in?9'`\f!_Ki`hqXWJCGl[m,qYKdBM$sBnmM,^5Ku/,HqYKd>!-nSEk5+rFie\'D`9mcJH-4-8
+J,~>
+$MOM=k2u]Ws1SHGrT5$djoAkCZu`>Bs5q9#Erc7&s8VfLK3A9;k3i62!:KdI!:KjK!:KjK!:KjK
+!:KdI!:KjK!:KjK!:KjK!:KdI!:KjK!:KjK!:KjK!:KdI!:KjK!:KjK!:KgJ)Xc_f@Y;%/XS2\V
+`;jrZs5s@]p>1F*!9WG3roO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4Kr8n"IroO4K
+roP-ejoAkCZu`>Bs5q9#Erc7&s8VfLK3A9;k3i62!:KdI!:KjK!:KjK!:KjK!:KdI!:KjK!:KjK
+!:KjK!:KdI!:KjK!:KjK!:KjK!:KdI!:KdI)Xc_f@Y;%/XS2\V`;jrZs5s@]p>1F*!9WG3roO4K
+r8n"IroO4KroO4KroO4Kr8n"IroO4KroO4KroO4KrT4+JroO4KroO4KroOFQk.Sb6p8!3~>
+(8RH\mdC+os2G#Wp@dqJme-WiPg+j"rr3Q'hL#;&m_t]\mYbNSme6)BquBIbme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6):p?qVS
+@[,,i`W#lKp>1/rs6djrPjXH=!:KRKpA=n?p?qYBp?qYBp?qYBp?qYBp?qYBp&OgSp?qYBp?qYB
+p?qYBp?qYBp?qYRmKiOSp&JQdc%F"7s%)k?HiO-6`LN1\Mdc\Sp?hqKp?hqKp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYR!!N#`p?qYRmKiOSp&JQdc%F"7
+rt"h[HiO-6`LN1\Mdc\Sp?qkZ3qi"8me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6&Kme6)B
+mdBf:p?qYBp?qYBp?qXn3LlloJ,~>
+$HgA:lK\Dhs2P)Yqs"mr&;e8L]))-khS+:/s6dmlOlhK3!<)3\!4hA0!"b"(H+NkGo%q*+pAaR#
+Q'(3c&-2[oquH*K!!)0H'`\f%_Ki`hp@@(SH1q:+`g)\KM%B[dl2Uh`l2Uh/lM^eWl4j:1M8FPL
+qY'L:^3TGPm`(NSk(sWLrp'F^hs(1AmcjqpIE'E<J,~>
+$NKhEk2u]Ws1SHGqrSUn@Z.=7XS2AU`KYHDs6djrPidU-!<)'X!4h5,!+LkfH`Zr7m_tE3s8VN+
+S<W/g@K?AhquH*G!!)0D'`_^$XF%&Bp?onaF8u:.`LN1TK44i[jo>D\jo>D+k5GASjqRl*Ml_9,
+p@dpnP]Qm)m_t]\k(@+CroX.ZhrXn=mcFYcc1_1-J,~>
+(7_0Tp@eO*s2G#WmdBf:p?hoiMp6Ufrr6L%eH#=CPa(%uk)3CCp?qVS!:KRKp?qYBp?qYBp?qYB
+p?qYBp?hqKp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp@dqJ
+mJp^Sc$RG/s$6;.!;?GWPhu,rMcp,Sme-V\me6)Bme6)Bme6)Bme6)Bme6)Bme-YSme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Jp'C*[mJp^Sc$RG/s%rF>!;?GWPhu,rMcp,Sme-YSme-YSme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme-YSme6)Jp'C*[mJp^S
+c$RG/s%`:<!;?GWPhu,rMcp,Sme-YSme-YSme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+!;>jSme6ABp?qYBp?qYBp?qYB`A+0Y.=_~>
+$HC56lK\Dhs2P)Yqs"mr%#)QD]))9ohS'!`qN6osp>Uc7!<29`!:8tN!6aXB!"=RuH+NkKo%q(\
+pA0o6hY,r_$ip:lrrDBM!!)'E'`\Yr_Ki`hqXWLW!;?8OOl#fkKa[t\l2Uh`l2Uh,l2UhYl4j:-
+Ku/,HqYKd>^&[m'OceMoie7d@rosI`rosI`i9C:BmcjqpH-4-8J,~>
+$MOM=k2u]Ws1SHGqrSUn@Y;%/XS2\V`KUArs-/c)p>1F*!<2-\!:8hJ!6aL>!+LSfF0,*8k/EPb
+pA^AAhY,fY=oeQarrDBI!!)'A'`_]qZu`>Bs5q:b!;?GWPhu,jK3A9Sjo>D\jo>D(jo>DUjqRl*
+K=#^$pAa9oPQ:FWPa(%uhLeu3roO1\roO1\i8t">mcFYc`W,Y-J,~>
+$Da1PmdC+os2G#WqsFUf>*R9a`W#l>p&KF>rr3/PPjXH=!<2Bd!;c-_!<;Hm!:K7Tmd:&Tmf!1d
+mf!4cmf!4dmKEUYmJu\CrW)udr;clcrW)rcrW)udrW)]\"TV_jc%F"7rr_rpHN='F"kAk*Mdc\c
+mJm7`mf*:emf!4cmf!4dmf!1gmJu\Cr;cibrW)udrW)]\"TV_jc%F"7rr_rpHN='F"kAk*Mdc\c
+mJm7dmK*CVmf!1kmJu\C!:K7TrU0Uas6fmes6fjdr9aObrpBdemf!4dmK3IWmK!1Q!!)c]"TV_j
+c%F"7rr_rpHN='F"kAk*Mdc\cmJm7dmK!=UrW)rcrrE)erW)udrW)udr;clcr;clc!!)HT"N<Bk
+Ua^f~>
+*QlBMk2u]`s2P)YlK[Nsk3;pTM8"8HqY'L:!-nSDrt*J<ie\3Hk3D(/k3D*ok3D+.!".lR!:&\H
+k3;pHk5G>\k5G>^k3D+.!!hZO!:&\Hk3DpG!UAhG!!2BIrW!#^lK8'G!Tr\H!#Fk^lK7Bok3D*o
+!"=^uH+NkGo%j@l!<3!4cB7+C&-1kXjoFQ/k3D*ojo>DHk5G>^k3D+.!!26IrW!&c!:&_F!!;HJ
+lM^balK8'G"6Sn2lMfoVlK7@3%#M]D]))-kh>hg$rr3MSOlD3/!9WS/!9WS/!9WSG!"8&llK/*/
+l2^,3lK8$F"mY4M!:&_G!".lRk3D(/k3D(/k5G>kk3;s3joFQ/k3D(/k3D*oroOaVk3;pTM8"8H
+qY'L:!-nSDrsm>:ie\3Hk3D(/k3D(/k5G>bk3D(/!:&_G!!26IrVuuak5>8\lK8$F)X?Gbk3D*o
+k2tsklK7BolK7BolK7BOIE'E<J,~>
+*WPiXhVS:Gs1SHGk2tO_hW=fAMl_!$s7YTo!-8/>rt*_Fk(@+ChWEYphWE\WhWE\o!".TF!9W,<
+hW=e<hYmKThYmKVhWE\o!!hBC!9W,<hWFe;!Tr8;!!26=rW!#Vk2-(;!T)u<!#F_Rk2,7WhWE\W
+!*Y;^F0,E8k/@=A!<3!4eWf3K@K>9Ih>lEphWE\Wh>dQ<hYmKVhWE\o!!1s=rW!&_!9W/:!!;<>
+k5G>]k2-(;"5`1sk5O3Jk2,5#>)TJ'XT/"V`;jrZrr3MZPidU-!8ckp!8ckp!8cl;!"7ohk2$*p
+joFQ#k2-%:"m4YA!9W/;!".TFhWEYphWEYphYmKchW=h#h>lEphWEYphWE\Wrn\1JhW=fAMl_!$
+s7YTo!-8/>rsmSDk(@+ChWEYphWEYphYmKZhWEYp!9W/;!!1s=rVuu]hYdETk2-%:)WolVhWE\W
+hVRDOk2,7Wk2,7Wk2,76c1_1-J,~>
+$CmnHmdC+os2G#WqsG1!@Z/KX`W,u3p=4fhs5'!)hWB`"!<2Bd!;l0a!<2Bl!:BjTmJu\C!<2Bl
+!:K7Tmd:)C!<2Bl!:BjTmJu\C!<)<o!:K7Tmd:)CmJu\C!<)<c!;5ap!+Ll2Hc?$bp@d$hpAa!6
+PhtP\=oeQi!!)l`!!*#d*WYWr!:K7Tmd:)CmJu\C!:K7Tmd:)CmJu\C!:K7Tp$NOp@Z/KX`W,u3
+p=4fhs5'!)hWB`"!<2Ea!!2KfrpKdd"mu?jmd:)OmK3IWmK!7S!s%cW!;u6f!:BjT!<2Bi!:BjT
+mK!7SrrDc\'`_^$c$RG0s7Z0:KD,?%Pa(%eMcp,[mem.cmKN[ZmJu\C!<2Bd!<2Bd!<2Bi!:BjT
+mK!1Q!s%cW!:K7X`A+0Y.=_~>
+J&]WVlK\Dhs2P)Yk2tsklK/'XKu/,HqYKd>\p=#LhN<rOie\3HlK7@3lK7BolK/*/lK/*/!9WPH
+lK/*/lK/*/l2^,3!9O:DlK/*/!9WPHlK/*/lK7@3lK/*/l2^,3!9WPHlK7Bo!9WS/lK7BolK[Ns
+jo>sH_Ki`hqEa]/\p=#LhN<rOie\3HlK7@3lK7BolK7@3lK7@3lK/*/l2^,3!9WPHlK/*/l2^,3
+!9WPHlK/*/l2^,3lK7BorotHblK/'XKu/,HqYKd>\p=#LhN<rOie\3HlK7C0!'BHGlK7@3!9O7]
+lK/*/lK7BolK/*/l2^,3l2^,3!9WS/lK/*/!9O:DlK/*/!9WPHlK7@3!9WS/lK8*2)s6GJ!"ak$
+H+NkKo%ps'pAa!3Ok/NK&-2"XlMU]Dk3;s3joFQ/!:&_3!:&_3!:&_3!9sRLjoFQ/k3D(/k3;s3
+k3D*olK7BolK7BolK7BolK6*3b/Rk?~>
+FS>aRk2u]Ws1SHGhVRDOk2$)IK=#^$pAa9oP]QQuhNX8]hMYP;k2,5#k2,7Wk2$*pk2$*p!8ci<
+k2$*pk2$*pjoFQ#!8[_4k2$*p!8ci<k2$*pk2,5#k2$*pjoFQ#!8ci<k2,7W!8ckpk2,7Wk2o@o
+k2$)IK=#^$pAa9oP]QQuhNX8]hMYP;k2,5#k2,7Wk2,5#k2,5#k2$*pjoFQ#!8ci<k2$*pjoFQ#
+!8ci<k2$*pjoFQ#k2,7WroP0Vk2$)IK=#^$pAa9oP]QQuhNX8]hMYP;k2,7u!'B<Ck2,5#!8[\U
+k2$*pk2,7Wk2$*pjoFQ#joFQ#!8ckpk2$*p!8[_4k2$*p!8ci<k2,5#!8ckpk2-+")rB`6!+LSf
+F0,*8k/ER+pAa!6Pht8T=od^Ak5>9@hW=h#h>lEp!9W/#!9W/#!9W/#!9O:Dh>lEphWEYphW=h#
+hWE\Wk2,7Wk2,7Wk2,7Wk2*ejs7W7=~>
+%A]LSk2u]_s2G#WmdB6:mKESoMp6mnrr3T(h>mTUPii#GmYbNSk3hX;k5OcMk3`6KmK`g\!:JtL
+md:)SmK!=Uqu@N#!:K";!:BjTmJuD;jo>DLjoFi;!:Kab$h!0F!!)HTjo>DLk5OfKk5OcP!*Y<*
+K>mii)YW"fs8S>Gs8VMF@K>QYmJuD;mJm7TjoFi;qu?`bqu@c*joFQ3!:JtLmd:)CmJuD;!:K";
+!!)HTk3h["k5OcP!*Y<*K>mii,PKsos8S>Gs8VMF@K>QYmJuD;mJuALk3hX;jo>DL!!)HTk5OfJ
+!<;Hg!9W_I!!2NMrpCI#mJuYTmcNp;mJu\C!9W_;!9W_3rpKdJrpBpi>)UXX`W#lLp>,fLs-2[G
+s6beS!9W_;!9X:Kqu@DujoFi;k3`3LjoFi;joFNDmd:)Smf!1nmcFN;mcNs"mdB6:mJuDKmJuDK
+mKCKhS>7Ta~>
+6H[;rio:!Xs2P)Yk2t[cioU4LKt_i@qY'L:^&[m'Q/_iDie7d@io]5#io]7_ioU7'ioU7'!9W8@
+ioU7'ioU7'qu@Mp!9W;'!9O:DiW/!#iW&u@iW/!#!9X1Z2s0,^!!)$@iW&u@io]7_io9+[jo>gD
+^3R0`p@@(S!;?8SirB&<Ka[t@k2HC#k2H@@k2HC#k552Zk552tk2HC#joFQ'!93,@k2HC#joFQ'
+jo>D@k2PP&i\KZUjo>gD^3R0`p@@(S!;?8SirB&<Ka[t@k2HC#k2HC#!93/#!9*tYjo>D@k2PO_
+k5G>`k2HC#k553!k2PO_joFNDjoFQ'joFNDk2HC#k2HC#k2PO_k5O?_k2PM'%#)E@[ef^ghS'!`
+qN^(?s5J_@!93/#!93/#k552pk2HC#k2PM'!9+"<k2HC#!93,@k2PP&!#k"Z!93/#k2PC_io]7_
+io]7_io]7_`dPkL@=S~>
+$NKhEhVS:Gs1SHGqq`%f>(`o'XS2AU`KUB&s-2[Gs5&B;!<1gT!;kUQ!<1g\!8[_4h>lEh!<1gU
+!8dVR!T!hUh?<o9!8cQ4rndYTs5!kYhVJ7hquH`QrrE&TrrDfM'`_EiXF%&Bp?ona!<<(`k5YJ<
+K44i[h>dQThZ!TUh?!]6hY[?RhY[BRh@BVCh>lEh!8cQ4hVJ7hh>mQ3rrDfM'`_EiXF%&Bp?ona
+!<<(`k5YJ<K44i[h>dQTh?!]6!<1gZ!8[\Uh>dQQhYmNTh?!]6hY[BOh?3i8!8[_Th?<o9!8cQ4
+rn[VTp"gD`>(`o'XS2AU`KUB&s-2[Gs5&B;!<1gT!<(dP!<:mU!<(dS!!1pVrn[eYh>lEh!<1jS
+!<:mU!:J\H^!69NS:C~>
+$_4"ImdC+os2G#Wk5F]PjoAS;c$RG/rr_rpK)kiL"6PMF!<2Ed!<;I4k3hX;mdB3;mJuD;!:JtL
+mdB3;md:)Ck3hX;k3hX;joFi;!;u6j!:BjTjoFi;!<2Bdk5F]K!9X:K!!*#d!9X7J#3GnhK?\b^
+rr3)o!.t:Lrr_DA=oeQirrE)e$K_?VmJu\;mJu\;rpBadrpCE]mJu\C!9W\LmcFN;mJu\C!9X7J
+!<D9YmKVeR>(b(H`W#l>p&K^Fr;Ql]Mcp,[mJm7dmK*CV!<2Bl!:Bgejo>DLk5OcQ!:K7Tmd:)S
+mJm7dmJuDKmLJ@Z!:K7Tk3hX;joFi;!<2Bdk5=WIk5=WOjoAS;c$RG/rr_rpK)kiL"6PMF!<2Bd
+!<2Bfk3`6KmKD\?!:K"KmM=pb!:K";!:BjTjoFi;!:K7Tk3`6;k5F]Jk5OcKk5OcKk5OcPk/B'N
+S1/s~>
+*QH6Ik2u]`s2P)Yio9+[k2H@HJ\HE<p@dq2!-nSBs'ac<"9@TDjo>D@k2PO_!93/#!9+"<joFQ'
+!93/#!93,@k2PO_!93/#!9+"<joFQ'k2PM'joFQ'!93,@k2PO_k2PO_!93/#joFQ'k2POcio]5#
+#_B^8[eBF_h>hg$r;S_4K`hD<ioU4@io]5#ioU7'ioU7'io]7_!9W;'ioU7'iW/!#!9W8@ioU7'
+iW/!#io]5#io]8"jq$J6iW'78^3R0\p?pc;Gl[dB8)Aq&!9W;'!9W;'!9O:DioU7'!!)!Y!9W;'
+ioU7'iW/!#!9W;'!9W;'io]7_iW&u@iW/!#iW.s<ioU7'io]7_io]7_ir8'Nio]5##_B^8[eBF_
+h>hg$r;T4BK`hD<ioU7'io]7_!9W;'ioU7'io]7_iW&u@ioU7'!9W8@ioU7'iW/!#!9W;'io]C_
+k2PO_k2PO_k2PO_`d,_H@=S~>
+$MOM=hVS:Gs1SHGqq__]>'m>lV!d[5`;jrZr;QlUK3A9ShZ!TRh>dQTh?X,<!8cQ4hVJ83h?*c7
+h>mN2!!*#T"T[BZhVJ81h?X,<!8cQ4hVJ8.h>dQSh>dQNh@'BfH`V:amdB5V!-8/<rr_,1=oeQY
+rrE&T!s%37!<1gT!;t[R!;t[a!8cQ4hVJ7hh>lEh!8cQ4r8%DRptcDZ>'m>lV!d[5`;jrZr;QlU
+K3A9Sh>dQTh?!]6!<1gZ!8[\Uh>dQRh?Eu:h>lEh!<1gT!;YLO!<:mU!<1gY!8[_4h>m*&$ijIX
+XE13*mcMIgErc.<"5\Z6!<1gT!;t[R!;t[R!;kXQ!<1gb!8[_4h>lEh!8cQ4hVJ8#h?:O2s7W7=~>
+(8RH\k2u]_s2G#WmdB6*k3`4IMp6mfrr3)ohL"tors.\==od^Qk3i-I!Uf+L!!26Mr;[,cmJu\;
+mJm7Lr;Zldk5G>]k3i0J!TrhL!!hrS!9W\LmcOHJ!Uf+L!!26MrW!Jsk3hC"k2u*omJp.Cc%E_/
+rr_uOHhRC;#NgYB!9W_3med%gmcFN3mcOHJ!Uf+K!"SGZ!!)EemcFN3mJu\;mf!1emcOKK"6T%6
+mf)>SmcNp;;N&eP^&J$6p>1/ir;R5gK3A9;mcFN3mcFN3mf!1omcFN3mJm7LmcNs"qu?l^!9W_3
+r;[/lk3hC"joFQ3k5G>]k3i0J$0L[<!9W_3mcNs:jp:D;mJp.Cc%E_/rr_uOHhRC;%-E1G!9W_3
+!9W_3mcOHJ"n(LQk3hC2!!26MrW!2kjoFQ3!:K"I!#ao!k3hC"k2u*omcNs"mcNs"mcNrV3Lllo
+J,~>
+$HgA:io:!Xs2P)Yqr/%b"G+:4[eB:_hR\"#pAOgihLPe0rSm_Ts5O"Xs5NtWs5F"Yro3qX!93qW
+s5O"Xs5NtWs5O"Xs5F1^io0stir&lWir/rXir/rPiXGkjJ\HE<p@@e2\p<`;rV?WQJHPuOiqrfV
+iW&uXir&lWir&lWir8u`iW.ut!92u<ro3nWs5O"XpYlV^"G+:4[eB:_hR\"#pAOgihLPe0ro*nX
+ro*tZio9q;s5F.]io0q<r8RVS!TF+Yir&lSiW&uXir/rXir&lViW&uOiXGkjJ\HE<p@@e2\p<`;
+rV?WQJHPuPiW&uVir&lWiW&uXir/rXir/rXiWT>AiW.utqu?cW!:JhL`dPkL@=S~>
+.f]4ee^a]5s1SHGhVQf>e_U:(K<0-imdB5VP]Q9ds7ZKmhKrE+e_\j5qu?cSec#OLe_^6)#h@c3
+hUUH_!7h#J!T)B+!!1X,r;ZlKhYmK[hUMVVh>lE_r;ZlTec#OLe_^9*,Mpu-e_\j,hUUH_;M2&l
+V!d[5`KYH3pAajds5&*+!7frVhY[?WhUMVVhUVQ)!T)B*!"Rl9!!(jUhUMVVh>lE_hYmKUhUVT*
+"4c8YhYu%LhUUH_;M2&lV!d[5`KYH3pAajds5&*+!7frV!7frV!7fs*!"7Z6!7fp+!7frVhUVN(
+"P!M&hUVQ)$/X4he_\gVe_\jU!!1X,r;[/ShUMVVhUUK5hYu%KhUUH_;M2&lV!d[5`KYH3pAajd
+s5&*+!7frV!7frVhUVQ)"l@c0e_\jU!!1X,rW!2[eH".V!8c9(!#a;ee_\j5e^`O,hUUK5hUUK5
+hUUJrc1_1-J,~>
+*Lro[mdC+os2G#Wk2u*omcFLIK?^cfec5@:eH#%8s'ac:;?6.ImcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs*k3h@3
+;M36$Ph#g-p=002r;S_4K2M^;k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+joFQ3k3hC"k3hC2mLSIJjoA;3c*W_cs7Z0:!:Kdb8)Akr!:K";k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3`6;k3hC"k3hC"k3hC"k3hC"k3hC"k5OcZk3h@3;M36$Ph#g-
+p=002r;T4BK2M^;k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3h["
+mcNs"mcNs"mcNs"`A+0Y.=_~>
+$HC56io:!Xs2P)Yqr7VU'7IHgJ]@9KhRW^Lo()MFp==Wl!3kJ_!#'dlV1HYWmbYMTk48*:o(LX_
+!!(X1!!)TLrr<^\\tstto'YAG!9WkCp@@q.I/j8siW&u?ir8ulICc8+`q&QS\cCm`o(MYJepRMu
+`8Up>H-4-8J,~>
++85`RhVS:Gs1SHGe^`O,hUMU(H`WHH[-$5aMZD;ik5OdYc$N=ghUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hVQf>
+eGrKoXH[J,k2+(8!7g5orpD_iHVsk#e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5eH".Ve_\j5e_\jUh@\;peGrKoXH[J,k2+(8!7g5orpE;$HVsk#e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5!8c8_e_\j5e_\j5e_\j5e_\j5e_\jUh@\;peGrKo
+XH[J,k2+(8!7g5orpE5"HVsk#e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_]05hUUK5hUUK5hUUK5]uC$FUjr~>
+$Da1Pk2u]_s2G#WqrS:e;M2s=XJFDHp&KF>r;QlUHVsjJjpV5fK>lBBUt,M=!.+_Drr_,);?5G5
+rW)KN$ij1X`RV&cec5=CHN=!D"5\B&!7g33!9E8N!)eHgeZ>Rss7QG>!;uj!hKr-#`9%3A3Lllo
+J,~>
+$HgA:hVS:Ps2P)Yqqh>Q'7I=+TomLgh>hg$lL+*2o$Vd`!3k>[!#'dh_P*+7o%j@l!:'"?o((4S
+!!(a0rW)KFrr<^\[_e`#b4=BhGl[-tmdfqsGlRiph>dQ:hZ!QhIC@"dOim7O!-nS0mdBZ:dWkfm
+`81X:IE'E<J,~>
+$NKhEe^a]5s1SHGqpcD];L>4HMgMhn`;jrZhWE\Wk/DC>!3jug!)e0>[#9:<k/@=A!8ckpk2sX(
+;?5G$rW)K='`_-YUpQ&,[-#=-Erb(ZhWEt>F&E"geGoU1eJ/'^H_e$,HaMqS!-8.sk2,7_`H+oW
+`75"(c1_1-J,~>
+$CmnHk2u]_s2G#WqrS:e8opNAc*X:sp=4fXrq6N`eXUtP!3kSo!(q=&`Qbcceb7OGk5P&Xma[hS
+5lesf$iin@SAia[Ut,1hKBE1,"n'p2HU.Y@jpV5^F.C4o[%u7GeV!#`p''m7S9mO%`9%3A0r1<g
+J,~>
+$HC56hVS:Ps2P)Yqq`%f#]Z!8^87+7hR\!`io]O__NcMT!3k;p!!mS,[_AT'`nn:Pf&GiWhSPO+
+#QVp%'`\MZOg`!#Q,_[lH.M!;lJBCC-jTg^hA$"rEKR]DV3T'W\p;ldk3Cg?Ppcn<`81X:H-4-8
+J,~>
+%JKh@hVS:Gs1SHGe^`OUeJ8-WC4i=`MgMhMMfZk^c.1(GK6'<YhYu%*hYu%,hUUK^eH"J*eH"J*
+eH"J*eH4UXhYu%*hYu%*hYu%*hYu%,hUUK^eH"J*eH"J*eH"J*eH4UXhYu%*hYu%*hYu(*hYu%@
+!(q!YUo]K$[)IrE`QcZXc*W+E5lfd@eH"J*eH4UXhYu%*hYu%*hYu%*hYu%,hUUK^eH"J*eH"J*
+eH"J*eH4UXhYu%.hUU05hYu%@!(q!YUo]K$[)IrE`QcZXc*W+E5lfd@eH"J*eH4UXhYu%*hYu%*
+hYu%*hYu%,hUUK^eH"J*eH"J*eH"J*eH4UXhYu%*hYu%*hYu%*hYu%,hUUK^ec+G)eJ8-WC4i=`
+MgMhMMfZk^c.1(GK6'<YhYu%*hYu%,hUUK^eH"J*eH"J*eH"J*eH4UXhYu%*hYu%*hYu%*hYu%/
+hUUK5e_^;U!8d_*!8d_*"MMeSp8!3~>
+&YtpWmdC+os2G#Wk2u*omcNs:!"E\5['ZXZeU-HHk/EigrW#jYmcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mdB6*
+k3i3K%;ME?[%u7&HfjbY`LKj*!&Wj+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC2mK;V>k3i3K%;ME?[%u7&HfjbY`LKj*!(>u;k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC2mK;V>k3i3K%
+;ME?[%u7&HfjbY`LKj*!(,i9k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k
+3hC"k3h["mcNs"mcNs"mcNs"`AsHa.=_~>
+$HgA:io:!Xs2P)YqVqJS%2>)(TolptH-Xjd[Zq!p!3Y>\!"BX-V4j$_\p;TLd^GDDrW'psrW!BA
+Q)11:]"314daGRh"TAD/ir/oe'U>MgOh/,LcI1.LPm%'d_r:g=IE'E<J,~>
+$ifqFhVS:Gs1SHGec">*e_^9*#@`=MK6*QIF8iNJUl.kE!!(RKh>l+*h>l+(h>l+*h>l+*h>l+*
+h>l+(h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+)h>u0`rW!14K9V"0
+S<S*oZi[%]9)\ejec+D*ec+D*ebn8(ec+D*ec+D*ec+D*ebn8(ec+D*ec+D*ec+D*ebn8(eb\,'
+e_^9*#@`=MK6*QIF8iNJUl.kE!!(RKh>l+*h>l+(h>l+*h>l+*h>l+*h>l+(h>l+*h>l+*h>l+*
+h>l+(h>l+*h>l+*h>l+*h>l+(h>l+(h>u0`rW!14K9V"0S<S*oZi[%]9)\ejec+D*ec+D*ebn8(
+ec+D*ec+D*ec+D*ebn8(ec+D*ec+D*ec+D*ec">)ec+D*ec+D*ec+D/e\06$s."T~>
+$CmnHmdC+os2G#WrU'[JrpCE]mJm5rMkllMK@Rr!C&e8%mcON:!9X:K!9X4I!9X:K!9X:K!9X:K
+!9X4I!9X:K!9X:K!9X:K!9X4I!9X:K!9X:K!9X:K!9X4I!TrhG!<2Bdk5Oc]k3`3L@Z.%P["HoJ
+MeW4lmdB6:mJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmK2P=meHk^mJuDKmLn[M
+!!$JdUn"fEe]!G]!!)HTk5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5=WIk5OcKk5OcKk5OcKk5=WI
+k5OcKk5OcKk5OcKk4o#VmJuDKmLn[M!!$JdUn"fEe]!G]!!)HTk5OcKk5OcKk5=WIk5OcKk5OcK
+k5OcKk5=WIk5OcKk5OcKk4nuWk5OcKk5OcKk5OcQk3g2CUmrla~>
+$HC56k2u]`s2P)YpZDJU$P8#WNLb@/Y)*hm!4h7f!;P^V!"0?lQ&V>[^93;,!!(C.q#L3Prr<E<
+Kp@XgH+pG<'EA-Kk4o#Pk5PDh&;?C/SU%rPM%fpif&lc.oB$1qH-4-8J,~>
+$MOM=hVS:Gs1SHGpYPoM$X.UuF*htuP]L:6!4gt^!;PFN!"2tOHZOOTS<S)(!!(C&q#L3Hrr<F1
+F*htTF.AJ9@K6DDhY@0HhZ!Q`>'#%3HZP^AF(,+Lf&$3&oA0V``W,Y-J,~>
+(8RH\p@eO*s2G#WmdBf:p?qYBp?qYBrW!%8K6qtE!(lnPp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBq#LHg#k%ESp?qYB
+p?qn[")<I8Hi="#p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYM!<;`ume6)Bme6)Bmf!1gC4gk[rW#:Yme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6GVs7Q`dp?qYBp?qYBrW!%8K6qtE!%dj3
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYM!##"np?qYBp?qYBp?qYB
+`AsHa.=_~>
+$HgA:lK\Dhs2P)Yp$2MV!u,m'*<#rIlM1GRlM^bc'Qn[@rW(7/q#L-RrW!$7Fa4u+!5@ao!;>^W
+!!<pXGoZe`eEZi0oBHIuIE'E<J,~>
+%fc7Ik2u]Ws1SHGk2,7WroO4;roO4;rW!$u@WP`P!<2*\hYuX;hYuX;hYuX=hWE\ojoF9;joF9;
+joF9;joXE%hYuX;hYuX;hYuX;hYuX=hWE\ojoF9;joF9;joF9;jojQ'hWEtr!<;0]hYuX;hYuX;
+hYmKW;IX]NrW)r[!8d_;!8d_;!8d_;!oE(rroO4;roO4;roO4;roO:=k2-+"!8d_;!8d_;!8d_;
+q#LHW!8d_;!8d_;!8d\T"&`TL>5eO$joF9;joF9;joF9;joXE%hYuX;hYuX;hYuX;hYuX=hWE\o
+joF9;joF9;joF9;joXE%hYuX;hYuX;hYuX<hWFV6s5j=<roO4;roO4;rW!$u@WP`P!<2*\hYuX;
+hYuX;hYuX=hWE\ojoF9;joF9;joF9;joXE%hYuX;hYuX<hWFV6roO4;roO4;roOIBk2sA%pA^Y5~>
+"Iu8BmdC)J!:KgZ!:Kj[!:Kj[!:Kj[#4;HkK)kW5rq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[
+!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[qZ$]kmdC)J!:Kj[
+!:Kj[#4;HkK)kW5rq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[
+rq6B\pA4gkp?qAJp&OO[p&OO[p'0pb!.t:Fmf)n[mf)n[mf)n[mf)n]me6)Jp&OO[p&OO[p&OO[
+p&a[Umf)n[mf)n[mf)n[mf)n]me6)Jp&OO[p&OO[p&OO[pA4jhmf)n[mf)n[mf)namJm6>!;>j[
+p&OO[p&OO[p&OO[p&a[Umf)n[mf)n[mf)n[mf)n]me6)Jp&OO[p&OO[pA4glme6ABrq6?[rq6?[
+rq6K60r1<gJ,~>
+!liB.lL+ZP!A"5Wme["Tmf*7f/-*i\qZ-3Trr<'N!4qUq!:oRX!!+VNd-gc2o'QY#H-4-8J,~>
+!quZ5lK8*H!HS7Ik5,/Lk5PD^EraAFqZ-3Lrr<(@!4q=i!:o:P!!.-@d,t3*o&^(g`W,Y-J,~>
+Co!R]s8VfmpAajdp@eO[s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZBk9E4_cs7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds8;otpAY(npAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdr;Zikrr5:Xs7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds8;p3
+pAb0ds7ZKds7ZKds7ZKd`AsHa.=_~>
+!m8N2Qh((T[IX7rV=OQb]CPn#naZh&IE'E<J,~>
+!rqu=rU'[JrpBdKrU'[JrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdK
+r9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aXKmdC#R!Uf+KmJuDKmJuDKmJuDKmJuDI
+mJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDKmem._mJuDKmJuDK
+mJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDKmJuDKmJuDKmJuDImJuDK
+mJuDKmJuDKmK)J<r;Zi[r9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdKrpBdKr9aRIrpBdKrpBdK
+rpBdKr9aRIrpBdKrpBgLmem.bmJuDKmJuDKmJuDKmKMadc1_1-J,~>
+!h?&@rr2ulrr2ulrVllkrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ul
+r;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr3,p!!*&mrVllkrr2ulrr2ulrr2ul
+r;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Zcss8N)mrr2ul
+rr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ulr;Qcjrr2ulrr2ulrr2ul
+r;Qcjrr2ulrr2ulrr2ulrr;uu!;??j!;?El!;?El!;?El!;??j!;?El!;?El!;?El!;??j!;?El
+!;?El!;?El!;??j!;?El!;?El!;?ElrrE&u!;?El!;?El!;?El#58)90r1<gJ,~>
+!liB.QM1=YZhFD!U\=]f\b?%'nFd")H-4-8J,~>
+!quZ5QL=bQZgRhnU[J-^\aKItnEpFm`W,Y-J,~>
+!i2>HJcC<$M>m^t3LlloJ,~>
+!m8N2JbjroM>@@pIE'E<J,~>
+"on;@p@dqRp''mXp?qYBrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[
+rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:KgZ!:Kj[
+!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[
+rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[
+!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMr:U-Yrq6?[rq6?[
+rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[!q,dMrq6?[rq6?[rq6?[rq6E]p?qqR!:Kj[!:Kj[!:Kj[
+!:KgZ!:Kj[!:Kj[#O_<Z^!69NS:C~>
+!h?&@JcC<$M>m^t0r1<gJ,~>
+!liB.JcC<$M>m^uH-4-8J,~>
+!quZ5JbFZgM=q(c`W,Y-J,~>
+!i2>HJPq%sM,FKV3LlloJ,~>
+!m8N2JQ78$M,a]YIE'E<J,~>
+!rqu=JPq%sM,FKVc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;Z6Uq!<)ot!;QQr!<<'!JcC<$T`5*SS>7Ta~>
+"3SW3<W2pt!<)ot!;QQr!<<'!JcC<$T`5+B`l__?~>
+"98)>;Z6Uq!<)ot!;QQr!<<'!JcC<$T`5,=pA^Y5~>
+".Z/A;Z6Uq!<)ot!;QQr!<<'!JcC<$T`5*KUmrla~>
+"3/K/<W2pt!<)ot!;QQr!<<'!JcC<$T`5+>b/Rk?~>
+"8;c6;Z6Uq!<)ot!;QQr!<<'!JcC<$T`5,5s7W7=~>
+"/MGI;Z6Uq!<)ot!;QQr!<<'!JcC<$T`5*SS>7Ta~>
+"3SW3<W2pt!<)ot!;QQr!<<'!JcC<$T`5+B`l__?~>
+"98)>;Z6Uq!<)ot!;QQr!<<'!JcC<$T`5,=pA^Y5~>
+".Z/A;Z6Uq!<)ot!<3#t!<3!#!<<'!rr;rtJcC<$VZ-`QUmrla~>
+"3/K/<W2pt!<)ot!<3#t!<3!#!<<'!rr;rtJcC<$VZ-aDb/Rk?~>
+"8;c6;Z6Uq!<)ot!<3#t!<3!#!<<'!rr;rtJcC<$VZ-b;s7W7=~>
+"/MGI;Z6Uq!<)p3!<<'!s8N'!s8N*!rrE*!!<<'!!.k0$s/5l!3LlloJ,~>
+"3SW3<W2pt!<)p3!<<'!s8N'!s8N*!rrE*!!<<'!!.k0$s/5l!IE'E<J,~>
+"98)>;Z6Uq!<)p3!<<'!s8N'!s8N*!rrE*!!<<'!!.k0$s/5l!c1_1-J,~>
+".Z/A;Z6Xm!<<'!!<3!)!<<'!s8N*!rrE&u!!%TMJcDYJ"#6UA.=_~>
+"3/K/<W2sp!<<'!!<3!)!<<'!s8N*!rrE&u!!%TMJcDYJ"*r&/@=S~>
+"8;c6;Z6Xm!<<'!!<3!)!<<'!s8N*!rrE&u!!%TMJcDYJ"3(<6Ujr~>
+"/MGI;Z6Uq!<)ou!<;ors8N9's8N*!rrE&u!!%TMJcDYJ"$)mI.=_~>
+"3SW3<W2pt!<)ou!<;ors8N9's8N*!rrE&u!!%TMJcDYJ"+A23@=S~>
+"98)>;Z6Uq!<)ou!<;ors8N9's8N*!rrE&u!!%TMJcDYJ"3pQ>S:C~>
+".Z/A;Z6Uq!<)p"!<<'!qu6j#s8N*!rrE&u!!%TMJcDYJ"#6UA.=_~>
+"3/K/<W2pt!<)p"!<<'!qu6j#s8N*!rrE&u!!%TMJcDYJ"*r&/@=S~>
+"8;c6;Z6Uq!<)p"!<<'!qu6j#s8N*!rrE&u!!%TMJcDYJ"3(<6Ujr~>
+"/MGI;Z6Uq!<)p"!<<'!qu7-+s8N*!rrE*!!!*'!!!%TMJcDeN"$)mI.=_~>
+"3SW3<W2pt!<)p"!<<'!qu7-+s8N*!rrE*!!!*'!!!%TMJcDeN"+A23@=S~>
+"98)>;Z6Uq!<)p"!<<'!qu7-+s8N*!rrE*!!!*'!!!%TMJcDeN"3pQ>S:C~>
+".Z/A;Z6Uq!<)ot!<3#s!<<'$!<<'!rr;rtrr;uuJcC<$X8`8VUmrla~>
+"3/K/<W2pt!<)ot!<3#s!<<'$!<<'!rr;rtrr;uuJcC<$X8`9Ib/Rk?~>
+"8;c6;Z6Uq!<)ot!<3#s!<<'$!<<'!rr;rtrr;uuJcC<$X8`:@s7W7=~>
+"/MGI;W.QT!.k0$s/Z/%3LlloJ,~>
+"3SW3<T*lW!.k0$s/Z/%IE'E<J,~>
+"98)>;W.QT!.k0$s/Z/%c1_1-J,~>
+".Z/A;W7WU!.k0$s/Q)$0r1<gJ,~>
+"3/K/<T3rX!.k0$s/Q)$H-4-8J,~>
+"8;c6;W7WU!.k0$s/Q)$`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"lErr<&srr<%Ms-N`f3LlloJ,~>
+"3SW3<It2Hrr<&srr<%Ms-N`fIE'E<J,~>
+"98)>;M"lErr<&srr<%Ms-N`fc1_1-J,~>
+".Z/A;M"lErr<&srr<%Ms-N`f0r1<gJ,~>
+"3/K/<It2Hrr<&srr<%Ms-N`fH-4-8J,~>
+"8;c6;M"lErr<&srr<%Ms-N`f`W,Y-J,~>
+"/MGI;SE)1!5JO6!;uis!.k0:rrY9OUa^f~>
+"3SW3<PAD4!5JO6!;uis!.k0:rr[\hb$ff~>
+"98)>;SE)1!5JO6!;uis!.k0:rr^O>s."T~>
+".Z/A;Z?[r!<)p!!<<)u!<2uu!<3!"!<<)u!;ulq!<<)u!<3!!!<;ors8N0$rr<&urr<&urrE-"
+rW)uurW)rtrW)lrr;cltrW)rt!<E0!!;ulq!<<'$!<3$!rVuisrVuisrr30&s8N*!rr@WMQi@.B
+Umrla~>
+"3/K/<W<!u!<)p!!<<)u!<2uu!<3!"!<<)u!;ulq!<<)u!<3!!!<;ors8N0$rr<&urr<&urrE-"
+rW)uurW)rtrW)lrr;cltrW)rt!<E0!!;ulq!<<'$!<3$!rVuisrVuisrr30&s8N*!rr@WMQi@/5
+b/Rk?~>
+"8;c6;Z?[r!<)p!!<<)u!<2uu!<3!"!<<)u!;ulq!<<)u!<3!!!<;ors8N0$rr<&urr<&urrE-"
+rW)uurW)rtrW)lrr;cltrW)rt!<E0!!;ulq!<<'$!<3$!rVuisrVuisrr30&s8N*!rr@WMQi@0,
+s7W7=~>
+"/MGI;Z6V)!<<'!s8N*!rr<'!rrE&u"9AK%!!)rsrrE#t(]aU9!!*'!!!*'!!<<'!s8N'!rr<'!
+rrE&u%KQP/!<<'!s8N'!s8N'!r;Zcsq>U["s8N'!s8N)srr<&ss8N'*rr<'!rrE*!!!)or"T\T&
+!<3&urr<%Ms-N`f3LlloJ,~>
+"3SW3<W2q,!<<'!s8N*!rr<'!rrE&u"9AK%!!)rsrrE#t(]aU9!!*'!!!*'!!<<'!s8N'!rr<'!
+rrE&u%KQP/!<<'!s8N'!s8N'!r;Zcsq>U["s8N'!s8N)srr<&ss8N'*rr<'!rrE*!!!)or"T\T&
+!<3&urr<%Ms-N`fIE'E<J,~>
+"98)>;Z6V)!<<'!s8N*!rr<'!rrE&u"9AK%!!)rsrrE#t(]aU9!!*'!!!*'!!<<'!s8N'!rr<'!
+rrE&u%KQP/!<<'!s8N'!s8N'!r;Zcsq>U["s8N'!s8N)srr<&ss8N'*rr<'!rrE*!!!)or"T\T&
+!<3&urr<%Ms-N`fc1_1-J,~>
+".Z/A;Z6V"!<<'!s8N)urrW9$rrE&u!s&B$!;lcr!;uis!<3!#!<<'!rr30&s8N*!rrE&u!s&B$
+!<3!&!<<'!s8N)urrW9$rrDrr!!)fo!s&B$!<2uu!;uis!;uis!<3!#!<<'!rr2ruqu6g"s8N*!
+!<2uu!.k0:rrY!OS1/s~>
+"3/K/<W2q%!<<'!s8N)urrW9$rrE&u!s&B$!;lcr!;uis!<3!#!<<'!rr30&s8N*!rrE&u!s&B$
+!<3!&!<<'!s8N)urrW9$rrDrr!!)fo!s&B$!<2uu!;uis!;uis!<3!#!<<'!rr2ruqu6g"s8N*!
+!<2uu!.k0:rr[Ph`aOA~>
+"8;c6;Z6V"!<<'!s8N)urrW9$rrE&u!s&B$!;lcr!;uis!<3!#!<<'!rr30&s8N*!rrE&u!s&B$
+!<3!&!<<'!s8N)urrW9$rrDrr!!)fo!s&B$!<2uu!;uis!;uis!<3!#!<<'!rr2ruqu6g"s8N*!
+!<2uu!.k0:rr^7?p8!3~>
+"/MGI;Z6V"!<<'!s8N)urrW9$rrE&u!s&B$!;lcr!;uis!<3!#!<<'!rr30&s8N*!rrE&u!s&B$
+!<3!$!<<'!s8)frrr<&rrr<&rs8;rtrr<&urr<&rs8N)urr<&urrE-"qZ-Wqr;cltrrE#t!!%TM
+Qi@.JS>7Ta~>
+"3SW3<W2q%!<<'!s8N)urrW9$rrE&u!s&B$!;lcr!;uis!<3!#!<<'!rr30&s8N*!rrE&u!s&B$
+!<3!$!<<'!s8)frrr<&rrr<&rs8;rtrr<&urr<&rs8N)urr<&urrE-"qZ-Wqr;cltrrE#t!!%TM
+Qi@/9`l__?~>
+"98)>;Z6V"!<<'!s8N)urrW9$rrE&u!s&B$!;lcr!;uis!<3!#!<<'!rr30&s8N*!rrE&u!s&B$
+!<3!$!<<'!s8)frrr<&rrr<&rs8;rtrr<&urr<&rs8N)urr<&urrE-"qZ-Wqr;cltrrE#t!!%TM
+Qi@04pA^Y5~>
+".Z/A;Z-Rp!<2uu!<3!#!<<'!rr3'#s8N)rrr<&srr<&urrW9$rrE&u"p"]'!<<'!rr3'#s8N)u
+rrrK'rrE*!!;lcr!;lcr!;uis!<3!#!<<'!rr2ruq>UNss8N)urrW9$rrDrr!!*#u"T\T&!<3%M
+s-*Hb0r1<gJ,~>
+"3/K/<W)ms!<2uu!<3!#!<<'!rr3'#s8N)rrr<&srr<&urrW9$rrE&u"p"]'!<<'!rr3'#s8N)u
+rrrK'rrE*!!;lcr!;lcr!;uis!<3!#!<<'!rr2ruq>UNss8N)urrW9$rrDrr!!*#u"T\T&!<3%M
+s-*HbH-4-8J,~>
+"8;c6;Z-Rp!<2uu!<3!#!<<'!rr3'#s8N)rrr<&srr<&urrW9$rrE&u"p"]'!<<'!rr3'#s8N)u
+rrrK'rrE*!!;lcr!;lcr!;uis!<3!#!<<'!rr2ruq>UNss8N)urrW9$rrDrr!!*#u"T\T&!<3%M
+s-*Hb`W,Y-J,~>
+"/MGI;Z-Rp!<3!.!<<'!!<<'!s8N'!s8N)rs8N)trs&Q(rr<'!rrE&u(BFL8!<<'!s8N'!s8N*!
+rr<'!rrE*!!;lcr!;lfr!<)ot!<3!#!<<'!rr2ruq>Ud%s8N*!rr<'!rrDrr!!*#u"p"]'!<3$!
+JcCu7"$)mI.=_~>
+"3SW3<W)ms!<3!.!<<'!!<<'!s8N'!s8N)rs8N)trs&Q(rr<'!rrE&u(BFL8!<<'!s8N'!s8N*!
+rr<'!rrE*!!;lcr!;lfr!<)ot!<3!#!<<'!rr2ruq>Ud%s8N*!rr<'!rrDrr!!*#u"p"]'!<3$!
+JcCu7"+A23@=S~>
+"98)>;Z-Rp!<3!.!<<'!!<<'!s8N'!s8N)rs8N)trs&Q(rr<'!rrE&u(BFL8!<<'!s8N'!s8N*!
+rr<'!rrE*!!;lcr!;lfr!<)ot!<3!#!<<'!rr2ruq>Ud%s8N*!rr<'!rrDrr!!*#u"p"]'!<3$!
+JcCu7"3pQ>S:C~>
+".Z/A;Z-Rp!<)rs!<3#t!!N<%s8N)qs8;rts8E#trr<&urriE&rrE*!r;cisrW!3'!<<'!!<<)t
+!<<'!!;c`o!!*&r!!3*"rr2rur;Z`rrr;osrVufrs8Vrr#QFf(rr<'!!.k0:rrY!OS1/s~>
+"3/K/<W)ms!<)rs!<3#t!!N<%s8N)qs8;rts8E#trr<&urriE&rrE*!r;cisrW!3'!<<'!!<<)t
+!<<'!!;c`o!!*&r!!3*"rr2rur;Z`rrr;osrVufrs8Vrr#QFf(rr<'!!.k0:rr[Ph`aOA~>
+"8;c6;Z-Rp!<)rs!<3#t!!N<%s8N)qs8;rts8E#trr<&urriE&rrE*!r;cisrW!3'!<<'!!<<)t
+!<<'!!;c`o!!*&r!!3*"rr2rur;Z`rrr;osrVufrs8Vrr#QFf(rr<'!!.k0:rr^7?p8!3~>
+"/MGI;Z-Op!7CfH!65$=!.k0$s8;m!3LlloJ,~>
+"3SW3<W)js!7CfH!65$=!.k0$s8;m!IE'E<J,~>
+"98)>;Z-Op!7CfH!65$=!.k0$s8;m!c1_1-J,~>
+".Z/A;Z-Op!7CfH!65$=!.k0$s8;m!0r1<gJ,~>
+"3/K/<W)js!7CfH!65$=!.k0$s8;m!H-4-8J,~>
+"8;c6;Z-Op!7CfH!65$=!.k0$s8;m!`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+"/MGI;M"k!s,$aX3LlloJ,~>
+"3SW3<It1$s,$aXIE'E<J,~>
+"98)>;M"k!s,$aXc1_1-J,~>
+".Z/A;M"k!s,$aX0r1<gJ,~>
+"3/K/<It1$s,$aXH-4-8J,~>
+"8;c6;M"k!s,$aX`W,Y-J,~>
+!i2>HJcC<$M#RQ;S>7Ta~>
+!m8N2JcC<$M#RR*`l__?~>
+!rqu=JcC<$M#RS%pA^Y5~>
+!h?&@JcC<$jo;.M"#6UA.=_~>
+!liB.JcC<$jo8`Zmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:H-4-8J,~>
+!quZ5JcC<$jo;.E"3(<6Ujr~>
+!i2>HJcC<$jo8`Vp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB3LlloJ,~>
+!m8N2JcC<$jo8`Vo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):IE'E<J,~>
+!rqu=JcC<$jo8`NmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"c1_1-J,~>
+!h?&@JcC<$jo>ASWrN%k"#6UA.=_~>
+!liB.JcC<$jo5GRme6L[rsAPqmdff:H-4-8J,~>
+!quZ5JcC<$jo>AKrUs"dpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb*brU'd,s7W7=~>
+!i2>HJcC<$jo5DMp@eFas6`D>mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs8jpCJLp?qYB3LlloJ,~>
+!m8N2JcC<$jo8`Vo()MJs8)<Ok2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2+tShW!\co'Z):IE'E<J,~>
+!rqu=JcC<$jo5\MmdBf:s7Ym;hUVV^!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*
+!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*r7),1k3hC"k0<W"S:C~>
+!h?&@JPq%sk#)BFp?qA2p9Xc#mcNC)k5P&V0r1<gJ,~>
+!liB.JQ78$k#D]Lmc*BglMCP\rq]XgqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'XFhU^Q;hW!tknp/Bt@=S~>
+!quZ5JPq%sk#)6Bmf)&Ek4\iPp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[pAaO^hUTmLec+t=`W,Y-J,~>
+"/MGI;M"k!s6'F]k5O5CrrV?>ec"A)mK5J>Ua^f~>
+"3SW3<It1$s6'C_k2-'j!;?Bk9`"ecs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)HOf$aNN"mYN(`l__?~>
+"98)>;M"k!s6'C^k5<a4me6\Ss1%b3mbZ45e]lXpk2sq^s."T~>
+".Z/A;M"k!s6'Cdk2,7_e_^#*rsRu>e`P`=hX3+oS1/s~>
+"3/K/<It1$s6'Cdk0hu;damuqrs\VXdaI"+cJ%]3b/Rk?~>
+"8;c6;M"k!s6'Cdk0;H,c->\QrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDcj
+rrDcjrrDclrse\ie]l@he]lY4`W,Y-J,~>
+"/MGI;M"l?rr<%Ms7QBnk0<&feH#<KrrDKdeHasUc/q$VUa^f~>
+"Nn`4<W@X,p"fZKJcGEC#Nj%[da$;/qR$82p?'ZGdb;^`idJhh@=S~>
+"TS2?;ZD;holC*5JcGEC!p72Hrl#*(me6ASpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquo
+rq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6KppAaR;rl#,m]uAjQpA^Y5~>
+".Z/A;M"l?rr<%Ms7QBrk/H3-c.26frsS8Fc.1sq^#h&FS1/s~>
+"NJT0<W@X,p"fZKJcGEC#j/kTd`0`#pA25t%JoeXcGn;d^:rTPb/Rk?~>
+"SVl7;ZD;holC*5JcGEC#3N;Cc+VBarUr_\pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb*b$f8k9c.027hSoNgUjr~>
+"/MGI;M"lGrr<&srrN3#!.k1CrrV>ihYtb"med(`s82l`s82l^rr<&jrrMi]rlk])[(Y<VS>7Ta~>
+"Nn`4<W@X,rS@MSr8%JTh>i-,p&>6YZI[18b3&U%rVHElm/$V[lM:J\o_K$jo&e*3b1<l0hL3Dd
+@=S~>
+"TS2?;ZD;hrGqr=r,Vo>Er^dkp&>6YUs6ll^#&Yerq6?[qu?fdp?qqR!q,dMrq6E]p?qqR!q,dM
+qu?`brq6E]p?qqR!q,dMrq6E]p?qqR!q$'Vrq6E]p?qqR!Uf[\mL.mb]uA6l[+3Fps."T~>
+".Z/A;M"lGrr<&srrN3#!.k1Crs%VehTa$i!;ulq!;uis!<)otpAFpjpAFpppAb-ms8VfjrrDcj
+rrDcjrrDcjrrVoo!<2uupAFpjpAY*lp'^$5`Qd8@^#h&FS1/s~>
+"NJT0<W@X,rS@MSr8%JTh>i-,p&>3XV:*N#b4,I)o(MYJo(MYJo(MYJo(MYJo(MVSo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJ!;?!Wo(MYJo(MYJo(MYFhTERTd\XP3H-4-8J,~>
+"SVl7;ZD;hrGqr=r,Vo>Er^dkp&>3XUs6lc`UNp/me6YJ!qu'UrpBj]me6YJ!qu$^rpBj]me6YJ
+!qu'UrpBj]me6YJ!qu'UrpBj]!;?E[!qu'UrpC?kme6):e]"o7c(q`'`W,Y-J,~>
+"/MGI;SW53!5JO6!;uiu!<3%Ms7QBrk+(;I`Q\DSs%EFmpAajdpAajdpAajdpAajdpAY-mpAajd
+pAajdpAajdpAajdpAajdpAajdpAagdpAajdpAajdpAajdp@dq:c,IZYSA!c>S>7Ta~>
+"Nn`4<WBkk!!'dj!!)rR!W_'WJcGEC$0IN$_S4"i!<<)p!<<*!!:KCX!9NbO!;#aimbYst_U=^\
+hL3Dd@=S~>
+"TS2?;ZFOR!!'cT!!)q<!W[9AJcGEC$0IJs]sPHQ!<<)p!<<*!!:K7T!9NVK!;#Uek1./P^!2eK
+e]mgfS:C~>
+"e;AC;Z?aqrrN3#s8E#trr<&urrN3#s8E#rs8;rts8E#trrE-"qZ-Zr!s&?$!<2uu!<3!!!<<#u
+s8W&urr;rtr;Z]qs8W&urr3!!s8E#rs8;rtrrW9$!!)utrW)osrW)rt#QXo)!<<'!rr@WMp&>?\
+Ph"$lblIcI>5A3u=onX'me6Y\qt:*lp&G*kpAP'jpAP'kp&b<gp&OdZ$g,^Ic./&ljtW[%.=_~>
+"ie]1<W<'th?!]6hYmNSh>dQTh?!]6hYmNQhYdHShYmNSh>mW5qZ-ZQ!s%0X!<1gT!<1gU!8d\T
+s5*_TrndVSr8.APs5*_Trn[YUhYmNQhYdHSh?*c7!!)uSrW)oRrW)rS#QW`<!8cQ4h>i-,p&>?\
+Oj_7\`W-!A=o&*t=oSKimf*:amK3IW!!)ucrW)obrW)rc!s%cW!;Gp]l3l=c]#N0\]&%_T`aOA~>
+"nqu8;Z?aqErl>_F8c1=ErZ4>Erl>_F8c1;F8Z+=F8c1=Erc8^qZ-Y;!s!BB!<.$>!<.$?!-A,>
+s)\/>rcA&=r,_f:s)\/>rc8)?F8c1;F8Z+=EruD`!!)t=rW)n<rW)q=#QSpe!-<2]Er^dkp&>?\
+MoEB:]`8%9>5A3u>5nRHk3hC"k3hC"k3hC"k3hC"k3h@3!:K";k3h@3jo>DLk3hC2!!DBOk3i3K
+*q&1Y!:JtLk3hC"k3hC"k3hBoe\/?'c&8sc`W,Y-J,~>
+';V-Y;ZHass8N*!rrE*!!!*'!!<3!$!<<'!!;uls!<)p7!<<'!!<<'!!<<'!s8N*!rr<'!!!*'!
+!<3!.!<<'!s8N*!rr<'!rr<&ss8N)prs&Q(rr<'!rrDus!!)rsrr<B*!!*'!!<<'!!;ld"!<<'!
+rrE&u!W`6#JcGEC!p5-crl#&t!<<(&>5eL$>6"U;!:KRKp?qYBp?qYBp?qYBp?qYBp?qn[-1:Kp
+p&G*\!!)`\!:KO\!:KRKp?qVSp?hqK!:KRKp?qYBp?qYRmL/0r]uAi\^"tc>Ua^f~>
+'?\=C<WCnUhVJ7hh>lEh!!(m4!<1gX!8cQ4!;t^R!<(ak!8cQ4!8cQ4!8cQ4hVJ7hh>dQ4!!(m4
+!<1gb!8cQ4hVJ7hh>dQ4h>dQRhZ!TOh?O&;h>dQ4h>mK1!!)rRrr<A^!!(m4!8cQ4!;kUV!8cQ4
+h>mQ3!W_'WJcGEC$g*/k_RdV<!!*%%=oJC#=T\U'!:9"M!<)3_!"%oj!:&hLlKS?Lqs"=blKSB7
+!;5Uck1[\`_U=.LhL3Dd@=S~>
+'E@dN;ZCe<F)q>&Er^9&!!%(]!<.$B!-<2]!;pp<!<$sU!-<2]!-<2]!-<2]F)q>&ErZ2]!!%(]
+!<.$L!-<2]F)q>&ErZ2]ErZ4<F8l79EsD\dErZ2]Erc,Z!!)q<rr<@H!!%(]!-<2]!;gg@!-<2]
+Erc2\!W[9AJcGEC$g)f\]sPK'!!*%&>5eL$=p=p+!8ckproO:=k2-+"!oE(rroO:=k2-(;+Pu8;
+jo>D<!!)0D!8ci<!9WG#k2,5#k2$*p!9WG#k2-+"&DlR+k2+Y%[(X_2[+3Fps."T~>
+%%O+J;ZHass8N*!rrE&u!s&B$!<3!#!<<'!qu6Wrr;Q`srr3'#s8N)urrrK'rrE*!!<3!#!<<'!
+rr30&s8N*!rrE&u!s&B$!;lcr!;QQr!<<'!rr2rur;Q`sr;Q`srr3'#s8N)urr<&rrriE&rrE'!
+rr3$"rr@WMp&>9ZK@S5[c/&I!s8?."rr<&smJuDImJuDImJuDImf*:dmKWaSmd:)CmK!7S!W_ZN
+rU'mjk3`6;!:K"ImJuDKmLA=HhT`aYeUtQt0r1<gJ,~>
+%*$G8<WCnUhVJ7hh>mQ3!s%37!<1gW!8cQ4qq_;Qr8%DRrn[_WhVJ83h?Eu:h>lEh!<1gW!8cQ4
+rn[hZhVJ7hh>mQ3!s%37!;kUQ!;PCQ!8cQ4rn[VTr8%DRr8%DRrn[_WhVJ83h>dQQh?<o9h>lC4
+rn[\Vh>i-,p&>6YJ^VQL`n(+hs8W%#s8W&u9]k?sio]7_io]7_io]7_io]7_io]7_!!)$@iW/!#
+iW/!#!9W;'!9W;'io]5#ioU7'!9W;'io]7_io]7_io8P/]#N0L]&%_T`aOA~>
+%/0_?;ZCe<F)q>&Erc2\!s!C`!<.$A!-<2]qf;`;r,Vi<rc8/AF)q?\Es;VcEr^9&!<.$A!-<2]
+rc88DF)q>&Erc2\!s!C`!;gg;!;LU;!-<2]rc8&>r,Vi<r,Vi<rc8/AF)q?\ErZ4;Es2PbEr^7]
+rc8,@Er^dkp&>6YHd072^!6NVs8W%$s8W&ulJDO@rn[VTrn[_WhVJ83h>dQQh?<o9h>lC4o\Ku#
+]sPJlHaMYKs7W7=~>
+%&BCR;ZHass8N*!rrE&u!s&B$!<3!#!<<'!qu6Wrr;Q`srr3'#s8N)urrrK'rrE*!!<3!#!<<'!
+rr3*$s8N*!qZ-Zr!!)or!!)orr;clt!!*#u!!)orrrE&u!!*#u!<E/s!<3#s!<<*!!<)p!!<3%M
+s7QBtk&]Cu]uAjj!;HL<!:K";k3hC"k3hC"k3hC"k3hC"k3hC"k3`3Lk3`6;k3`6;qZ$][mcOHJ
+'(4l^!:K";k3hC"k3hC"k3hBgrl#,mF1pEjS>7Ta~>
+%*HS<<WCnUhVJ7hh>mQ3!s%37!<1gW!8cQ4qq_;Qr8%DRrn[_WhVJ83h?Eu:h>lEh!<1gW!8cQ4
+rn[bXhVJ7hqZ-ZQ!!)oQ!!)oQr;clS!!*#T!!)oQrrE&T!!*#T!<D!R!<1jR!<:pU!<(aU!8[^,
+s7QBsk&o+h]#*%Tr;cfrr;c'@rrE)Y!!*#X!<D-V!<2!V!<;'Y!;,7ZhU]QT_U<S<hL3Dd@=S~>
+%0-%G;ZCe<F)q>&Erc2\!s!C`!<.$A!-<2]qf;`;r,Vi<rc8/AF)q?\Es;VcEr^9&!<.$A!-<2]
+rc82BF)q>&qZ-Y;!!)n;!!)n;r;ck=!!*">!!)n;rrE%>!!*">!<@3<!<.'<!<7-?!<$s?!-8-k
+s7QBsk%`/J[(X`7r;cfrr;\%ue_\j5e_\j5e_\j5e_\j5e_\j5e_\j5!!(R+!8c8_!8dSQ!nH/X
+r;[kpeGoU+e_\j5e_\j5e_\j5e]ke7[*<?me]mgfS:C~>
+".Z/A;Z?^r!<2uu!<3!#!<<'!rr3'#s8N)rrr<&srr<&urrW9$rrE&u"p"]'!<<'!rr3'#s8N)u
+rrrK'rrE*!!;lcr!;lcr!;uis!<3!#!<<'!rr2ruq>UNss8N)urrW9$rrDrr!!*#u"T\T&!<3&s
+rr<%Ms7QBuk&](t^!5ErjoG5W!!)0D!s%KG!<2*_!9WDDqrRkYroO@ak2l[+!;,C]hT`aYeT8Fd
+0r1<gJ,~>
+#fb#4<WCq4!!*#T!!*#T!s%37!<1gW!8cQ4qq_;Qr8%DRrn[_WhVJ83h?Eu:h>lEh!<1gW!8cQ4
+rn[hZhVJ7hh>mH0!!)oQ!!)rR!!*#T!s%37!<1gT!;YIR!8cQ4rn[_WhVJ80h>dQTh?<o9h>lC4
+r8%DRJcGEC#j-!P`k'%<hVRu,:?(-ihW!DOhW!DOhW!DOhW!DOhW!DOhW!DO!92i8hW!AlhVnOp
+hW!DOh>lElh>lEl!9+"<hW!DOhW!DOhW!DKf###<dVZSPH-4-8J,~>
+#kn;;;ZCfZ!!*">!!*">!s!C`!<.$A!-<2]qf;`;r,Vi<rc8/AF)q?\Es;VcEr^9&!<.$A!-<2]
+rc88DF)q>&Erc)Y!!)n;!!)q<!!*">!s!C`!<.$>!;U[<!-<2]rc8/AF)q?YErZ4>Es2PbEr^7]
+r,Vi<JcGEC#j,m@]sPJthUV?#:>XOXe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5!8c6+e_\gVe_U;_
+e_\j5eH".VeH".V!8[_4e_\j5e_\j5e_\j5c+U3lc"aWB`W,Y-J,~>
+"/MGI;Z?^r!<3!.!<<'!!<<'!s8N'!s8N)rs8N)trs&Q(rr<'!rrE&u(BFL8!<<'!s8N'!s8N*!
+rr<'!rrE*!!;lcr!;lfr!<)ot!<3!#!<<'!rr2ruq>Ud%s8N*!rr<'!rrDrr!!*#u"p"]'!<3$!
+rVlitJcGEC!p3tBrl+oo"6SG?!<)rt!)Mb6k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wjo>D<joFQ#
+!!)0<!8ckpk2,5#k2,5#k2$*p!!)0<k2,7Wk2,7Wk2+t6]uAi;^"tc>Ua^f~>
+#g1/8<WCq4!!*#T%KPAB!!(m4!8cQ4!8cQ4qqh>QrS@bZhVJ54hVJ83hA61Kh>lEh!8cQ4!8cQ4
+hVJ54hVJ7hh>mH0!!)oQrrE#S!!*#T!s%37!<1gT!;YIY!8cQ4hVJ54hVJ80h>dQTh?Eu:h>lC4
+!<(aS!.k1Crs@grd_`T0f%T!;q#EY9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>2f0g>2hdg&M-0
+g&Tj`g>:Q?!8cGd!8cE0g&M-0g>:Q?g>:Q_h@/,h^:M20@Ck<D`l__?~>
+#ljVC;ZCfZ!!*">%KLQk!!%(]!-<2]!-<2]qfDc;rGr2DF)q<]F)q?\Eu+gtEr^9&!-<2]!-<2]
+F)q<]F)q>&Erc)Y!!)n;rrE"=!!*">!s!C`!<.$>!;U[C!-<2]F)q<]F)q?YErZ4>Es;VcEr^7]
+!<$s=!.k1Crs@gkc+UKkc-=ehq#EY0c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.)doc.)gEbl@ao
+blH#=c.1(h!7f?E!7f<obl@aoc.1(hc.1)<ec3noZj=@i>-ui)pA^Y5~>
+".Z/A;Z?^r!<)rs!<3#t!!N<%s8N)qs8;rts8E#trr<&urriE&rrE*!r;cisrW!3'!<<'!!<<)t
+!<<'!!;c`o!!*&r!!3*"rr2rur;Z`rrr;osrVufrs8Vrr$3(#*rr<'!!<3%Ms7QC"k$llc^!5Er
+hWE\Wr;[\kk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wqu?fTk2-%:"6SJ&hYdETk2,t8*9I7`h>dQ<
+hWE\WhWE\WhWE\>^!5):^#h&FS1/s~>
+#fb#4<WCq4!!)uSrW)rSrW!)X!8cQ4qVM/Ns5*_Trn[VTrn[eYhVJ7hhYdHRhYmK[h>lEh!!(m4
+r;clS!!)lPr;ZiSqZ$ZR!<1gT!;t^Q!<1jR!<(dQ!<:pQ!"%K^hVJ54h>lC4JcGEC$g(aC`k'%8
+g=kE;hYdEkg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?gACpPg>:Q^!!D*3hV.o.!T)Q-!$'hqhV%r0
+hV-i?hV-i?hV-]3_Rdb8?+Sm<b/Rk?~>
+#kn;;;ZCfZ!!)t=rW)q=rW!(B!-<2]qK)T8s)\/>rc8&>rc85CF)q>&F8Z+<F8c.EEr^9&!!%(]
+r;ck=!!)k:r;Zh=qZ$Y<!<.$>!;pp;!<.'<!<%!;!<7-;!"!]HF)q<]Er^7]JcGEC#3K+6]sPJt
+r71`GkgfS2rmgrIrRLiHs4-uH"k<V'eGoUCeI0X8[(X^f[,/e%p8!3~>
+"/MGI;Z?[r!7CfH!65$=!9O4\!.k1Cs'b%fhTa$YhVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,5#k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WhSmIYhGV&D
+3LlloJ,~>
+#Kk&7<WCq4!7BX'!63jq!9N&;!.k1Crs%Ucf#GG@db!1Q!8Z?:f##/@elB<<IE'E<J,~>
+#QOMB;ZCfZ!7>if!60'[!9J8%!.k1Cs'b%fc+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lVEe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhc+UKtbu1q!
+c1_1-J,~>
+".Z/A;Z?[r!7CfH!65$=!9O4\!.k1Crs%U`hUTTiec+\OhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWFV61#;oek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wc,J5i;SD3IUmrla~>
+#KFo3<WCq4!7BX'!63jq!9N&;!.k1Cs!Qr&f$;.Pdb`^7g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>;W*1"lW]hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i;`kp$P9Y0)+b/Rk?~>
+#PS2:;ZCfZ!7>if!60'[!9J8%!.k1Crs%UXc,IB0c/@.J!!1UMh:2nX]sPc'9!mHos7W7=~>
+"/MGI;M"l?rr<%Ms7QC!k!@kSc,JPrk2,8"h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9
+h>l^9h>l^9h>l^9h>l^;h@8W(hTa<qhEej33LlloJ,~>
+"Nn`4<W@X,p"fZKJcGEC#j+P+cGm`Lg>99l%Gogib/V`\7(V6'`l__?~>
+"TS2?;ZD;holC*5JcGEC@HKl#`P&t0c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(`]tMD86+#1epA^Y5~>
+".Z/A;M"k!s6'Cfk$$$dc.1A$hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9
+hYcL9hYcL9hYcLDhUU05bu27;0r1<gJ,~>
+"3/K/<It1$s6'Djk#KRTb0&/dg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?hW!87cIU-3]&%_T`aOA~>
+"8;c6;M"k!s6'Cdk#01C`Pp*.eI:<Zc,IrH9!mHos7W7=~>
+!i2>HJ`_OGjlQehXPVgae_]0\joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9;jojQ'k3hC2h?U,k^#h>FUa^f~>
+!m8N2J`_OGjlQefWnPnHcIU_KhGr:dg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>_,ShU^-/Y$JWqIE'E<J,~>
+!rqu=J`_OGjlQehUt*`/`QcZ:ec+D5e]l@hUft.^c1_1-J,~>
+!h?&@JcC<$jo5Cq;U,3t!nH/a\)n.fp?q)*eP_=EhD(gr.=_~>
+!liB.JcC<$jo5Ut9Zkr;daH_#\)%SRmcNB_c:ir+hKd8`@=S~>
+!quZ5JcC<$jo5Ch9#^eS!l`F/\((rEk2+Y=`Cbcre]%R^Ujr~>
+!i2>HJcC<$jo5PYMb:)$hWFgo<p&9$hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEtgk2*I;C:)7R3LlloJ,~>
+!m8N2JcC<$jo5SVNC9Vgf%S]ag&U"/iX48>885BPk'b7l@=S~>
+!rqu=JcC<$jo8`VMb9eac.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1A$hT_ig@][Q2c1_1-J,~>
+!h?&@JcC<$jo5SRp:Y2q.4I"L.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%
+.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.K;+/;M2?ihX3+oS1/s~>
+!liB.JcC<$jo8`Vo!W*d/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/2U@\ZG,&XH-4-8J,~>
+!quZ5JcC<$jo5JGm^-FXYUKo6;M2'ae`OjNp8!3~>
+!i2>HJcC<$jo>>R"7G<r`N[#]`QdQ5p,SY=.=_~>
+!m8N2JcC<$jo5PUmdfZ"b/1Bo#f=a@lLKACb$ff~>
+!rqu=JcC<$jo>>J?0:"_]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJlhWF7NpA^Y5~>
+!h?&@JcC<$jo8`Vp?qYBmb[*_k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WmdBf:0r1<gJ,~>
+!liB.JcC<$jo5MPo'Yr2k-!PGk3DC&H-4-8J,~>
+!quZ5JcC<$jo8`NmcNs"k1/>=hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5k2u*o`W,Y-J,~>
+!i2>HJaS*WM!b@*S>7Ta~>
+!m8N2JaS*WM!b@n`l__?~>
+!rqu=J`_OGLunfapA^Y5~>
+!h?&@JaS*WM!b@"Umrla~>
+!liB.JaS*WM!b@jb/Rk?~>
+!quZ5J`_OGLunfYs7W7=~>
+!i2>HJaS*WM!b@*S>7Ta~>
+!m8N2JaS*WM!b@n`l__?~>
+!rqu=J`_OGLunfapA^Y5~>
+"Iu8BmdAe,!<7W<JaTi3"#6UA.=_~>
+"NJT0mdAe/!<7W<JaTi3"*r&/@=S~>
+"SVl7k2tAq!<7W4J`a9#"3(<6Ujr~>
+"f.YKmd=!-mK!9<mXaf3mK5J>Ua^f~>
+"j4i5md=*0mK!9<mXaf3mK7mWb$ff~>
+"on;@k2oRrjoGF4k(2[#jo`m%s."T~>
+"e;ACmd=!-mK!9<mXaf3mK52>S1/s~>
+"ie]1md=*0mK!9<mXaf3mK7aW`aOA~>
+"nqu8k2oRrjoGF4k(2[#jo`U&p8!3~>
+"f.YKmd=!-mK!9<mXaf3mK5J>Ua^f~>
+"j4i5md=*0mK!9<mXaf3mK7mWb$ff~>
+"on;@k2oRrjoGF4k(2[#jo`m%s."T~>
+#+VJDmd=!@quH*O!!)c]!<7W<JaTi3"#6UA.=_~>
+#0+f2md=*CquH*O!!)c]!<7W<JaTi3"*r&/@=S~>
+#58)9k2oS(quH*G!!)cU!<7W4J`a9#"3(<6Ujr~>
+#GdkMmd=!@!<2Ed!:B1S!;Gm]s+0Thm]u6_3LlloJ,~>
+#Kk&7md=*C!<2Ed!:B1S!;Gm]s+0Thm]u6_IE'E<J,~>
+#QOMBk2oS(!<2-\!:AnK!;GUUs+0<`k-F+Oc1_1-J,~>
+#FqSEmd=!@!<)<c!:B1S!;Gm]s+0Thm]u6_0r1<gJ,~>
+#KFo3md=*C!<)<c!:B1S!;Gm]s+0Thm]u6_H-4-8J,~>
+#PS2:k2oS(!<)$[!:AnK!;GUUs+0<`k-F+O`W,Y-J,~>
+#GdkMmd=!@!<)<c!<2Ec!<)?b!<)?a!!2KfrU'XcrpBddJaS*WZL.fTS>7Ta~>
+#Kk&7md=*C!<)<c!<2Ec!<)?b!<)?a!!2KfrU'XcrpBddJaS*WZL.gC`l__?~>
+#QOMBk2oS(!<)$[!<2-[!<)'Z!<)'Y!!23^rT4([roO4\J`_OGZK;86pA^Y5~>
+#FqSEmd=!@!<2Ed!<;Hi!:K7T!;l0n!:K7T!:K7Tmd:)CmK!4R!<7W<JaTi3"#6UA.=_~>
+#KFo3md=*C!<2Ed!<;Hi!:K7T!;l0n!:K7T!:K7Tmd:)CmK!4R!<7W<JaTi3"*r&/@=S~>
+#PS2:k2oS(!<2-\!<;0a!9WDD!;kmf!9WDD!9WDDk2l[+joGAB!<7W4J`a9#"3(<6Ujr~>
+#,IbLmd=!@r;cfa!!*#d!!)oa!s%cW!<2Bj!:K7Tmd:)RmK!9<mXaf3mK5J>Ua^f~>
+#0Or6md=*Cr;cfa!!*#d!!)oa!s%cW!<2Bj!:K7Tmd:)RmK!9<mXaf3mK7mWb$ff~>
+#64DAk2oS(r;cfY!!*#\!!)oY!s%KG!<2*b!9WDDk2l[BjoGF4k(2[#jo`m%s."T~>
+#FqSEmd=!@!<2Bf!:K:P!<2Eb!<;He!<2Bj!:K7Tmd:)RmK!9<mXaf3mK52>S1/s~>
+#KFo3md=*C!<2Bf!:K:P!<2Eb!<;He!<2Bj!:K7Tmd:)RmK!9<mXaf3mK7aW`aOA~>
+#PS2:k2oS(!<2*^!9WG@!<2-Z!<;0]!<2*b!9WDDk2l[BjoGF4k(2[#jo`U&p8!3~>
+#GdkMmd=!@!<2Ed!<;He!;l0a!<2Bg!:K7TrpBadrpKddr9aRbJaS*WZL.fTS>7Ta~>
+#Kk&7md=*C!<2Ed!<;He!;l0a!<2Bg!:K7TrpBadrpKddr9aRbJaS*WZL.gC`l__?~>
+#QOMBk2oS(!<2-\!<;0]!;kmY!<2*_!9WDDroO1\roX4\r8n"ZJ`_OGZK;86pA^Y5~>
+#FqSEmd=!@!<)<f!:K7TqsFFarpC!kmd:)CmJm7dmf*:dmK*CVs+0Thm]u6_0r1<gJ,~>
+#KFo3md=*C!<)<f!:K7TqsFFarpC!kmd:)CmJm7dmf*:dmK*CVs+0Thm]u6_H-4-8J,~>
+#PS2:k2oS(!<)$^!9WDDqrRkYroOFck2l[+jo>D\k5PG\joPPFs+0<`k-F+O`W,Y-J,~>
+#GdkMmd=!@!<)?c!<;Kc!<;Ka!<;Ke!!2KfrpKddrpBgfmf.k+JaTi3"$)mI.=_~>
+#Kk&7md=*C!<)?c!<;Kc!<;Ka!<;Ke!!2KfrpKddrpBgfmf.k+JaTi3"+A23@=S~>
+#QOMBk2oS(!<)'[!<;3[!<;3Y!<;3]!!23^roX4\roO7^k5U"pJ`a9#"3pQ>S:C~>
+"e;ACmd=!4mJm7amK!9<mXaf3mK52>S1/s~>
+"ie]1md=*7mJm7amK!9<mXaf3mK7aW`aOA~>
+"nqu8k2oS$jo>DYjoGF4k(2[#jo`U&p8!3~>
+"f.YKmd=!4mJm7amK!9<mXaf3mK5J>Ua^f~>
+"j4i5md=*7mJm7amK!9<mXaf3mK7mWb$ff~>
+"on;@k2oS$jo>DYjoGF4k(2[#jo`m%s."T~>
+"e;ACmd=!-mK!9<mXaf3mK52>S1/s~>
+"ie]1md=*0mK!9<mXaf3mK7aW`aOA~>
+"nqu8k2oRrjoGF4k(2[#jo`U&p8!3~>
+"f.YKmd=!-mK!9<mXaf3mK5J>Ua^f~>
+"j4i5md=*0mK!9<mXaf3mK7mWb$ff~>
+"on;@k2oRrjoGF4k(2[#jo`m%s."T~>
+"Iu8BmdAd.JaS*WZL.fLUmrla~>
+"NJT0mdAd.JaS*WZL.g?b/Rk?~>
+"SVl7k2t@sJ`_OGZK;8.s7W7=~>
+!i2>HJaS*WM!b@*S>7Ta~>
+!m8N2JaS*WM!b@n`l__?~>
+!rqu=J`_OGLunfapA^Y5~>
+"JhPs@VYmOrFu=Arb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrbDFA"DVDAS2#N~>
+!QrFYV1GXtWfsI[V#nfZ@=S~>
+"98)gmf)n[mXb(_p5enNme6ASp8!3~>
+!M#taF8]hRF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnUF)#Ig@KN'q.=_~>
+!QN:\Xok],WiCQOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)Wii@OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)DQ^"BWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA%rM9S8b$ff~>
+!quZ^rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6Wcp?qYBp@eNVJ,~>
+"f.Z'@VTZVEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEs$/uC23`W!i2>8J,~>
+"Nn`\V5f*LJZb$9s/Q'p!m8MkJ,~>
+!<7WDJbFil"7H3_Ujr~>
+$(Reh>$>BEC1:Y%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peIqiG-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@WcEpC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:XU>+DB;J,~>
+$-(,YTqS<ZWhlPAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lJ#]?FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV0/f7Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhlD[TuP5`J,~>
+$24Dep?qYBp?q?up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBJ+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmWJ6kp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp@eNVJ,~>
+"/MGb;Z0f!@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO<@Tm5E@Tlr5Ums/i~>
+!QrF\SUmJcToPfNV4F<Nb/Rk?~>
+#QOMkme6)BmeuhZmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[melb^me6)Kp8!3~>
+!M#tb8d&$a;G'Q2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8oIU";G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G-pd!h?&8J,~>
+"NJTLR?`>kJXMIb"eD'P`l__?~>
+!VZQmmJutZmJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mK3+MpAXL[p&Y2`J,~>
+$)F)eS>;[NS>;s1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NJ"3=)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUii3'S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;Z(J,~>
+$-L91`lc<D`lcGR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<DJ&]XNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb&t_H`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc;0J,~>
+$30`!pAajdpAb/BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds)n&8pAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAai^J,~>
+JLQ.!JLQ*~>
+JRO+<JRO'~>
+$(Rf]Un"6NUn!s)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NJ#&U1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS9:WtUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NJ,~>
+%%EndData
+showpage
+%%Trailer
+end
+%%EOF
diff --git a/doc/kmouth/kmouthmain.png b/doc/kmouth/kmouthmain.png
new file mode 100644
index 0000000..1b18f0b
--- /dev/null
+++ b/doc/kmouth/kmouthmain.png
Binary files differ
diff --git a/doc/kmouth/kmouthwizard.eps b/doc/kmouth/kmouthwizard.eps
new file mode 100644
index 0000000..5983d91
--- /dev/null
+++ b/doc/kmouth/kmouthwizard.eps
@@ -0,0 +1,4821 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: GIMP PostScript file plugin V 1.15 by Peter Kirchgessner
+%%Title: /local/src/kde32/kdeaccessibility/doc/kmouth/kmouthwizard.eps
+%%CreationDate: Sun May 30 14:53:50 2004
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%Pages: 1
+%%BoundingBox: 14 14 475 153
+%%EndComments
+%%BeginProlog
+% Use own dictionary to avoid conflicts
+10 dict begin
+%%EndProlog
+%%Page: 1 1
+% Translate for offset
+14.173228 14.173228 translate
+% Translate to begin of first scanline
+0.000000 138.472437 translate
+460.240758 -138.472437 scale
+% Image geometry
+1150 346 8
+% Transformation matrix
+[ 1150 0 0 346 0 0 ]
+% Strings to hold RGB-samples per scanline
+/rstr 1150 string def
+/gstr 1150 string def
+/bstr 1150 string def
+{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
+{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
+true 3
+%%BeginData: 335235 ASCII Bytes
+colorimage
+JcC<$JcC<$JcC<$JcC<$KE$H~>
+JcC<$JcC<$JcC<$JcC<$KE$H~>
+JcC<$JcC<$JcC<$JcC<$KE$H~>
+JcC<$JcC<$JcC<$JcC<$KE$H~>
+JcC<$JcC<$JcC<$JcC<$KE$H~>
+JcC<$JcC<$JcC<$JcC<$KE$H~>
+g]%?3[%r82[u1?QXMsmas2"^:hR')0MmnTHPcVjtJcEUe!oC;[JW%!q"-fn+p7))4~>
+g]%NDd`T;<]"Yn.]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi8@lOH^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:qJ0hYMg'_>ac*d`T;<]"Yn.]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi8@lOH
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:qJ0hYMg'_Z'l+d`T;<]"Yn.]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi8@lOH^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i
+^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:M%i^:qJ0hYN`AJ,~>
+f`)*Js7ZKmJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds$cY]pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAb0dJcE@^"SVlhs8RTBs7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZI]pAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7V$D
+]`/-.s7ZKmJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds$cY]pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAb0dR/_[~>
+h>[fLUk=SXMh?q?K7Af3Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh=TZK8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA7Mh?qGc%5o5rsA+hK8YA?K8YA7IuAr;K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K1UuRMh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?Y?K8YZ4JcE^h$1=UAMh?q?Mh?Y3Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?8W/4ZK8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K7f)7Mi5iMs*t~>
+h>[NHb(7./\cKP)JcE[g!V4Ba]!8gI^>a_D`W#u0b(7./\cKP)SH"*~>
+g])iuYkEYJ_>f)[YkEYJ_Z,2\YkFRdJ,~>
+hZ!r-Mh?q?Mh?q?Mi3(;Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?p\K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?Mh?q?Mh@hnJcEdj$I+K]Mh?q?Mh?qGItNZ3
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?MbA\\K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YY?Mh?q?V!`g6aSuUlMh?q?Mh?q?Mi3(;Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?p\K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?Mh?q?
+Mh@hnT)X<~>
+hZ!W5^4Eku\cKtEJcEdj!T(PA\urUFb4:,`aSu:t^4Eku\cKtET)X<~>
+h#@EKs8M]os7Z0drq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq?Blrq6Bmp4<7]rrMinrq6Hop@eOcp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+pAb0lp&Y3eJcE[g!VZQmp&k?gpAb-c!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l
+!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l
+!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l
+!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&l!<<&ls8W)l!WVk`s*t~>
+q>UNQ[&!)I"-iNZ]n(g:K*.&"s3:P$!/%S8".Z13p:UD,hR'*GMZ]4;s1Nu9X+LM4mf1Q2MZAC8
+MZ]KFc1\jN!oC;[m>D(2pA_gWK<'V,MsgViregc/ZASgTUs8W.s*t~>
+q>Vc+d`T;<]"Yni^:M%i^:M%i^:M%i^:M2Ts44ci]!f2Y]!f2Y[XYls]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!bGH[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roU
+]!f2Y]!f?Hs5LW$<5,rX]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi^:M>,iqC%b-0iq$^:q1m^:M%i^:M%i^:M%i
+^:M%i_Y4#\]!f2Y]!f2Y]!f%s]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y:qF*H[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^NcU]!f2Y^@qTd]"1kT]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Yni`ld<7^&KDDd`T;<]"Yni^:M%i^:M%i^:M%i^:M2Ts44ci]!f2Y]!f2Y[XYls
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!bGH[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roU]!f2Y]!f?Hs5LW$<5,rX]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi
+]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi]"Ybi^:M>,iqE0IJ,~>
+pAYj#s7ZKmpAajdpAajdpAajdpAaj[rr7QCWqQGlrUs(fpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7ZKd\,R09
+s7ZKmpAajdpAajdpAajdpAaj[rr7QCWqQGlrUs(fpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7ZKd\Gm9:s7ZKm
+pAajdpAajdpAajdpAaj[rr7QCWqQGlrUs(fpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7ZKdpA]X~>
+qu7W'Uk=SXMh?q?K8YA?K8YA?K8YA?K8YA?ec4KWK;jK,SH&VRMh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+K8YA?K8[_JrrBaMru:C%K8YA?K8YA7Mh?q?Mh?q?Mh?q?Mh?r<s5&<ZWInBEs8S=AK8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA7Mh?q?MoG\q!56>N)t'MSMh?q?Mh?Y?K8YA?K8YA?K8YA?K8\:[hLU<YK3FfF
+s-/FoMh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?Y?K8YA?`W#l;^&@t]~>
+qu6]fb3QVL^?5I\]!f2Y]!f2Y]!f2]J$uqs]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y\l,uJ[^roY[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^s&Y]!f2Y]!fWYs1Z(U^9>*K
+^>Akh!8>?j!V4D!\duO;s6@2(]!f2Y]!f2Y]"3C"]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f1J[^roY[^roY[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY]!f2Y]!f2Y`rH(Q
+]"5VZ\cKP%rr2uP`;]l/b3QVL^?5I\]!f2Y]!f2Y]!f2]J$uqs]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y
+]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y]!f2Y\l,uJ[^roY[^roY[^roY
+[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^roY[^s&Y]!f2Y
+]!fWYs1Z(U^9>*K^>Akh!8@DOJ,~>
+q>]aRrr<#l!<<&l!<<&l"98)gs8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8DWks8M]ms7ZHlrq6?lY4fO.lLt5Ws7QHm
+rq6?lrq6Hop@eOcp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-kp&P-lp&Y3err;uk!<94q^&RBkrr<#l!<<&l!<<&l"98)g
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8DWks8M]ms7ZHlrq6?lY4hYjJ,~>
+r;Rb]Mh?q?Mh?q?Mi34GK8YA?K8YA?K8YA?MuWg8JU=>B?HrMpH\6s/K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+Mh?q?Mh?q`pAb/W`W$q&Mh?q?Mh?q?Mi34GK8YA?K8YA?K8YA?MuWg8JU=>B?HrMpH\6s/K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?Mh?q?Mh?q`pAb/W`r@%'Mh?q?Mh?q?Mi34GK8YA?K8YA?K8YA?MuWg8JU=>B
+?HrMpH\6s/K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?Mh?q?Mh?q`pAb/Wrr7K~>
+r;QfS^?W9?^An5IZF7'IZF7'IZF7'EJ$uYkZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZ;S-:[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*3IZF7'IZF7'us5(&m[]R+D
+b4bl8_SuNUhS/9d&&/)D^9Y2Q[^*?I[^*?IZ@B<g[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^&f>ZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'E[^*?I[^*?Iir@l@
+]!e`P"NpH<s2)eU!T(QU\duOTs1YeIZF7'IZF7'IZEetgZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'I
+ZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7'IZF7&:[^*?I[^*?I[^*?I[^*?I
+[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?I[^*?IZF7'IZF7'I
+ZJto@ZF[KH\cg1Ls8Tt8s*t~>
+qYpTis8M]os7Z0drq6?lrq6?lrq6?lrq?BlJbH#8rr3)gp@eOcp&P-lp&P-lp&P-lp&P-lp&P-l
+p&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lp&P-lpAb0lp&P-l
+pAY'lp;?n2pAb-c"98)gs8M]ls8M]ls8M]ls8M`ls+0mApAY'ome6ASrq6?lrq6?lrq6?lrq6?l
+rq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq6?lrq?Bl
+rq6?lrq??k!;=A2!VZQmp&k?gpAb-c!<<&l!<<&l!<<&ls8RZDVtU,i"7GmVs8M]ls8M]ls8M]l
+s8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]ls8M]l
+s8M`ls8M]ls8M`krrDcls*t~>
+rVlr4K7!QL"+,[%hZ!3Lc(t>k!.4Wr"FIi^eT:_:#'5-DXJBT?rHeWMF.B?1HN8-dHN8-dHN8-d
+HN8-dHN8-dHiO-GHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-d
+HN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHiO-GHN8-dHN8-dHN8-dHN8-dHN8-dHN8-d
+HN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHN8-dHiO-GHN8-dHN8-cHN8-d
+HNeJ;MuVpdrIY)srdt<"K<3r/p&WF6rdt2trdto3K7hGBs7ZKds7ZKds7ZKdc%CXqrdt^*pAajd
+pAajdpAajdp<EMf%suRps7ZKds7ZKds7ZKdc2N=uMt[2N9#pr5]n:\1K*-IQXPWsM!R7G>K)g8r
+K*6P7s4)2iHNnP<K<1k`@f:WU>'$48rHeNcrd+Wdrd+Wdrd+Wdrd+Wdrd4\Fs*F`erd+Wdrd+Wd
+rd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wd
+rd+Wdrd+Wdrd4\Fs*F`erd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd+Wd
+rd+Wdrd+Wdrd+Wdrd+Wdrd+Wdrd4\Fs*F`erd+WdrHeNcrd+fiH].pdHi8QsHiAX"H\8EVrq6B;
+V#GuHHiAX3H\6sqpAajdpAajdpAajdp<A5BHiAX-c1_22s7ZKds7ZKds7X_8K+E=RpAajdpAajd
+pAajdp<ESh"H3!Rs%:B4!kj55rIY3!K<3r/p&WF6rdt2tr.>-!^&QW(rd+ijH\8DqC1@-g"'Tc9
+XSmJGF8gLdF8gLdF8gLdF8gLdF8gOds8REGF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLd
+F8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gOds8REGF8gLdF8gLd
+F8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gLdF8gOd
+s8REGF8gLdF8^FcF8gLiF*iiFk'R&Z!.4]t"+,[%hZ!3Lc(t>k!.4]t'RPIbc1_22s7ZKds7ZKd
+s7X]iK7!TM%aF_IpAajdpAajdpAaj2r.>N,c1_22s7ZKds7ZKds7X_:K*I8-s8P^ks*t~>
+rVm5U]!f2Y[^roYcKbE&%c5LB[^roY[^roY[atK@qm$>a!#/+`rNZQ_9G@IdlE^HiYHn3.]<_J:
+n?NS=s73>$]!f2Y]!f2Y]$BU?p.X>g]!f2Y]!f2Y]!gJhqY'dZqY'dZqY'dZhR^/(]!f3,pA4LZ
+pA4LZpA4LZp>3Bh]!f2YhY-g>qY'dZqY'dZqY&dW[^s'Ds8SA)rsI>g[^roU]!f2qlMgJehTi^@
+]!f2Y]!f2Yf)On0Z33,e'MOA^Z36"X'EC,XZN's.ZN's:ZN'soZ4F\LnufF4[^roY[^roYcKbE&
+9]"(+[^roY[^roY[bg`SpA4LZpA4LZpA4L>]!f&Y[^t>hqY'dZqY'dZqY'dZhR^/,[^rp(pA4LZ
+pA4LZpA4LZp>3Bh]"7V8s-:\*$J)es]!f&Y[^scLrq6iYcFUHq[^roY[^rous5s3a"?6Aq9Sr_R
+"Goed!''8Ls8T:.s8T^:s8VSo&&/)7Y-tpM]!f2Y]!f2qlMgKPhTi^@]!f2Y]!f2YhY-g>qY'dZ
+qY'dZqY&dW[^NcU]&*/WpA4LZpA4LZpA4L>]!f2Y]!gJhqY'dZqY'dZqY'dZhR^/,](Z1(Q2gl7~>
+r;ZTdqZ$<`rr;lh"B#4:C;p/F"N>*m!)i+Us8T:rs8T_)s8VQ]s8N)ep\+I`p\+1XqtBU\qtBU\
+rV$6j!:Il,q=a[bp\+Udqt:.j!#TIirUpB5C)?qKlLt8XYP/"r]Cu:)n+Qe]!:KUTqZ$<`o)JU\
+o)JU\o)J[^rr2uda8bu/qZ$<`rr;lh"B#4:C;p/F"N>*m!)i+Us8T:rs8T_)s8VQ]s8N)ep\+I`
+p\+1XqtBU\qtBU\rV$6j!q-*gJ,~>
+rr3GXK6r5tK7eNHc0kW*mf)>W`M@j5H\6ZtH\9TCV#59E;ZG#As5p+\>,:Tds3:R9qfDf;pN-B7
+s)\5?!s!EBs7g[8s7pa7s6at-rrR9As5S2#rrW7Bs8V,#s8W(>s8W+?rr;t=rr;G.s8N0$F8u:3
+Erk_/rd,$*H\6ZtH_epSs7Ym[jq#G,H\6ZtH\6Ztk5Y/Tp@eIQr8nB6K7eN'HfkA%s7Z0bmel2T
+H\6ZtH\:J\pAaj[rU0UG#^_2NK9ZE9]fF47%Fp)XK6r6'H_epSs7Ym[jp]5)H\6ZtH\6Ztc2XU;
+Et;1Kc2[h+Ufprtmf3=3s%<00s8Vh7s8W+?s8N0$F8u:8F8u:9F8c.,F8l1@F8u:#F8u7B!-A2?
+j)b8#rcA,>s)\2>rcA)=mrSO/!s!EBs7::4mf395$\NeYH\6[@c0kW*mf)>Z`M@j5H\6ZtH\:J\
+pAaj[rU0UG$[[MYH\6\-s7ZKdpAOFWjpQNgH\6Ztk5Y/Tp@eIQr8n93K6r68s8Tbmb5Vq$K6r5t
+K7eNHc0kW*mf)>W`M@j5H\6ZtH\9TCV#59E;ZG#As5p+\>,:Tds3:R9qfDf;pN-B7s)\5?!s!EB
+s7g[8s7pa7s6at-rrR9As5S2#rrW7Bs8V,#s8W(>s8W+?rr;t=rr;G.s8N0$F8u:3Erk_/rd,$*
+H\6ZtH_epSs7Ym[jq#G,H\6ZtH\6Ztk5Y/Tp@eIQr8nB6K7eN'HfkA%s7Z0bmel2TH\6ZtH\:J\
+pAaj[rU0UG$%%;OK9ZE9]fH+C~>
+rr2u\qR-RIhX:72mf)JPg;`rs#ibm,ZECL9Z??'F!t\mP&GuM]FgA0UY-P51s0Af5Y-P49Y-P51
+s0Ag-rrB5%s0Af5Y-P49Y-S*-Y-P49Y-P49rVmM5ZECL9ZECL9ZECL9ZECL9ZEF3,9s4NrZECL9
+ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZEF6-!3ZA%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9
+ZEF6-ZECM5s/r[,rrTL/ZMskQZECL9ZECL9ZECL9ZECL9ZEF6-!3ZA%ZECL9Y-P49Y-P49Y-RWu
+ZEj>8"ifEeqXX(Rl2fVYq6gdup@eO_p@@eBmcs*"lK\8T%dNc]s8)H[o'Yr2lK7BsqmI""p@eO_
+p@@eBmcs*"lK\>V"N(3=eqqNK!9X-d"ifEeqXX(Rl2fVYq6gRgs2qXMZECKUqu?g1@:^#J!&&K#
+Y-P49Y5eO-Y-P49Y-P49Y5eO-Y5eM%Y5eO-Y-P49Y-P49s8T7-Y-P49Y-S$+'!AOCZECL9ZECL9
+ZECL9ZECL9rr5]qs8TC-ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9s8N)%s8TC-ZECL9ZECL9
+ZECL9ZECL9ZECL9ZECL9ZECL9s8TC-ZN's-ZMsk*ZECM4s!b7VZECL9ZECL9ZECL9ZECL9s8N)%
+s8TC-ZEC@9Y-P49Y-P49o)H#$qR-RIhX:72mf)JPg;`rs%dNc]s8)H[o'Yr2lK7BsqmI""p@eO_
+p@@eBmcs*"lK\8T%dNc]s8)H[o'Yr2lK7BsrO)jGs8UZ,b5VJ(qR-RIhX:72mf)JPg;`rs#ibm,
+ZECL9Z??'F!t\mP&GuM]FgA0UY-P51s0Af5Y-P49Y-P51s0Ag-rrB5%s0Af5Y-P49Y-S*-Y-P49
+Y-P49rVmM5ZECL9ZECL9ZECL9ZECL9ZEF3,9s4NrZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9
+ZEF6-!3ZA%ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZECL9ZEF6-ZECM5s/r[,rrTL/ZMskQZECL9
+ZECL9ZECL9ZECL9ZEF6-!3ZA%ZECL9Y-P49Y-P49Y-RWuZEj>8"ifEeqXX(Rl2fVYq6gdup@eO_
+p@@eBmcs*"lK\8T%dNc]s8)H[o'Yr2lK7BsqmI""p@eO_p@@eBmcs*"lK\>V"iC<>eqsEW~>
+rVuWc!<<#k!:KUTs8W&k!q,c`qu?g9Mi/GM!!8timf)n_mf3=\mf)n[mf)ngmf3=\mf3:emf3=\
+mf)n[mf)q[s8Vcmmf)n\me6VZs7QH\rq6?[rq6?[rq6?[rq6?[rr3,hs8Vf\rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6Wcs8N)es8Vf\rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6Zds8Vf\pAb0\
+pAY*kpAY'mp?qqR!:Kj[!:Kj[!:Kj[#k%`m!:Kmep?qnQ!:Kj[!:Kj[s8N,nme?DTs8DWkme6AP
+rrMinrUp<\p?qeNr;Qfks8DWmme6)FpAFpkpAb*b!q,dMr:^-i!9VB&p\"UerUp6Zp\+XerUp<\
+p8n/l!uQrS)#O@8V"X6Up&sg`s7Ym[p&OO[p'gBhs7Ym\rrDKes7Ym[p&OO[pAb0mp&OO[p&XUT
+rVuok!:Kj[!:Kj[!:Kj[!:Kj[!:Kjd"Rc<ip?qqR!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[#k%`m
+!:Kmep?qqR!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[$1@inp?qYSs6fU[s8M`krrMi]rq6?[rq6?[
+rq6?[rq6Wcs8N)es8Vf\rUp6Zrq6?[rq?Bl!VYsUp&P-kp&OOSpAFpkpAb*b!q,dMqY'je!VZQl
+p&a[UmeZYTrrMinrUp<\p?qkPrr2u\aoD,/!<<#k!:KUTs8W&k!q,c`qu?g9Mi/GM!!8timf)n_
+mf3=\mf)n[mf)ngmf3=\mf3:emf3=\mf)n[mf)q[s8Vcmmf)n\me6VZs7QH\rq6?[rq6?[rq6?[
+rq6?[rr3,hs8Vf\rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6Wcs8N)es8Vf\rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6Zds8Vf\pAb0\pAY*kpAY'mp?qqR!:Kj[!:Kj[!:Kj[#k%`m!:Kmep?qnQ
+!:Kj[!:Kj[s8N,nme?DTs8DWkme6APrrMinrUp<\p?qeNr;Qfks8DWmme6)FpAFpkpAb*b!q,dM
+r:^-i!TsE4~>
+rr2tVqg/aAhWFP3s7YmCk2+XQqKi\Fs+>B6C3+GgXM(F2c2IYH`N5TCX@d7,Es-6!s8N)uEr]tS
+Es-6!s8N)trr[?BrrE%>!,DLS"D[u:!,DLS!GZ]Ps8I'>CAr8SCAr8SCAr8SCAn/7!<<'!rc8'S
+rc8'Src8'Src8'Src8'Src8'Src8'SrVlt@s8N)uEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEscZ'
+s8N(?s8N'!F8l1@!-;oSrr<&uEr]tSEr]tSEr]tSEr]tRrr[?BrrE"=!,DLS!,DLS"DZKeP]Q_K%%
+Q2:pAb0dmcNZgeWfoW"4cQ%pAFsjpAX1TeT:Y8"4cQ%pAFsjpAX1TeT:Y8"4cQ%pAFsjpAX1TeT
+:\9"3plG3Q_:$Mu.i0SDNE%s8Vf\k2tONPko_9pA]bdF)#c;9!#_%XNg_D#0![6]rXh@rc83WF8
+u7?rc8'Src83WF8u7?rVlt@s8N)uEr]tSEs-7Xrr?g5Erg#sqZ$P9!,DLS!,DLS!,DLS!,DK4!s
+&B$!<.$>CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAn/7F8u7?rc8'Src8'Src8'Src8'Src8'Src
+8'Src8E]F8u7?F8u7?!-A/>!W[:Vrr2rurc8'Src8'Src8'Src8'SrVlt@s8N)tEr]tSEr]tSEs
+-7.s-.U%HOQG$k4\iTp?q)*hURkeHNVg\me6SYs7ZHS!S)8hHNVg\me6SYs7ZHS!S)8hHNVg\me
+6SYs7ZHS!S)8iHNVOms#J7%!/p`$%%Q2:pAb0dmcNZgeWfoW%JKgSF)u);F%WOIUo_i>rs$HDS@
+u!rCAr8WC30FT!<.$>CAr8WC30FT!<)p"F8u7?rc8'Src83Ws8N(6rc8*TF8Gq9Er]tSEr]tSEr
+]tSEr]tRrrW9$rrE%>!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DK4"*=MB!<.$>CAr8SCAr8SCA
+r8SCAr8SCAr8SCAr8]C30FT!-A2?!!%*>rrN1ACB"55!<.$>CAr8SCAr8SCAr8SCAn/7F8u7?rG
+qsRrc8'Src83Wec1kTqg/aAhWFP3s7YmCk2+XQqKi=pk3hs@s8VfljoO"Rr-JOrk3hs@s8Vfljo
+O"Rr-JOrk3hs@s8VfljoO"RrHe[ls8P+ZJ,~>
+rr4"QZF7'IZEh@(lLt8Xo'Yf.inhPX[^*?I[^,W,])8]6FTB!a*;]^=*+?DYFo/?Arr<&oY5eM%
+!<)p"Y5eM%q6'bt!!)o!qZ$)grVls"s8N)\Y5SA&Y5eM%jKAO_"oth+rr<&%rr3$"Y-.d(!!)Pl
+rVlu&s8N)kXs3$._Q(&M[^*?I_VXSOs8VZXlK[Bc_QpVU[^*?IhWjP&s8Dctp@@M6k2-*C#I^qH
+hWjP&s8Dd*p@@M6k2*DL[^*?IhWjP&s8Dd(p@@M6k2*DL[^*@$s8RqtruJhZ[^*?IZGPJ`pAb0`
+mcs)shSQS,ZF7'IZM+=0r2p0F!4l_]qZ$a=@CcG]ql]u!!!)ess8N'!rVlu&s8N)pY5eM%!;iqq
+s7*8jrrW9$rrD/`rVlu&s8N)[Y5eM+!3ZA%!!'2$rrN2'Y5\G$!:d5jrr]G(rrD\o,3JpBWj]4A
+ZF7'UhWjh7s75UClJg[;ZF7'IZF7'qlL+BGrV?]ko'5N&hYsec[^*?ulL+BGrV@*!o'5N&hQjGq
+ZF7'qlL+BGrV@#to'5N&hQjGqZF8cms,"nu*PShfZF7'E_VXSOs8VZXlK[Bc_QpVU[^*?IpA_`%
+XorkI\n)lY!!F9M\c?mMY5eM%!;N_srr<&trr]G(rrDkts8N'!ql]eqnZMij!s&B$!9LB^rr]G(
+rrD,_s8N9'Y5eM%!3Z>$!W]C+rr2runZMij"0V\(!;*E<k5W;u[^*?I[^*d,lLt8Xo'Yf.inhPX
+[^*?I[^+cTme6\Zq??T`lK[Ngriud;ZF8WTme6\Zq@NAklK[NgZEgpE[^+cTme6\Zq@E;jlK[Ng
+ZEgpE[c7>eM>r)~>
+rr;ff!Uf[[s8M`lmeQSUs8;QnU]A);)#F:9+C`"aV#0lcrr<&opAb-m!<)p"pAb-mq=ajg!!)oi
+qZ$*ZrVls"s8N)\pAP!npAb-mjS&WR"p"Asrr<&mrr3$"p@eLc!!)Q_rVluns8N)kpAY'lk5+cP
+me6VZrq?B[q=XjWpA"[fpAXLXp&XUTq#CBfrpK^X!Uf[Vs8VflmeukYrrD3's7u?hme6VZrq?B[
+q=agfr:U8h!52hYqZ$aA@_Dc;qtC'i!!)ffs8N'!rVluns8N)ppAb-m!;lKds7,g]rrW9$rrD0S
+rVluns8N)[pAb-s!;?Hm!!)`lrrN2opAY'l!:fd]rr_uprrD]brr2u\qXssXpAP$jpAaRVp&XUT
+q#CBfrpK^X!Uf[Vs8VflmelbZme6GUs7ZH[rV$6j!9VH(q=XjWpAP$jpAaRVpAY*ip&q/k]j_iU
+!!FER]`=l*pAb-m!;Q9frr<&trr_uprrDlgs8N'!qtBmdnb2q]!s&B$!9NqQrr_uprrD-Rs8N9'
+pAb-m!;?El!W_rfrr2runb2q]"8;cp!;-!arrD3Xp&XUTrVuljs6f^V!Uf[Vs8VflmelbZme6GU
+s7ZH[r:U0ZpA"[fpAXLYpAY'mk5Tr~>
+s8N,MF8gLjF*i88hX9h2rsA,UhWE@iHZOOTrd4\Fqe?X>k$$Wu]p,U_Pf;M9;XRH[CB+;7!,DH3
+rbDK5!!)ut"9AK%!,DH3s(_T6!!)q3s8W#ts8N*"CAn23CAe,3CAn/9!<<'!C23\Hs(_T6s(_T6
+s(_T6!c%aMr;Qb3rVm$$s8N(6CAn23CAe,&CB+;<!<<'!!,?9JrrN18CB"57!,?9Is8Hd5s8Qj6
+rr?g4rr<&ss7U11^&OUDF8gLiF*k"FmdBuQ"lAClXF#$fHNnP<^#nJFpAFpjmf)>V]jc>8F*i8I
+k2u+*r;QcbroO<r@XE1qHN_%Ek3hs@rrDKdjpJe2HZOO\MuWgY3QqF'eT:_:#'5-<XPWC5rr3;m
+k2,7NXF##8F8gOds8-OA;W_0>hS#/TPa'/DhGWc>qeH02!<?m4s8Hd5rr<&trr`?%rr?g3s8Qj6
+rr<&sCB+>4!<<'"!,DK4rbDB2s(_N4"T\T&!,?9Hs8Qj6s8Qj6s8Qj6rrQs8CAe)3CAn/9!<<'!
+C23_IrbDB2nnS4)"p"]'!!$bKrr3$"C23bJ!WZtMrVuk3s8W+6s8N(6rVlitr;ZJ*"MOi*F*%>-
+"`o$lhX9h0!!V6AeZ=+=rd+ijHbJS(me6SY!:KjK$b^"rHZOO\^#nJFpAFpjmf)>N]jc>0rd+d]
+k2u+*r;QcbroOR$@XE0CH].q(X?"N)!S)8jHNnP<H`Z)lmf*4mmcNBgeZ=+=HZT15s8Vt2%oVOn
+hVPr1XH\sghVM/u;Yt5/rrE+7r;Zb2s8N'!rVm!#s8N(6r;Ze3s8N'!r+c93r;clt!<?m5s8Hd2
+s8Qj4rriE&rr?eKr;Ze3s8W+6s8W+6s8N.8s(_K3!,DK4"T\T&!,?9Is8Hd2s70q)rrrK'rr<%6
+CB"57!,?9JrrN18CAn23CB+>6CB+;6CAn/4!;uljC';6MS9&cNHNeJ;XPWC5qu?oWk1-P[F8gLj
+F*kU_k3hs@rrDKdjpSk3H[Bg\HbJS(me6SY!:KjK"2//jF8gLh^#nJFpAFpjmf)>U]jc>0H[C\N
+s/\52~>
+s8N)]qQ^4ChX9t6q??<Pk3Cg?qQg/$+0)KDY,\XY!*Rn,\rj"TNOm]p<<.`UWiiA)WrN)!Wr2l#
+WiiB%rrE#t"9AK%!35ts$`^B0rrB4%Y,\Z)s8;rtrrE,&rVlr!Y,_F"!NN=$rriE&rrB(%r;R80
+WrN+%WrN+%WrN+%s/u;"!3Z;#"T\T&!334#rrT4'Wr2l5WiiA)WiiA)WiiA)WiiB%rrE*!!!'%%
+rr3$"Wil@$!W]7'rVm2(Y,_O%Y,_O%Y5SA#!;ulsWXZ,2Y,\Y)Y,\YUs2Ln<r3?FEhX9t4!!DBK
+hST,p&'F2&meZt[s8)T_lK76OU&;2,b3J9[qZ$ElqYKdJk2sg[r3?jUlK[g6s8)clqXWq6k/sCr
+Z37oAs3?2=rrD3XZ3/,'mdgAR"n([<lJBDSZN'qHWiiA)Wih$U=k;<<OfFP']%5S8!/7SUY,\Y)
+s8N)!r;Qr#Y,_O%!<)p#!<<'!Wr2l)WilC%!3W?)WilC%r;clt!<B;$rrT4'Wr2ktWil=#"T\T&
+!334"rsl33s8T7%s8T7%s8T8%Y5J;"Y5SA(!<<'!Wil=#!iiE'r;RS5Y,\Y)Y,\Y)Y,\Y)Y,_O%
+!<<'!!334$rrN2#Y5\G&!334#rs>^.WrN+%WrN+%rVlitr;Zes%Bc_6WiiA)WijqQ`hfj9Z3/,'
+mdg8U"6Sn*_YUPKb3J9[qZ$ElqYKdJk2sg[r3?jUlK[g6s8)clqXWq6k/sCqZ4G+ClL+NKqZ$Eg
+o'5B"b+\d>"MXp9c@O4>!9X-`"303co)AIhmcrs"hST,ps8O1@Y,\Y)Y(ZjYf%R]tWf`:Pf%O+(
+Ks%GYWiiB%rrB(srroF*WrN)!rVm!#s8N)!r;R/)Y5eM%Y,\Y)Y5eP#!<<'"!3Z;#!iiE'r;Qet
+Y5SA(!<<'!Wil:"%^)i3s/rC%s/rC%s/uC)r;Qc"rVm$$s8N)!Y5SA%WiiB"rth]<WiiA)WiiA)
+WiiA)WrN)!s8N'!Wil@$!W]7'rr3$"Wil=#$*(/.s8T7%s8T8#rr<&ss8T).Y,\Y)Y,\Y)Y1EWm
+V69a%"303co)&Iik3Cg?qQ^XSlK[g6s8)clqXWq6k/sCqZ4G+ClL+NKqZ$Ego'5B"b+\a=&'F2&
+meZt[s8)T_lK76OU&D8"^An5YJUd~>
+rr;ig"6T%FpAY*lp&jaVk2uO6s8W,m*U`Xhp:UH0hVPr1XH\sghVM-1^%Umfme6)KrrDKbrrqia
+mf3:erVm!#s8N)er;R/mpAb-mp?qYBpAb0k!<<'"!;?Bk!q,dMr;QfcpAP!p!<<'!me6SY%ef>j
+s7Ym\s7Ym\s7ZKdr;QcjrVm$$s8N)epAP!mme6)Hrtk+sme6)Bme6)Bme6)Bmf3:es8N'!me6Y[
+!W_Z^rr3$"me6VZ$1@NTs8Vf\s8Vfkrr<&ss8VKrp?qYBp?qYBpAb0dk3i0@"6T%FpA=mmme5f*
+qXsp>rq?6hs7QQ_p>4[(p&NYBpA=mip&jaVhVS2(!7h)Bqu?]i"7Gm>hYm0HrrCTls8)Ekk3hs:
+rr<#l"7GmFk5+fOs8Vd5me6)B]`;6mhS#/TPa'/DhGO?ep?qYBp?qt\!:Kdb"n)*Ps8N)trr`?%
+rrDKbrsS8gs8N)mme6)Bs8W#ts8N*"pAP!mme6)HrrMQ]rVm$$s8N)epAFq#p?qt\p?qt\p?qt\
+pAajarrDckrriE&rrDK\rVlrep?qkY([h"bp?qYBp?qYBp?qYBs8N*!rr<&epAY'n!:KR[rrN2g
+pAP!tme6)Ks7Ym\s7ZEk!!)rss6^?ime6)Bme6)Bs8VfTmelb\k3hs:qu?iep?(N6p&NYBpA=mi
+p&jaVhVS2(!7h)Bqu?]i"7Gm>hYd'Iec,:>s8Vcpme5MorV$3i!7f9mqXt$Rme6ARs8Vcpme5f*
+qY'shs7RK$p?qXf!*\79]p,U_Pf;M9;?4E(me6)Bmf3:emem(gme6)KrrE#t"9AK%!:Kdb$h!`g
+rrDc\p?qYSs8;rtrrE,nrVlrep?qkY!Uf[[rriE&rrDK\r;R9#mf3=\mf3=\mf3=\s7ZBj!;?Bk
+"T\T&!:KRZrrVW^mem)$me6)Bme6)Bme6)Bme6)KrrE*!!!)H\rr3$"me6Y[!W_Z^rVm2lp?qt\
+p?qt\pAP!k!;ulsmLAmXp?qYBp?qYSs7YUCr:U6Tme6AP!!DZ_k2uO6!7h)Bqu?]i"7Gm>hYd'I
+ec,:>s8Vcpme5Mor:U-@rq?6hs7QQ_p>4[)pAP!keUR~>
+s8N(pqf;mm^#nJNrVm&hhVRD.KDT`irrHkDrb;sQC5]0XMj2cle_Z4KMl_j9C&h`BCB+;7!,DE2
+s(_T6#QSW>rr<'!rrE&u!!*#u&Sh@G!,?7XC23eK!,?7XC&e82s8Qj2s8Qj6s8N*!rrE+7qu6s&
+CB+;6CB+;6CARr1!<3!(CB+;6!<<'!CA\&2CA\&2C&h`BC&h`BC&h`BCAn24!<6d6@f?<,CAn/5
+!,DE2s(_T6#ln`?rr?g6rr<&rs8Ha5@fC*H@VTYBs35<VEs%'.k2uL?"5`1RKDT]iXT%>^pAFpo
+p>4roXCD*K!3H1^$hjW#!!*&mhWEt%@f19IXT%A^!<)rt!<;0^XCD*K"7H3_.Eh_kV#,39K>$F0
+pAP!pmbZg_]n?3's8N+7@fC*Q@VUh&P`(dVs4,taP`)W$rb;FBrbDK5!<?m3s8Qj6rs/U>s8N'!
+s8N)urr<&urt0#Grr?eK@VTZXrr?eK@VPlCqu?\2qu?\2s8W*!s8N*"CA\#;!,DQ6!,DQ6!,DB1
+!!*#u#\sD>!!*'!!,DE2s(_H2s(VOCrb;FBrb;FBrbDE3rrE(6!+Pp,!,DK4!<?m3s8Qj6rs8[?
+s8N(6s8N'!qu?Y1!+PqB#%D=^PlK!Cr,Vsm^#nJR!!D*?]n?3'!3H1^!;??j"npg8k,`%iEr`<@
+jpUn_rr<'!p>4roXCD*K!3H1^rrE#trrE)]!N]c.Es(k1p*n5c!2TL5"G=DMk4\cR"n(7(k.QEE
+F8u7@C1@0W%q9:3XH\X-ec41VMj0.$MuIGk@fC-BrrE+7qu?\2s8N?)CB+;6!<<'!rr2rurr3RF
+s8N(6C1:pms8N(6C1:oX!;lfrCA\&2CB+>6!<<'"!,DE2#ln`?rr?g6rr?g1rr<&urs3B>rr<'!
+rr?g2s8Qj2s8Qg6@fC*B@fC*B@fC-@s8N*!C&h`Arr?g4rrE+7qu?\2s8NB*CB+;6CB+;6!;lfq
+C&h`BC'J-^C6\bCCA`,TK>$F0q>^WSk.QEEEr`<@joG,Qrrr,Qk2raSr,Vk>roOU^s8N'!s7Y=3
+k,`%iEr`<@k5PG[s8N*!joMPmr,Vu.s7Rml~>
+s8N)AqlUC6`ocRWqZ$Ecmc*6k`qlk<s8&`),WLpGOk0Q`er>fO3$e@#s8N*"Wr)hrWrN))!36)!
+!!*'!!<2uu!<3!#WrN)!r2Tes!!)ttrrDrrs/Ptrs/Q,!rrE*!!<B.srs8\*s8N)!s8N)!qYpNq
+rr38(s8N'!s8N)!qu?\rqu?8frVultri5qs!36"t!<B.ss8T,!rs8\*s8N)!s8N'!qu?Dj"2b)t
+Sc#VmZGu%lq>^TVlGi\'!4r0l$hjGsqZ$E_io]C7Q2Icb])Lh"pA4dh!;c9Gk2s7?r2p%2roX4\
+$30l%q>^NXk.6iUXonCtp1__M!6Y2A%C4"9lLOfOqY'@:ip+P[Y5eOuWXU45Oc>LSs45b\Oc;=G
+qPsSq!<B.ss8T,!rs/V)s8N'!s8N)urr<&urr];$rrDtss8N'!rMoktqu?\rqu?\rs8W*!s8N*"
+Wr)f&!36)!!36)!!35nq!!*#u#cdq)!!*'!!35qrs/Ptro;_chrrE%urVlktrVlluWr)hrWrN)*
+!36)!!36)!!!)orpSn>4s5KUIXokuLk3DdC!oiLbqQ9h0roOU^qZ$ElqXWY.k.6iUXoQ'4jpUnZ
+rr<&qo&Afo\s<2r!4r0lrr<B*qZ$Bl!9WFTQ2IcepAai#bl7[cqlUC6`ocRWqZ$Ecmc*6k`qlk<
+s8&`),WLpGOk0Q`er>fO3$e@#s8N*"Wr)hrWrN))!36)!!!*'!!<2uu!<3!#WrN)!r2Tes!!)tt
+rrDrrs/Ptrs/Q,!rrE*!!<B.srs8\*s8N)!s8N)!qYpNqrr38(s8N'!s8N)!qu?\rqu?8frVult
+ri5qs!36"t!<B.ss8T,!rs8\*s8N)!s8N'!qu?Dj"2b)tSc#VmZGu%lq>^TVlGi\'!4r0l$hjGs
+qZ$E_io]C7Q2Icb])Lh"pA4dh!;c9Gk2s7?r2p%2roX4\$30l%q>^NXk.6iUXonCtp1]$~>
+s8W&k#4D3Ymb[[2r;QromdBf*k5=oSmf3=`p'i`:P`(dVs4,taP`%OVqY'sh!<Dijs8Vfmrs/Vu
+s8N'!s8N)urr<&urr_uprrDujs8N'!rV$6kqu?]iqu?]is8W*!s8N*"pA=jr!;?Hm!;?Hm!;?9h
+!!*#u#kn;u!!*'!!;?<is7Z?ioCi._rrE&lrVllkrVllupA=mipAb.!!;?Hm!;?Hm!!)orp\+Ud
+!8d_K"n)*PhY-[>!!DZ_hWFh2#4D3Yeb8_)qYpcfp?p2Up?qqR"4d,=mf*7d!<<'%me6(nec#1G
+ma_%)mJm7cs8N'$p?p2UrUp6Zrr2u"bQ%P7#4D3Ymb[[2r;QromdBf*k5=oSmf3=`p'i`:P`(dV
+s4,taP`%OVqY'sh!<Dijs8Vfmrs/Vus8N'!s8N)urr<&urr_uprrDujs8N'!rV$6kqu?]iqu?]i
+s8W*!s8N*"pA=jr!;?Hm!;?Hm!;?9h!!*#u#kn;u!!*'!!;?<is7Z?ioCi._rrE&lrVllkrVllu
+pA=mipAb.!!;?Hm!;?Hm!!)orp\+Ud!8d_K"n)*PhY-[>!!DZ_hWFh2#4D3Yeb8_)qYpcfp?p2U
+p?qqR"4d,=mf*7d!<<'%me6(nec#1Gma_%)mJm7cs8N'$p?p2UrUp6Zrr2u"bl@Y8#4D3Ymb[[2
+r;QromdBf*k5=oSmf3=`p'i`:P`(dVs4,taP`%OVqY'sh!<Dijs8Vfmrs/Vus8N'!s8N)urr<&u
+rr_uprrDujs8N'!rV$6kqu?]iqu?]is8W*!s8N*"pA=jr!;?Hm!;?Hm!;?9h!!*#u#kn;u!!*'!
+!;?<is7Z?ioCi._rrE&lrVllkrVllupA=mipAb.!!;?Hm!;?Hm!!)orp\+Ud!8d_K"n)*PhY-[>
+!!DZ_hWFh2#4D3Yeb8_)qYpcfp?p2Up?qqR"4d,=mf*7d!<<'%me6(nec#1Gma_%)mJm7cs8N'$
+p?p2UrUp6Zrr2u"J,~>
+s8NX_C3+-2C3,$PhWF8+pAaj[rn[t#HYRV:F)#drs8$169(&5+hNY++Phsrdk">JZs8Nf6@fQH.
+!<<'!@fQH.@fQH.@fQH.@f??3@fQH.s8N)s@fQH.!;p=+s8;rtrt/`?rr<'!rr?O.rr?O.rrE*!
+rW)uu$NOZ9rr?O.rr?O.s8)d)@fQH.s8N(.s8N*!s8;rtrs*$5rr<'!rrE",rVue)r;Z_)rVlit
+rVlp!s8W#ts8NaAs8N(.s8N(.s8N(.s8N'!s8N)o@Q:IhS765SC3+-Bc/.R_!;?Hd!!(m4`Hu?@
+C3+-2MrrRHmf3"\pAaR;e`McnF)u);C5_6)hX:FB!"SGRe`McnF)#c2F,T22hYmKUs7ZEl%+XKu
+>'"G"C3.Z"s"V^s&;+_=C3+-2K?`98mf3"\p@eLB$,q7+F)#c2F8u::@LYrtSDN+eXH\t+eYM>"
+qI9L)'`__Crr<'!rr?O.rr?O.rr?O.rr?O-!!Zp4rrE*!!;p=+rr<&s@fQK,!<<'2@fQH.!<<'!
+@fQH.@fQH.s8W&us8NH,@fQH.@fQH.@fQK*!"<?:rrE*!!+Q!.!<<)t!<<'(@fQH.!<<'!rF5a*
+r*oU(rF5a*!!)ut!W`9#r;clt'4V"A!+Q!.!+Q!.!+Q!.!!*'!!;L"_XT+f"C3+-2C4jdfjo>DT
+s7QEmhVQ4uC3+-2C3,<qe_]`opAajdmbZLVMct1CC3+-Jk1/>Vs8;p-mbZLVMct1:F)#cSk1/>f
+!!3,nrW!AWk)3DaC3+-2c2[eubl86,C3+-2C3,$PhWF8+pAaj[rn[t#HYRV:F)#drs8$169(&5+
+hNY++Phsrdk">JZs8Nf6@fQH.!<<'!@fQH.@fQH.@fQH.@f??3@fQH.s8N)s@fQH.!;p=+s8;rt
+rt/`?rr<'!rr?O.rr?O.rrE*!rW)uu$NOZ9rr?O.rr?O.s8)d)@fQH.s8N(.s8N*!s8;rtrs*$5
+rr<'!rrE",rVue)r;Z_)rVlitrVlp!s8W#ts8NaAs8N(.s8N(.s8N(.s8N'!s8N)o@Q:IhS765S
+C3+-Bc/.R_!;?Hd!!(m4`Hu?@C3+-2MrrRHmf3"\pAaR;e`McnF)u);C5_6)hX:FB!"SGRe`Mcn
+F)#c2F,T22hYmKUs7ZEl%+XKu>'"G"C3.Z"s"T$~>
+%KH:9WiiA)Wii2Lk2u76q@<5iio9+GTrP8qY,\Z)s8&Q$JH/6perctpNS;rS!.k!Cs8Nf6V>pPq
+!<<'!V>pPqV>pPqV>pPqV>^H!V>pPqs8N)sV>pPq!;r\ns8;rtrt2+-rr<'!rrAnqrrAnqrrE*!
+rW)uu$NR%'rrAnqrrAnqs8)d)V>pPqs8N(qs8N*!s8;rtrs,D#rr<'!rrE"orVuelr;Z_lrVlit
+rVlp!s8W#ts8Nb/s8N(qs8N(qs8N(qs8N'!s8N)oV)Zp'_O77'Wii@uf&l)p!;cQc!!)$@cCq8@
+WiiA)U#t(go(r(VpA4@>g?,)kY-+e-WhJS/ipusE!"SSZg?,)kY,\Y)Y+b"3ir/oYqY'mg%,0j;
+Ofk^eWik@]s'a.O%/RQ8Y,\Y)Y,0_3k48NJ%efJQio\O[WiiA)WilC%qP=XP!(bhpOfFP'g=Adp
+Jbl5CrtPO1s8N'!s8N(qs8N(qs8N(qs8N(qrW!/!s8N*!rrDtns8N'!r2'Gnr;clt&Z,O-!!*'!
+!2]_q!2]_q!<<)u!<<',!2]_q!2]_q!2]_qqZ%&$s8N*!rrAnqrrE*!r;clt#GqJ#!!*'!!<&bm
+s88_ks8Aemrr<&trrN3#s8;rtrtD7/rrAnqrrAnqrrAnqrr<'!rrDhj37@iDRAI'dY,\>Lk2lXD
+qYKmc!93.dTrP8qY,\Xuk1\hcqY'dZqXWY"k+Rp?Y,\Y)U#t(go(r:b%eAW5k+Rp?WiiA)U#t(g
+rVuuqpAP%#g?,)kY,\Y)Y2]K]@Enf\qRW]0WiiA)V:Oeko)AIqp@@5&k0B[#Y,\Y)Y5eOuV%%tU
+8D;XWWf`:pejodlqPF5l'`b*1rr<'!rrAnqrrAnqrrAnqrrAnp!!];"rrE*!!;r\nrr<&sV>pSo
+!<<'2V>pPq!<<'!V>pPqV>pPqs8W&us8NH,V>pPqV>pPqV>pSm!">_(rrE*!!2]_q!<<)t!<<'(
+V>pPq!<<'!rMBJmr2'>krMBJm!!)ut!W`9#r;clt';ba/!2]_q!2]_q!2]_q!!*'!!;NBMdf71P
+V66i$Whn;/jo>DXqXsmhio\O[WiiA)Wii&Xg>_]"pA4LZo&ABcTolL\Wii@qk1\hcqY^C(o&ABc
+TolLXY,\Xuk1\ho!!2rirW!A\k+Rp?WiiA)irB$eJ,~>
+rr;lh"O6)sp@eFarpBgDc2757s"j*:me6)Bm_o/uhVOKuPa(%T8cZiup?qYBp?qt\!:Kme!!*'!
+!:Kme!:Kme!:Kme!:Kgd(%2,%!<<'!p?qYBpAb-mp?qYBpAb0k!<<'2mf3:e!<<'!mf3:emf3:e
+s8W&us8NH,mf3:emf3:emf3=a!"AT$rrE*!!:Kme!<<)t!<<',mf3:e!<<'!me6)BrVm#gp?qYB
+r;Qlep?qYQrr<&trrN3#s8;rtruph1rrDKerrDKerrDKerr<'!rrDc\p?qYBp?qYJs7Y"2rUpE>
+k3hpC!<3#u!<;HfhTbrk"MONkme6SY"nqBHp:]#Sp'&/'k3hsCr;[#pmcO5Vebo+C^%UUVrW)uu
+rW!&_p:]#SpAY'lUrr`7p&rY&me6APs8MEehTbrks8OnCp?qYBp?om"9&AEhXH\t+eOfh\me6)B
+me6)KrrDKerr<'!rrDKerrDKerrDKerrDKd!#=r%rrE*!!;>jSme6\\!;>jSme6\\r;clt&ao]!
+!!*'!!:Kme!:Kme!<<)u!<<',!:Kme!:Kme!:KmeqZ%&us8N*!rrDKerrE*!r;clt$h"&p!!*'!
+!:KRKpAP!ome6)Bmem(eme6)BrVlitrVlp!s8W#ts8O81s8N)es8N)es8N)es8N'!s8N)mme6)B
+me6)BpAaj:meuh_c0"Hf!!*#urrE)e!T))up&r)&k3hs@rrr,ak4ZL=r:U<-p?(f:s8;p$p?q):
+^"*&S"24Ejmf!4ds8E!#k4ZL=r:^-i!2Rg<qt:0;k3hs:r;Zca!T))upAb.Kme6)Bme6(f!(u,)
+PcU+6hUP3u`U<Hfp?qYBs8N)es8N'!s8N)es8N)es8N)es8N)erW!]$s8N*!rrDc\p?qYSrrDc\
+p?qYSs8;rtrt4]!rr<'!rrDKerrDKerrE*!rW)uu$NTVprrDKerrDKes8)d)pAb-ms8N)es8N*!
+s8;rtrsS8prr<'!rrDK\me6VZ"Rc!Op?qkY"7GmNpAP!k!<)p!!<<)t!<<'Bmf3:emf3:emf3:e
+mf3:e!<<'!p?qYBp?qYBp@eO[eaED0"jQ2tp&G*ls8N*!mK)1hqt:0+p?(f:r;QromcO5Vebo+E
+^%UUVpAb'k"nqBHp:]#Sp&i#%k3i3Ks8W&u"6T<jebo.?rrAjF~>
+s7ZJ-!+PqB"(HW6k4ep?k1+ff@VT@eCB+<C>%1ZE>%1Z=k,af\s4+f@XQEtq@Tm5E@Tm7@rr?O.
+rr?O.rr?O.rr?O.rr?O.rr?O*s#pG_rr?53>%1\8rr?53>%1\8rr?53>6"U&s8N(.s8N(.s8N(.
+s8N*!rr?53s8N(.s8N(.s8N(.s8N(.>5S==!<<'!@fQH.s8N(&@Trg3!<<'!@fQH.@Tm5ErVo1a
+>%1ZEs8N*!rr?53>6"U&rrE'!s8N*!rr?53>6"U&s8N(.s8N(.s8N(.s8N(.s8N(&@Tm5E@Tm5E
+^&O!oC1@0W#CG=ihX:+;pAP$qe`PD/@Uf=O#@`&:e^a*]s8M^&ma]kEHWjlnC1:q)hUU0EqZ-ZH%
+,Q>7@VT@eC4"gfeaE;7s4%;0HWjln@fC-Brr=Lms8VfmC&h`BC'.plhWFS553CCB@Ua(]C23eK@
+Tm5E@Tm5E>3;oN^&QWrMlc&M>%1ZE>%1ZEs8N(.s8N(.s8N(.s8N(.s8N(.s8N(.qu8h[s8N(&@
+Tm5Es8N(&@Tm5Es8N(&@Trg3!<<'!@fQH.@fQH.@fQH.s8N(&@fQH.@fQH.@fQH.@fQH.@Tr[/)
+Z]p<!+Q!.!<<'!>%1\8rrE*!!+Q!.!+K,@>5eIf!*Wi8@fQH.s8N(&@Trg3!<3'!!<<'!s8N(&@
+Trg3!<<'!@fQH.@fQH.@fQH.@fQH.>%1ZE>%1ZE>.sro>&%OGC'T+Bk2,P"s7ZEl"kDbcHX^I`C
+'S3phUU0EpAb-c&+7uuhKrF8C2.3mHf!<'me["aeI:;]>%25UC2/+Pe^a*b!<:RQhKrF8C1@0Ws
+8N'JcN!q<s(VOCrb;OEHf!o[!']PqHX^H!@VTZXs'f/@>%1ZE>$C'iPeI+I]o/uS@Tm5E@Tm5E@
+fQH.@fQH.@fQH.@fQH.@fQH.@fQH.@f-0h!<<'!>%1ZE>6"U&>%1ZE>6"U&>%1\8rrE*!!+Q!.!
++Q!.!+Q!.!<<'!>%7O3!+Q!.!+Q!.!+Q!.!+K./ru1t<rr?O.rrE*!!*Wi8s8N*!rr?O.rr?M3@
+Tra163(1u>%7O3!<<'!>%1\8rrE'!rrE*!!<<'!>%1\8rrE*!!+Q!.!+Q!.!+Q!.!+Q!.!*Wi8@
+Tm5E@TpJFMcsk)rb;[bhWE\_pAajc!!Up8eU(b7rb;[IHf!<'me6\[p(-TAe_YXV@VTXeC4"gfe
+aE;7s4%P7HWjln@VTY)hUU0EqZ-ZH"l=T0@VTBOCB+;6.=_~>
+!VZBdWWJIFk4eoYk1Z)or2Tes1SpeATr"HZTkscLEOu2$\oA\iD5!f"V4j`ZV>pPqV>pPqV>pPq
+V>pPqV>pPqV>pPqV>L9V!<<'!Tr"HZU&Y,mTr"HZU&Y,mTr"I_rrE*!!2]_q!2]_q!2]_q!<<'!
+Tr%eh!2]_q!2]_q!2]_q!2ZCdru1t<rrAnqrrE*!!266_s8N*!rrAnqrrAmhV4mkf5ldUTTr%eh
+!<<'!Tr"I_rrE'!rrE*!!<<'!Tr"I_rrE*!!2]_q!2]_q!2]_q!2]_q!266_V4j`ZV4lK?^6PPn
+WX"gKk2Pt*qY'mg"Q&:pQ(e,U"I8!#hX:=8"n(7$ig#Z(WW\UHg>;8p!!M04ig#Z(WW\UHg>;8p
+!!M04ig#Z'WrN)!@EnfQpA4Wc!gVd-p](EYg6JB0WrN)TV4j`ZV4j`ZD#bPq])U?mE?"sqTr"HZ
+Tr"HZs8N(qs8N(qs8N(qs8N(qs8N(qs8N(qqu8h[s8N(mV4j`Zs8N(mV4j`Zs8N(mV4mqh!<<'!
+V>pPqV>pPqV>pPqs8N(mV>pPqV>pPqV>pPqV>pPqV4med)Z]p<!2]_q!<<'!Tr"I_rrE*!!2]_q
+!2ZBcU&G!W!266_V>pPqs8N(mV4mqh!<3'!!<<'!s8N(mV4mqh!<<'!V>pPqV>pPqV>pPqV>pPq
+Tr"HZTr"HZU"97XQ)4GZ#F4<2ipug>pAP$phWEOWU&:nnQ/^NSmelb^mbZ[WQ')!E"I8!#hX:7@
+"Q%klQ')!E"I8!#hX:7@"Q%klQ'(sDs8N(-cMmq=qYI2nQ/^s$!!DB;Q(e,Us8OmOTr"HZTr"H"
+!$$!is44c$)usiLV4j`ZV4jacrrAnqrrAnqrrAnqrrAnqrrAnqrrAnms#pG_rrAahTr"I_rrAah
+Tr"I_rrAahU&Y,ms8N(qs8N(qs8N(qs8N*!rrAahs8N(qs8N(qs8N(qs8N(qU&4j/!<<'!V>pPq
+s8N(mV4mqh!<<'!V>pPqV4j`ZrVo.`Tr"HZs8N*!rrAahU&Y,mrrE'!s8N*!rrAahU&Y,ms8N(q
+s8N(qs8N(qs8N(qs8N(mV4j`ZV4j`Zf)NILV>[D!Q/^rco(MqRrW!)Xk1Z)or2KmbinE8Wr:U<^
+hV-tSOo23^Q/^NSmeZtehV-tSOo23^Q/^NSmeZtehV-tSOo)0Yrr?JX~>
+s8NDnp?qYBp?o<Up@nUpp?''Vme6)Bmf3=dp&OO[p(-Se!#Tdjs4+f(+9852p?qqR)=I4urrDcm
+rrDcmrrDcmrrDcmrrDcmrrDcirr`?%rrDKdp&sg`rrDKdp+Ge5rrDK\pAb-ms8N)ms8N)ms8N)m
+s8N*!rrDK\s8N)ms8N)ms8N)ms8N)mpA=k+!<<'!pAb-ms8N)ep@eOd!<<'!pAb-mrq6?[rVn\S
+p@dqJs8N*!rrDK\pAb-mrrE'!s8N*!rrDK\pAb-ms8N)ms8N)ms8N)ms8N)ms8N)erq6?[rq6fh
+s8VfCmdBf:p9a8]mf!1b!"//fk.U3Np?qYB[/TLis8MEk[+4U4p?qX]rpBddqZ-W`#IN%Lp?qYB
+[/TIns8)fqmL$>Ome6)Bme6\\SBLp=me6)Bme6(Ume6DU$MNVqmdBf:p?qt\rq6?[rq6ljU];6Q
+^&QWrF!(IYp@dqRp)3;ls8N)ms8N)ms8N)ms8N)ms8N)ms8N)mqu6d!s8N)erq6K_s8N)erq7u4
+s8N)ep@eOd!<<'!pAb-mpAb-mpAb-ms8N)epAb-mpAb-mpAb-mpAb-mp@eC`(BFL8!;?Hm!<<'!
+me6ASrrE*!!;?Hm!<2Zlmf!/B!;?-SpAb-ms8N)ep@eOd!<3'!!<<'!s8N)ep@eOd!<<'!pAb-m
+pAb-mpAb-mpAb-mmf)n[mf)nhmf3=\eaDl!me4$Up?qnZrW!;np?''Vme6)Bm^2u]qZ$Q_#IN%L
+me6)B[/TIns8)fqmK^,Lme6)Bm^2u]!<;orrpC-#eaE/!p?qYSs.%=5$1@NTp?qYB[-mY_!"/G^
+^$b=^me6)Ks8M]lmf)njm\Bh"F1qV(]lP:rV"XNMrq75tpAb-mpAb-mpAb-mpAb-mpAb-mpAb-m
+pA=jm!<<'!mf)n_mf3:emf)o4mf3:eme6ASrrE*!!;?Hm!;?Hm!;?Hm!<<'!me6\\!;?Hm!;?Hm
+!;?Hm!;?-`rtb\8rrDcmrrE*!!:KRSs8N*!rrDcmrrE&l!:Kgc1][7Cme6\\!<<'!me6ASrrE'!
+rrE*!!<<'!me6ASrrE*!!;?Hm!;?Hm!;?Hm!;?Hm!:Kj[!:Kj[%IX8rp=8U!p?qX]me6)Is8E!*
+me5eVmdBf:p?o<emeZt_mK^,LmdBf:p9ahe!<;orrpC#ueaE/!p?o<emK!:a!<2Bn[+4U<me6)B
+s8SU>~>
+%/0+(@VT@e@VTB7hVS)/rn[oi>&%M]@VYrCpK@gHs37XPc2Z&_>6"U<!*]F&!*]F&!*]F&!*]F&
+!*]F&!<<)u!<<'$!<<'!r*'.#!!*"%rVlitr`]@%-34)G!*]F&!*]F&!*]F&!<<'!>$Ct+!*]F&
+!*]F&!*]F&!*]F&rW)uu$3:,+!*]F&!<<'!r`]@%#6=f(!*]F&!;p%!!<$+$rrW7)s8W(%s8NE+
+rrE'!s8N*!rrE%%s8N`4s8N(&s8N(&s8N(&s8N(&s8N)o=q@_7PZh7*@VT@]k2+tWp@eIc!9X:;
++(ADg@VT@e@c#A[k4\6:me5enc/)o-C2.3m@Ue3=ebK1Tc/)o-C1:peC1?&Ee`QT(!"S/Ac/)o-
+C1:peC1@5C.F%l$p?l[)C1:peC1?>^hYI6Oh?[RoC1:peCB+>.=pN=Pc)e:ss3::As8Ni7>6"U&
+>6"U&>6"U&>6"U&>6"U&s8W&us8N0$s8N)s>6"U&!<-1#rr<&u>6"UL!<<'!>6"U&>6"U&>6"U&
+s8N(&>6"U&>6"U&>6"U&>6"U&>6"X%!<<'+!<<'!>6"U&s8N)u>6"U-!<<'!>6"U&r*'%!rEB7$
+!ruO)s8H4%rsAc+!<3'!rrE*!!<-1%rt>D4rr?7&rr?7&rr?7&rr?7&rrDgt&$5eq>$>ZMC1:Z7
+hVRDgpAP$lk5O3Z@TmMUC1:pehTaU5p?qYBp?'oMhI9AtC1:pe@c#A[q#CoLhI9At@VT@e@c#A[
+k4\`R%d)<dhI9At@VT@e@fQHWcMn=HmV63G@VT@e@clP(q>gNO#\$tP@VT@es8Vgs#L3:nXL-7P
+c1bEArtYT<s8N(&s8N(&s8N(&s8N(&s8N*!s8E#urrW9$rrDt#s8N'!r`]:#!!*"%s8ODGs8N(&
+s8N(&s8N(&s8N*!rr?5+s8N(&s8N(&s8N(&s8N(&s8W&us8NE+s8N(&s8N*!rrE%%s8N<(s8N(&
+s8N)s>5\I">6"U)!*]F&r`]@%$3:)+rrE*!!<<'!r`]@%'*/(4!*]F&!*]F&!*]F&!*]F&!;K_.
+XT+Mg>&%M]@UeKVhWFP*rVur\rn\`+>&%M]@VTB/c.1tMme6)Bk1.`5@T$rU@VT@]hTaUH!"R91
+@T$rMC1:pehTaU5pAFt$k1.`5@T$rMC1:pes8ONu~>
+s7Qf"V5gAlV5f73injM3(#Is4Kpes;Whl`qs.,jSTq.mJTq-&r!$Z9NTq.mJTq.mJs8N(is8N(i
+s8N(is8N(is8N(is8N*!s8E#ursf&/rrAa`Tq.nWrrAa`U&G!B!25sWs8N*!rrAVirrAVirrAVi
+rrE*!!25t`rrAVirrAVirrAVirrAVis8E#uru;%=rrAVirrE*!!25sWs8N*!rrAVirrAU`SY;VQ
+!)'#VTq25`!1j/iTq.nWrrE'!rrE*!!<<'!Tq.nWrrE*!!1j/i!1j/i!1j/i!1j/i!25sWSY;UJ
+SY=@/_NCChV5gAGk2P7_o()b[,O4.Fk(T5'V5gAlL#U\;lLON>o())"f&DCCWiDnqV1mp[gA(^Y
+f&DCCWhl_lWeKH`g?S8-!"S;Jf&DCCWhl_lWhoal@EniPp'RgrWhl_lWeKTphYI3ehW![ORB!*`
+V5jRqSY;UJSY;UJSSe0&,&NmESY;UJSY;VSrrAVirrAVirrAVirrAVirrAVirrE*!rW)uu%KQP/
+!25sWSY?)`!25sWrVnDKTq.nWrrE*!!1j/i!1j/i!1j/i!<<'!Tq25`!1j/i!1j/i!1j/i!1j/i
+rW)uu*!$$=!1j/i!<<'!Tq.nWrrE*!!1j/i!1fgSTq2,^9;.oMScA]iScA_`SY?)`!<3'!!<<'!
+s8N(mSY?)`!<<'!ScA]iScA]iScA]iScA]iTq.mJTq.mJU!E\TOe&MKWhkF3initko)8V6lJCO_
+Kpes;Whl_LimuiKo()MFo'4r[ie<AlWhl_lL#U\;q#CoUie<AlV5gAlL#U\;lLOlR%dMd!ie<Al
+V5gAlV>pC#cN!q<$EBr&V5gAlL$%COq>_8eioYr_Whl_lWrN*iTq.mJTq.mJD>=/UD4RAkTq.mJ
+Tq25`!1j/i!1j/i!1j/i!1j/i!1j/i!<<)u!<<'/!<<'!Tq.mJU&Y,mTq.nUs""/DSY?)`!<<'!
+ScA]iScA]iScA]is8N(mScA]iScA]iScA]iScA]iScA`h!<<'=!<<'!ScA]is8N(mSY?)`!<<'!
+ScA]iSY;UJSc&O]Tq.mJs8N(is8Sd`U&Y,mrrE'!s8N*!rrAa`U&Y,ms8N(is8N(is8N(is8N(i
+s8N(mSY;UJSY;UJcMtbDSZ8NdV1n'khWj\&rW"2.hW![ORB!*`V5f7/f%TE[o(MYFlIshKKoN+4
+V5gAGimuiZ!"RT>KoN+/Whl_LimuiKo)/OulIshKKoN+/Whl_ls8$/S~>
+s8Vrh!2TV^q>gN_!MnlUpAb.!me6)Bme6)Bm\KXY,,FZ#me6)Bme6)KrrDKerrDKerrDKerrDKe
+rrDKerrE*!rW)uu%KQP/!;>jSme6\\!;>jSrVnDKp?qYSrrE*!!:Kme!:Kme!:Kme!<<'!p?qt\
+!:Kme!:Kme!:Kme!:KmerW)uu*!$$=!:Kme!<<'!p?qYSrrE*!!:Kme!:KRKp?qkZ5kaX>mf3:e
+mf3=\me6\\!<3'!!<<'!s8N)mme6\\!<<'!mf3:emf3:emf3:emf3:ep?qYBp?qYBp@eO[e`Qi(
+!2TV^!quZorVurlrpBf_k5=o`V!dC5pAajdpAajSk3f%qr:U5gmcNs5!!DBOUt,D:"f1SKme6\Z
+!!W)ak3f%qqtC'i!2Rg<qXsobrpKU_rpBf_k5=rQrsA,eme6)Bme6(Eq#DV7me6)Bme6)Bmf3:e
+mf3:emf3:emf3:emf3:emf3:es8W&us8NQ/s8N)mme6)Bs8N)mme6VZ/-,D3pAb-ms8N)es8N)e
+s8N)es8N*!rrDc\s8N)es8N)es8N)es8N)es8W&us8O&=s8N)es8N*!rrDc\pAb-ms8N)es8N)e
+p?qYBr;]+Vme6)KrrDKes7YmSs8N*!!<3'!rrE*!!;>jSs8N*!rrDKerrDKerrDKerrDKerrDc\
+p?qYBp?qYJs7Y"*rUp5erpBj]s8W&u!;?E[!MnlUp(*tek3hsCpAajdp?q)2Ut,D:"/PAImeHhb
+k3f%qr:U;imcNs2s8;p$p?q)2Ut,A9s8N(pbl@P5!2TV^q>gN_!MnlUpAb.!me6)Bme6)Bm\KXY
+,,FZ#me6)Bme6)KrrDKerrDKerrDKerrDKerrDKerrE*!rW)uu%KQP/!;>jSme6\\!;>jSrVnDK
+p?qYSrrE*!!:Kme!:Kme!:Kme!<<'!p?qt\!:Kme!:Kme!:Kme!:KmerW)uu*!$$=!:Kme!<<'!
+p?qYSrrE*!!:Kme!:KRKp?qkZ5kaX>mf3:emf3=\me6\\!<3'!!<<'!s8N)mme6\\!<<'!mf3:e
+mf3:emf3:emf3:ep?qYBp?qYBp@eO[e`Qi(!2TV^!quZorVurlrpBf_k5=o`V!dC5pAajdpAajS
+k3f%qr:U5gmcNs5!!DBOUt,D:"f1SKme6\Z!!W)ak3f%qqtC'i!2P,~>
+%Hd(^@Tm5E@Tlslk1/Vl!'fo%k06e->%1ZE>6"V3;Hct%;Hct%;Gpu*s8T0(;Gp[r>#JO%>#JQ(
+rr?7&rr?7&rr?7&rr?7&rr?7&rrDoq#lt#*!)cuu>#JQ#rr<&rs8N*!rs\s3s8N(&s8N(&s8N(&
+qu6Zs>5S='!*]F&!*]7!#QXo)!*]F&!*]:"rrE*!*<9:Crr?5#>#JO%>#JO%>#JQ(rr?5#s8Q8#
+s8N)urr`?%rr?7"s8N)rs%EDrs8N(&s8N(&s8N's>#JO%>#JO%^&NFW@Tm5E@TqXNe`Q;n!!)HT
+e`P+S>$>B=@Tlsle^a*Up?qYBma]kE>#JO-@Tm5EhUU0P!"RQ9>#JO5>%1Z=hUU0Emem+qma]kE
+>#JO5>%1ZEme/*Srse,Y>%1ZE>%1Z=hWEANquAtLe`P+S>$>B=@Trg3@T$B->#JO%>#J7-XT/=%
+>#J7%;Hct%;Hct%s8N(&s8N(&s8N(&s8N(&s8N(&s8N)qrs8]*rr>r#;Hct%qYpNqqu?Zrs8NN.
+>6"U&>6"U&>6"U&>5S=#!*]:""TVa+rr?7!rs/W)rr?7&rr?7"s8N*!ruD)Cs8N(&;Hct%;Hct%
+;Hct%s8N(&;ZHc#;ZHasrr3*$s8N(&qu?Zrqu9=i>6"U&>6"U&>6"U&;Hct%;Hct%;SE*W;IWg=
+>%1[lk1/V^p&G*\ma^IE;Hd75>%1Z=hUU0Eme6)BmdAWUhHEf\>%1ZE>2If[q#CoThHEf\@Tm5E
+>2If[mdC#R%dqlthHEf\@Tm5E@d`q=cMn@9mTO('@Tm5E>2JDlk553Dma^IE;Hd75>%1\8s'el0
+;Hct%;Hcsr@]]V0XBJM">#JO%>#JO%>6"U&>6"U&>6"U&>6"U&>6"U&>6"U&qYpj%s8N's>#JO%
+>5J7!!;lfr!<<'.!*]F&!*]F&!*]F&!*]:"!<?=#rriC+s8N(&qYpg$s8N(&s8N(&qu?Zrs8O)>
+>6"U&>#JO%>#JO%>#JO%>6"U&>#PD#>#PD#!<3!$!<<'!>5S@"!;ldi!*]F&!*]F&!*]F&!)cuu
+>#JO%>#N'6HW"<V@Tm5EhWEANme-V\mdAWfbu._K@Tm5E>2If[mdBf:p?qA!e_XJ->$>B=@TqX=
+ebK1Te_XJ->%1ZE>$Be5eaDl(!"SGIe_XJ->%1ZE>%6pn.=_~>
+s7-PkV4j`ZV4i=ok2,D$!#Y.\k14g?Tr"HZU&Y.hSY;UJSY;UJSWQ>=!$XgnSY;UJSY;UJSY?)`
+!29Gm!29Gm!29Gm!29Gm!29Gm!;c^%!<<'!SY;UJSY>o[!!)orrrE*!%03+%rrAbmrrAbmrrAbi
+rrE+nqu6g"U&Y,mU&+cp!<<'!U&Y,mU&4li!<<'>!29Gm!25sWSY;UJSY;UJSY?)`!25t`s.Q"`
+rrE&u"9AK%!29;irrDrr3<5cQrrAbmrrAbmrrAU`SY;UJSY;V.s0e&`Tr"HZIGX,ClL+3C!:oR7
+k14g?Tr"HZTmbqSg?S,*ndk0Rg=kP7NM3&BTr!1sg=l?&%bfojNM32BV4i=sg=ki[r;[>mg=kP7
+NM32BV4jaZp0l5Gs7-PkV4j`ZV4i=ok2,D$!#Y.\k14g?Tr"HZU&Y.hSY;UJSY;UJSWQ>=!$Xgn
+SY;UJSY;UJSY?)`!29Gm!29Gm!29Gm!29Gm!29Gm!;c^%!<<'!SY;UJSY>o[!!)orrrE*!%03+%
+rrAbmrrAbmrrAbirrE+nqu6g"U&Y,mU&+cp!<<'!U&Y,mU&4li!<<'>!29Gm!25sWSY;UJSY;UJ
+SY?)`!25t`s.Q"`rrE&u"9AK%!29;irrDrr3<5cQrrAbmrrAbmrrAU`SY;UJSY;V.s0e&`Tr"HZ
+IGX,ClL+3C!:oR7k14g?Tr"HZTmbqSg?S,*ndk0Rg=kP7NM3&BTr!1sg=l?&%bfojNM32BV4i=s
+g=ki[r;[>mg=kP7NM32BV4jaZp0l8Hs7-PkV4j`ZV4i=ok2,D$!#Y.\k14g?Tr"HZU&Y.hSY;UJ
+SY;UJSWQ>=!$XgnSY;UJSY;UJSY?)`!29Gm!29Gm!29Gm!29Gm!29Gm!;c^%!<<'!SY;UJSY>o[
+!!)orrrE*!%03+%rrAbmrrAbmrrAbirrE+nqu6g"U&Y,mU&+cp!<<'!U&Y,mU&4li!<<'>!29Gm
+!25sWSY;UJSY;UJSY?)`!25t`s.Q"`rrE&u"9AK%!29;irrDrr3<5cQrrAbmrrAbmrrAU`SY;UJ
+SY;V.s0e&`Tr"HZIGX,ClL+3C!:oR7k14g?Tr"HZTmbqSg?S,*ndk0Rg=kP7NM3&BTr!1sg=l?&%
+bfojNM32BV4i=sg=ki[r;[>mg=kP7NM32BV4jaZp0iI~>
+s8NJpp?qYBp?o$Mp?))H!#YFtp?&1-me6)Bmf3=\me6)Bme6)BmbV^W!$Z17me6)Bme6)Bme6\\
+!;?Hm!;?Hm!;?Hm!;?Hm!;?Hm!;c^%!<<'!me6)Bme6MW!!)orrrE*!%06,%rrDcmrrDcmrrDci
+rrE,nqu6g"pAb-mpA4dp!<<'!pAb-mpA=mi!<<'>!;?Hm!;>jSme6)Bme6)Bme6\\!;>j\s7Ym\
+rrE&u"9AK%!;?<irrDrr9E=edrrDcmrrDcmrrDK\me6)Bme6)Ks7Y"2me6)BXR>fEp@eLd!<;c\
+p?&1-me6)Bm\K:5k4\NKpAaj[k3hZ5eaDl!me3IEk2uI>s6^;keaE/!p?naEk2uC2r;[?$k3hZ5
+eaE/!p?qYSs.%:4$h!`Vp?qYBXR>fEpA=n-p?qY:Uu(P5me6)Ks7YmSme6)Bme6)*CAe,VC>SCP
+me6)Bme6)Bs8N)ms8N)ms8N)ms8N)ms8N)ms8N)qrs8]*rrDK\me6)BqYpNqqu?Zrs8NN.pAb-m
+pAb-mpAb-mpA=jj!;?<i"T\8rrrDchrs/W)rrDcmrrDcis8N*!ruD+5s8N)mme6)Bme6)Bme6)B
+s8N)mmf3=\mf3:err3*$s8N)mqu?Zrqu9=ipAb-mpAb-mpAb-mme6)Bme6)Bmf3=\eaDl!me3aM
+p?))Brr<'!p?qY:Uu(P5me6(EmcN[*pAajdp@dY:m\JD$me6)BV!dC-q#LH_%&DGAp?qYBV!dC-
+p@eFb%ef&Qm\JD$p?qYBpAb/_bl8(=p?qYBp?o$Mp?))H!#YFtp?&1-me6)Bmf3=\me6)Bme6)B
+mbV^W!$Z17me6)Bme6)Bme6\\!;?Hm!;?Hm!;?Hm!;?Hm!;?Hm!;c^%!<<'!me6)Bme6MW!!)or
+rrE*!%06,%rrDcmrrDcmrrDcirrE,nqu6g"pAb-mpA4dp!<<'!pAb-mpA=mi!<<'>!;?Hm!;>jS
+me6)Bme6)Bme6\\!;>j\s7Ym\rrE&u"9AK%!;?<irrDrr9E=edrrDcmrrDcmrrDK\me6)Bme6)K
+s7Y"2me6)BXR>fEp@eLd!<;c\p?&1-me6)Bm\K:5k4\NKpAaj[k3hZ5eaDl!me3IEk2uI>s6^;k
+eaE/!p?naEk2uC2r;[?$k3hZ5eaE/!p?qYSs."T~>
+s5j;jr`TS:>$=P"hUU0ErW!/jk2+sr5t_)Z"(L-eF8f&;9)_]g9)_]j8hi=ur_`_gr_`_gr_a;"
+s8N'ks8N'ks8N'ks8N'krr3*ns8N'krr36(s8N*!rr>qhr_`bh;Z6Xp!!#pqs8N'19)nnk9)nnk
+9)nnk9)nnk9)JVi!(p/errrHqs8N'k;Z?[u!<<'!rr3-os8N'k;Z6Xq!!l3srr>[krr>[j;?0>g
+;?0>g;@H1trr>Yh;ZHbps8N)urriE&rr>YhrVult!D68frrE*lrr39ss8N'ks8N's9)_]g9)_]t
+c2UsF;Hd75>"YmQe^aTc&*Da*X?fH^>%1Z=60?GBk5=WPk1.`=5tY<ir`TFjk0;H=r9aaNe]m5B
+9)Vos@R9/$e`Q`/"P(cZ5t_)Z"CbR&mP2uds5j;jr`TS:>$=P"hUU0ErW!/jk2+sr5t_)Z"(L-e
+F8f&;9)_]g9)_]j8hi=ur_`_gr_`_gr_a;"s8N'ks8N'ks8N'ks8N'krr3*ns8N'krr36(s8N*!
+rr>qhr_`bh;Z6Xp!!#pqs8N'19)nnk9)nnk9)nnk9)nnk9)JVi!(p/errrHqs8N'k;Z?[u!<<'!
+rr3-os8N'k;Z6Xq!!l3srr>[krr>[j;?0>g;?0>g;@H1trr>Yh;ZHbps8N)urriE&rr>YhrVult
+!D68frrE*lrr39ss8N'ks8N's9)_]g9)_]tc2UsF;Hd75>"YmQe^aTc&*Da*X?fH^>%1Z=60?GB
+k5=WPk1.`=5tY<ir`TFjk0;H=r9aaNe]m5B9)Vos@R9/$e`Q`/"P(cZ5t_)Z"CbR&mP3#es5j;j
+r`TS:>$=P"hUU0ErW!/jk2+sr5t_)Z"(L-eF8f&;9)_]g9)_]j8hi=ur_`_gr_`_gr_a;"s8N'k
+s8N'ks8N'ks8N'krr3*ns8N'krr36(s8N*!rr>qhr_`bh;Z6Xp!!#pqs8N'19)nnk9)nnk9)nnk
+9)nnk9)JVi!(p/errrHqs8N'k;Z?[u!<<'!rr3-os8N'k;Z6Xq!!l3srr>[krr>[j;?0>g;?0>g
+;@H1trr>Yh;ZHbps8N)urriE&rr>YhrVult!D68frrE*lrr39ss8N'ks8N's9)_]g9)_]tc2UsF
+;Hd75>"YmQe^aTc&*Da*X?fH^>%1Z=60?GBk5=WPk1.`=5tY<ir`TFjk0;H=r9aaNe]m5B9)Vos
+@R9/$e`Q`/"P(cZ5t_)Z"CbR&mP04~>
+s6f`W"b",EhVRPs!!`#Zio[shNVoJ%lMn/\R@Tb:R@Tb:R@TaWBpkN[SXH%:SXH%:SXKNX!1Ele
+!1Ele!1Ele!1Eid"I];i!1Eid%06G.!<<'!SXH%:SXH&Is8DuuSc/Tg!"bRurrAJerrAJerrAJe
+rrAJarrN1gSc&Kl!1Ele!1BDWrrW9$rrE&u"e#Dj!1BDVs8N'ARK*9eRK*9eR@Tb:R@Tb:R@Tb:
+RK*9eR@TcGs.02i!<3!%!<<'!R@X<Vrr<(fSc&Kg!1Eid'q,+%!1Ele!1fOKR@Tb:R@W@;ToGK=
+Ta#qZiniPWmf)b\lJgs?BoW%a%rLI_hWjOso'Yr2hV.+/NVoI\D<BR/lL+*2mdBAsg?*73r1O71
+k1\\WqZ$cUg?*73qk4)bnmTfCs6f`W"b",EhVRPs!!`#Zio[shNVoJ%lMn/\R@Tb:R@Tb:R@TaW
+BpkN[SXH%:SXH%:SXKNX!1Ele!1Ele!1Ele!1Eid"I];i!1Eid%06G.!<<'!SXH%:SXH&Is8Duu
+Sc/Tg!"bRurrAJerrAJerrAJerrAJarrN1gSc&Kl!1Ele!1BDWrrW9$rrE&u"e#Dj!1BDVs8N'A
+RK*9eRK*9eR@Tb:R@Tb:R@Tb:RK*9eR@TcGs.02i!<3!%!<<'!R@X<Vrr<(fSc&Kg!1Eid'q,+%
+!1Ele!1fOKR@Tb:R@W@;ToGK=Ta#qZiniPWmf)b\lJgs?BoW%a%rLI_hWjOso'Yr2hV.+/NVoI\
+D<BR/lL+*2mdBAsg?*73r1O71k1\\WqZ$cUg?*73qk4)bnmTiDs6f`W"b",EhVRPs!!`#Zio[sh
+NVoJ%lMn/\R@Tb:R@Tb:R@TaWBpkN[SXH%:SXH%:SXKNX!1Ele!1Ele!1Ele!1Eid"I];i!1Eid%
+06G.!<<'!SXH%:SXH&Is8DuuSc/Tg!"bRurrAJerrAJerrAJerrAJarrN1gSc&Kl!1Ele!1BDWr
+rW9$rrE&u"e#Dj!1BDVs8N'ARK*9eRK*9eR@Tb:R@Tb:R@Tb:RK*9eR@TcGs.02i!<3!%!<<'!R
+@X<Vrr<(fSc&Kg!1Eid'q,+%!1Ele!1fOKR@Tb:R@W@;ToGK=Ta#qZiniPWmf)b\lJgs?BoW%a%
+rLI_hWjOso'Yr2hV.+/NVoI\D<BR/lL+*2mdBAsg?*73r1O71k1\\WqZ$cUg?*73qk4)bnmR%~>
+s8W)l!:Kj[!OUDVmJut[!!`JsmdAVihZ!3Rme6\\p?qABrpBd[rpBm^m[UBXmJut[mJut[mLf0\
+s8N)es8N)es8N)es8N)err3,hs8N)err33's8N*!rrDclmK3+Mmf!1b!!)Hcs8N'1mf3:emf3:e
+mf3:emf3:emed"c!:K:QrrrJks8N)emf*4g!<<'!rr3/is8N)emf!1c!!hrlrrDKerrE&d!;?E[
+!;?E["SV9`rrE&ds8N2hs8N)urriE&rrDKTrVults6fgb!<DQers8&mrrDKerrDclmJut[mL/ag
+s6eG"p?qYJ[+50Ds7Qg"pAajSma[QYp?qqR&!ZMEme6\Ss7ZKdmcNr%ec#1QmZd/%me6\Ss7ZKd
+mcNr%ec,7Hme2n5k3hs?!!M`PmZc9$p''mXpAb/gbQ%S8!:Kj[!OUDVmJut[!!`JsmdAVihZ!3R
+me6\\p?qABrpBd[rpBm^m[UBXmJut[mJut[mLf0\s8N)es8N)es8N)es8N)err3,hs8N)err33'
+s8N*!rrDclmK3+Mmf!1b!!)Hcs8N'1mf3:emf3:emf3:emf3:emed"c!:K:QrrrJks8N)emf*4g
+!<<'!rr3/is8N)emf!1c!!hrlrrDKerrE&d!;?E[!;?E["SV9`rrE&ds8N2hs8N)urriE&rrDKT
+rVults6fgb!<DQers8&mrrDKerrDclmJut[mL/ags6eG"p?qYJ[+50Ds7Qg"pAajSma[QYp?qqR
+&!ZMEme6\Ss7ZKdmcNr%ec#1QmZd/%me6\Ss7ZKdmcNr%ec,7Hme2n5k3hs?!!M`PmZc9$p''mX
+pAb/gbl@\9!:Kj[!OUDVmJut[!!`JsmdAVihZ!3Rme6\\p?qABrpBd[rpBm^m[UBXmJut[mJut[
+mLf0\s8N)es8N)es8N)es8N)err3,hs8N)err33's8N*!rrDclmK3+Mmf!1b!!)Hcs8N'1mf3:e
+mf3:emf3:emf3:emed"c!:K:QrrrJks8N)emf*4g!<<'!rr3/is8N)emf!1c!!hrlrrDKerrE&d
+!;?E[!;?E["SV9`rrE&ds8N2hs8N)urriE&rrDKTrVults6fgb!<DQers8&mrrDKerrDclmJut[
+mL/ags6eG"p?qYJ[+50Ds7Qg"pAajSma[QYp?qqR&!ZMEme6\Ss7ZKdmcNr%ec#1QmZd/%me6\S
+s7ZKdmcNr%ec,7Hme2n5k3hs?!!M`PmZc9$p''mXpAb/gJ,~>
+s5"&[>#JO%>#It-k5O4#mJutKmcNYH0iCnQ;Hcu*s/\gj8lA8Z8lA8Z8lAPZ;G'hZ;G'hZ;G'hZ
+;G$oh;G$oh;G$oh;G$oh;G-og"A/Xo;G-og%8$U#;?-\h;G'hZ;G'jc!!>hk8lGTf&kZ%o!!#nh
+!!#nh!!#nh!!*'!rW)uu!ru4k;Z$M!;G$oh;G'jd!!?+!!)!4j"\Jap;G'jc!$Y$58cSih8cSih
+8lA8Z8lA8Z8lA8Z8cSih8lA7]!)`ds9)\eo8cSih8lGTf"%lH`;Z$Lq;G-og)bL)1;G$oh8lA8Z
+8lA8Z;ZHbh8m5+r;Hc\-k5O3MmJm7TmcNYH0iCnQ;HcsYhVQfY!<:m_3D*1I>#JNahVQfY!<:m_
+3D*1Q;HcsYhVQf^!<;Kd!<:m_3D*1Q;Hct%k2n,;s8Up^;Hct%;HcsjC?GNP4mi=DmdB6"C,&Ua
+>#JO%[/[4";G'hZ;G'hZ;G'hb8lA8Z8lA8Z8lA8Z8lA7]!)cDh!)cDh!)cDh!)cGg!!Gmo!)cGg
+!"DO#!)`ds8lA8Z8lA8Zr;Zpl;G'jc!"qn%8cSih8cSih8cSih8cSkks8E#urrW7!8lGQe##\%n
+!)cEerW!$u!!#Xj!!Psp!)cEer;\$6;G$oh;G$oh;G'hZ;G'hZ;G'hZ;G$oh;G'hZ!!#ms!)!4j
+"\Jap;G'jc!!>hk8lGQe!E)Ph!#nN1!)cDh!(p-];G'hZ;H!Pp8kN8b>#JNrC?GNP'(,`"mdB6"
+C,&Ua>#JO%3SrWCq#LHO$9:^V;Hct%3SrWCq#LHO$9:^V>#JO%3SrWCrW)udrW)uT$9:^V>#JO%
+>3=rrcN!q$#uXr)>#JO%8o!MfhEC9,p?qA2k%ZVK;Hct%;RHJ*8lA8Z8lA8Z8lA8Z;G'hZ;G'hZ
+;G'hZ;G'hZ!!#nh!!#nh!!#nh!!#nhrW!'n!!#nhrW!C"!!#ms!(p-];G'hZ;Z-Rt8lA8Zr;[I&
+;G$oh;G$oh;G$oh;G$ohs8W&us8N0$;G'jb!!Z=n!!#nh;Z6Xu;?-\hrW!*o!!#nh;Z-S>8lA7]
+!)cDh!)cEe8lA8Z8lA8Z8lA7]!)cEe8cSih!!#Xj!!Psp!)cEer;Zpl;G'jb!!,tirW!m0!!#nh
+!!#Vh8lA8Z8lARes%5me;Hct%8o!Mfh@f5V!:K:;k%ZVK;Hct%;E<UjebK4Fh?l88;Gp[r=ukHr
+ebK4Fh?l88;Hct%;E<Ujec#RKmf!4dh?l88;Hct%;Hi5F.=_~>
+s6BHOs+q3Iinihc!;?!Ok2qY7NVo=Kf)O%WRK!9eRK!9eRK!9eRK!9eRJm0hR/d5TRJm0iR/d5T
+!!)h_r;cear;chbrrE(errE(errE(errE*!rW)uu!!*"dquHbbrrE%drW!%g!!&Gd!!8Pg!</Db
+!</Dd!<8Je!:uWY!<&>c!!AVh!1Efd!gs#grgE]brL*Q`s-`id#+5GkR@+$Tq3_AVs8RM,r13kE%
+Hc[,k3`3Lo'YZ&NFe+ISHEH_injJ2s5F&jM>WnHA`D_+q#LHS!G.,cSHEH_injY7!UfOX!<;$ZA
+Vp;Ts6]kqc2[h/qORYC%Hc[,k3`6Co'YZ&NFe+ISH@CBcK1Jo!<8Je!<8Je!<8Je!<8Jd!!J\i!
+1B8S!!Sbj!1<feq3h0]rL*TargEcds-`les-`les-`les8W&us8N'!rgEZas-`lergE`c".9,hR
+Jm0fR/d6dRJd-bRK!9eRK!9YRK!9cRK!6hR/d5TrW!"f!!*"dr;ceaquHbbrW!.j!!&FT!!)h_"
+J,SmI?"/qs+q3Iinihc!!)TXk2qY7NVo=LA`D_+q#LHS!G.,cSHEH_injJ2s5F&jM>WnHA`D_+r
+Vuueo)8XhiW3VIqjmcT!+F1Qs6BHOs+q3Iinihc!;?!Ok2qY7NVo=Kf)O%WRK!9eRK!9eRK!9eR
+K!9eRJm0hR/d5TRJm0iR/d5T!!)h_r;cear;chbrrE(errE(errE(errE*!rW)uu!!*"dquHbbr
+rE%drW!%g!!&Gd!!8Pg!</Db!</Dd!<8Je!:uWY!<&>c!!AVh!1Efd!gs#grgE]brL*Q`s-`id#
++5GkR@+$Tq3_AVs8RM,r13kE%Hc[,k3`3Lo'YZ&NFe+ISHEH_injJ2s5F&jM>WnHA`D_+q#LHS!
+G.,cSHEH_injY7!UfOX!<;$ZAVp;Ts6]kqJ,~>
+s8NDnp?qYBp?pJ4pAXIirrE)mp?qXUPhtj%me6)Js"!O2me6)Bme6)Bme6ABp?qYBp?qYBp?qYB
+p?hn\p?hn\p?hn\p?hn\p?qn["RZ6ip?qn[%IO2rp&G*\p?qYBp?qYQ!!DZ_me6SZ'(5J]!!)`\
+!!)`\!!)`\!!*'!rW)uu!s&&_pA=mpp?hn\p?qYR!!Dop!:Kgd"mu?jp?qYQ!$^k)mJm7\mJm7\
+me6)Bme6)Bme6)BmJm7\me6&K!;6Bmmf!1imJm7\me6SZ"7GmNpA=mkp?qn[)t!\+p?hn\me6)B
+me6)Bmf3=+eaDl!me524pAXIjrr<&mp?qXUPhtj%me6(5rpKR^s6^,VeaDl!me2nEmeHk_mK]!,
+me6)BmZd_=rVuums8E#umL#3/me6)Bme6\\SBLp=me6)Bme6)!XS2Y]%fZP/p@dqJXH_T0p?qYB
+rr4M:p?qYBp?qYBp?qYJme6)Bme6)Bme6)Bme6&K!;>g\!;>g\!;>g\!;>j[!!M]i!;>j[!"J>r
+!;6Bmme6)Bme6)Br;Zrfp?qYQ!#"_nmJm7\mJm7\mJm7\mJm7es8E#urrW8pme6PY#57Hb!;>jS
+rW!&o!!)Hd!!Vcj!;>jSr;\&0p?hn\p?hn\p?qYBp?qYBp?qYBp?hn\p?qYB!!)]m!:Kgd"mu?j
+p?qYQ!!DZ_me6PY!VYs\!#t>+!;>g\!:KRKp?qYBp?qt\`RXDEp?qY)XS2Y]&,uV0p@dqJXH_T0
+p?qYBPlC+H!<;HlPh#3ip?qX=rpKR^s6^,VeaE/!p?n1Emf!1epAb*ls6^5YeaE/!p?qYSs.%=5
+$1@NTp?qYBeZAKDmLK6ss7Z0Sp8jM8me6)Bmf*5:me6)Bme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+!!)`\!!)`\!!)`\!!)`\rW!)h!!)`\rW!Dq!!)]m!:KRKp?qYBpAFsnme6)Br;[Jup?hn\p?hn\
+p?hn\p?hn\s8W&us8N0$p?qYP!!`/b!!)`\pAP$op&G*\rW!,i!!)`\pAFt8me6&K!;>g\!;>jS
+me6)Bme6)Bme6&K!;>jSmJm7\!!)Hd!!Vcj!;>jSr;Zrfp?qYP!!2f]rW!o*!!)`\!!)H\me6)B
+me6)Ks2EOVme6)BeZAKDmLT<t!;?-Sp8jM8me6)BmZd_=q#LH_#F*d,me6)BPlC+H!<;HlPh#3q
+me6(5rpKac!VZQm!<;HoPh#3qme6)Bs8SU>~>
+!T)B&;@Y^Ok2+tWmdBf2k05>89)MQiHiN5#62jIV62jIY5tXa8r^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m2W9)APi!(ojLr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/V
+r^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr^m/Vr_!2Vr^m/Vr^m>[
+MuUIN9)DKr3L&[_hW=e<p?(M^.61#u;?/0FhY@-RhW?7Qr)*MDrndGN"5`/h62XU\.K83(!<2Bj
+p&G*Ljs`Un;?H";.F%knhUVF"%QTd9hVRD_me5f*bpbYFr)*ZEs5lp>r^m/Vr^m8Y8kMDK8cV0V
+8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V
+8cV0V8cV0V8cV0V8cV0V8c_4MqYpWt8kMDK8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V
+8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V8cV0V
+8cV0V9)h3V8cV0V8d.M=s1LEbqbdnaPigiZjo>DTk2so;3D03I!%Ip(q#CNRjs`Uo;?/0FhY@-R
+hW?7Qr)*MDrndYTrpC!a!!(m<.7*i/!p8>gcMmq%ebN)Q3L&[_hWF7op?(M^.61#u;?V@Hk"7r=
+8cV0V8cq@O8jWGK!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV
+!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!C9?SrrW6n8jWGK!($TV!($TV!($TV!($TV
+!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV!($TV
+!($TV!($TV!($TV!($TV!($TVs$?WV!($TV"[S(H]fA^^;@Y^Ok2+tW!!)`Tk05>89)MQe.K83"
+!!D*?.7*l0!%Ip(q#CNRjs`Uo;?/0FhZ!TTmKW@b!8cie62OO]k2%P;~>
+!UAhCSITM:k2PC_mdfr:lIK*TOo1b\[f>c`Q'mo*Q'mo*Q'mo&R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*RJQr,!0rt;R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*Q'mo*Q'mo*
+Q+m:PH&\6iSITM:k2PC_!!)TXlIK*TOo1aP<T`<#q#LHW!EG!SSHDmSio9b6s5j>^M>WnJ<T`<#
+!!*#d#4_`ok2o[#qjdfVl=%s;!UAhCSITM:k2PC_mdfr:lIK*TOo1b\[f>c`Q'mo*Q'mo*Q'mo&
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*RJQr,!0rt;R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*Q'mo*Q'mo*Q+m:PH&\6iSITM:k2PC_!!)TXlIK*TOo1aP<T`<#q#LHW!EG!S
+SHDmSio9b6s5j>^M>WnJ<T`<#!!*#d#4_`ok2o[#qjdfVl=&!<!UAhCSITM:k2PC_mdfr:lIK*T
+Oo1b\[f>c`Q'mo*Q'mo*Q'mo&R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*RJQr,!0rt;R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*
+R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*R?a2*Q'mo*Q'mo*Q+m:PH&\6iSITM:k2PC_!!)TX
+lIK*TOo1aP<T`<#q#LHW!EG!SSHDmSio9b6s5j>^M>WnJ<T`<#!!*#d#4_`ok2o[#qjdfVl=#2~>
+s8NE!me6)Bme6@U`Vo6)p(.2sp?%:7hY-C2me6ASs7ZH[!;?E[!;?<X!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!qu'MqYpTsme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?BZ!;?E[%
+ef>as8TI_me6)Bme3a$rU0[c%0-%pk)6=tp?qYBp4NA4q#LH_#D::pp?qYBKDt<7!<;HlK?a,Xp
+?qX,rpKdd'))A!rr<&emXrdXme6)Bmf3<_bPqnBme6)Bme6@U`Vo6)p(.2sp?%:7hY-C2me6ASs
+7ZH[!;?E[!;?<X!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!
+;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!qu'MqYpTsme6YJ!;?E[!;?E[!;?E[!;?E[!
+;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!
+;?E[!;?E[!;?E[!;?E[!;?E[!;?BZ!;?E[%ef>as8TI_me6)Bme3a$rU0[c%0-%pk)6=tp?qYBp
+4NA4q#LH_#D::pp?qYBKDt<7!<;HlK?a,Xp?qX,rpKdd'))A!rr<&emXrdXme6)Bmf3<_bl8"Cm
+e6)Bme6@U`Vo6)p(.2sp?%:7hY-C2me6ASs7ZH[!;?E[!;?<X!;?E[!;?E[!;?E[!;?E[!;?E[!
+;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!
+qu'MqYpTsme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!
+;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?BZ!;?E[%ef>as
+8TI_me6)Bme3a$rU0[c%0-%pk)6=tp?qYBp4NA4q#LH_#D::pp?qYBKDt<7!<;HlK?a,Xp?qX,r
+pKdd'))A!rr<&emXrdXme6)Bmf3<_J,~>
+/^;g<;G'hZ;G'PI0pLhWk2uC2mZ]FK3D)nA8lA8Zec1P"5tXF85tXF85tXaM5tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXF85tV.Vs8E"J8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'8
+8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'8
+8jQ'A5tXF85tXF8k5T0^8lA8Z8lA8I0pLhWs5s@T&FPc;+?<%d;G'hZ+Pu8;k2uX1&GGPSjrcr^
+8lA8Z+Pu8;k2uX1&GGPSjrcr^;G'hZ+Pu8;k2uX1%ef>Qjrcr^;G'hZ;UsVQc2TB?eOi_3;G'hZ
+8jP1rk2,7_p@dp=0d&JK8lA8Z8lF4>Mb69-5tXF85tXF88le5M5tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF8!<3#t!.RU,8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'8
+8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88kMBA5tXF8
+5t^;>C-bHi8lA8Z8jP1rk2-.#s7R#lPVF:@8kMuR;G&(gk2,7_rU(6jmcNXS5tXaI8l?egk2,7_
+rU(6jmcNXS5tY$I;G&(gk2,7_rU(0hmcNXS5tY$I;G'j;hC6bM/^;g<;G'hZ;G'PI0pLhWk2uC2
+mZ]FK3D)nA8lA8Zec1P"5tXF85tXF85tXaM5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF8
+5tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tXF85tV.Vs8E"J
+8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'8
+8jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'88jQ'A5tXF85tXF8k5T0^8lA8Z
+8lA8I0pLhWs5s@T&FPc;+?<%d;G'hZ+Pu8;k2uX1&GGPSjrcr^8lA8Z+Pu8;k2uX1&GGPSjrcr^
+;G'hZ+Pu8;k2uX1%ef>Qjrcr^;G'hZ;UsVQJ,~>
+!TN8;R1=pVWoiI/lLsr>Wa/GHOo(OJk5W/fPlLg`s8E"]Pm*TDs/LL,qj@qJ?)m&LlK\*:m]'Ph
+H'/#m%nu!Fk3D7"mdfrBmcrq.L&@>L9]G3slK[g*o()MBlK1cor0\'hio]CglL+*2o(MM:k"LL+
+RK)CL@EnfQio^')%Y\2gk2tsop@dpS>u5g/qj@NJs1Y+j!!*#urW&+H"e"fYWdTm(R1=pVWoiI/
+lLsr>Wa/GHOo1UX9]G3slK[g*o()MBlK1cor0\'hio]CglL+*2o(MM:k"LL,R1E!Nk2tsomdBZ:
+p?q5.9SNA3s5j;icMmq)k4tDTKjC_@k3D7*p?nqd:jJ3#R0)ON^7UYj!<3#t!0WTNRI:*TI?",l%
+Y\2gk2tsop@dpS>u5g/r0\'hio]CglL+*2o(MM:k"LL,R1E!Nk2tsomdBZ:p?q5.9SND4%nu!Fk
+3D7"mdfrBmcrq.L&7;<joAh?~>
+s8W)d!;?BZ%b6KVp?qYJs8Vf3MhA_*rpFInme6\\p@dqJme6)Bme6)Bp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qVSrr;rtGP:Iume6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+p?qYBp?qYBpAb0d`SU%NpAXIkeVhE?me6ASs7XEiK>$F8pAXI^KC8I$rV$6js7QN^K?aA_"SRK9
+p?qnQrr<#l!q(]crpBs`mXss$meukYs8VcomXrd`mKN=Pmf3<WbQ%S0!;?BZ%b6KVp?qYJs8Vf3
+MhA_*rpFInme6\\p@dqJme6)Bme6)Bp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qVSrr;rtGP:Iu
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bp?qYBp?qYBpAb0d`SU%NpAXIk
+eVhE?me6ASs7XEiK>$F8pAXI^KC8I$rV$6js7QN^K?aA_"SRK9p?qnQrr<#l!q(]crpBs`mXss$
+meukYs8VcomXrd`mKN=Pmf3<Wbl@\1!;?BZ%b6KVp?qYJs8Vf3MhA_*rpFInme6\\p@dqJme6)B
+me6)Bp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qVSrr;rtGP:Iume6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bp?qYBp?qYBpAb0d`SU%NpAXIkeVhE?me6ASs7XEiK>$F8pAXI^
+KC8I$rV$6js7QN^K?aA_"SRK9p?qnQrr<#l!q(]crpBs`mXss$meukYs8VcomXrd`mKN=Pmf3<W
+J,~>
+s3:=2$ooG.PeH4uUfnTP0gYY.AsE>h;F*</3C,Yk3C,Yc5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4krW%.&5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k3C,Yk3C,Yk
+V#ReV3D)U78dm^&;O"lW`M?ZS(bn>R8c]LcrndV9s6^$`md:WPr(6u$k5O69k5XiPp?q>[62X=U
+&E`uKrT=.J"SV9O&4-1c!nGOMc2[ggpdtrT+B"H;k/F-"(`4tnqFY@as7T>V3C,Yk3C,Yk3B9Ac
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rnoEG<%rL5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rgqk3C,Yk3C0J@ZnXR562O7_3?V4a^#m;0=r8)262O7T&E`uKrT=.J"SV9O
+&4-4d!>+DmhYlU:mKE7OmLV\^8c]LcrndV9s6^$`md:WPqapq?bq[NDs3:=2$ooG.PeH4uUfnTP
+0gYY.AsE>h;F*</3C,Yk3C,Yc5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4krW%.&5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k3C,Yk3C,YkV#ReV3D)U78dm^&;O"lW
+`M?ZS(bn>R8c]LcrndV9s6^$`md:WPr(6u$k5O69k5XiPp?q>[62X=U&E`uKrT=.J"SV9O&4-1c
+!nGOMJ,~>
+,3%IIQ'mo*Q'n&*I8G'_b3%-XI7-b?KpA'kR?a2*^An&#Srs!POHCg2s42%<Od2?"R?a2*I8G'_
+b3%-XI7-b?KpA'kR?a1.k2POcrTXs^o(MMB7"LboQ'mn*k2POcrTXs^o(MMB7"LbkR?a1.k2POc
+rTXp]o(MMB7"LbkR?a2*k2Kgos!$IZR?a2*R?a2.Q$lJOV97rKZ@,,7AVHD;Q'mo*Q+m:pSXtuC
+!0E<gb5^%0JWZ4cQ'mo*Q$lJOV97rKZ@,,7AVHD;Q'mo*7-<Lkk5FQVmdg)>njJ%sR?a2*7-<Lk
+k5FQVmdg)>njJ%sQ'mo*7-<Lkk5FQUmdg)>njJ%sQ'mo*Q0.(7cMo*JhO0XsQ'mo*R?`1sFf!7C
+d^"9h9P&pCR?a2*R?bMdqOO4?rW&%B,g-/<D1Rh7R?a2*R?`1sFf!7Cd^"9h9P&pCR?a2*R7-2s
+k2uX-&FT,_md`bsR@0>.Psjcok2uX-&FT,_md`bsR?a2*R7-2sk2uX-&+9#^md`bsR?a2*R?cpo
+@=S~>
+s8O27me6)Bme6ABc&8+2hY-*VS9'=QhX:+*p?qYBpAb/`mf!3JmND6'p8lO$me6)Bme6(nMk%cC
+p?'ViF+^">me6)Bme1`#mK*%LrUpTupA]3Yp@dqJmW8?p!VYs[p'Uins)ZHYme6)BF8bM-p?qnQ%
+KH/%F3XFHp?qYBs8Sn<ru^t&p?qYBp@dq!Mk%cCp?'ViF+^">me6)Bme6)Bs8SYXrW&&J+SPj/X
+Nfnqp?qYBp?p1`SAj@Yk09E;K:Lfdp?qYBp2g3#!VYs[p'Uins)ZHYp?qYBF8bM-p?qnQ$NKi"F
+3XFHp?qWqrU'^[meuhgs7ZJ6c1^T!me6)Ks.mm=+85-rme6)Bp?p1`SAj@Yk09E;K:Lfdp?qYBp
+?qYSs./TW!0HUkpAaifc0"Hfme6)Bm`gZ[`SU=Nc(&j-SDN]-me6)BF8bM-p?qnQ$NKi"F3XFPm
+e6'irU'^[meuhds7ZJ6c1^T!me1`#mK*%LrUp^#pA]3Yp?qYBp?qt\Ujr~>
+s2>")9)_*V9)LsU+;"MX#S7h%.60[d5t_,B"\M)"s5lrQ5l`qE5m',55rnp1!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1!D
+!'1$E#rt;0s8PAF5s\-B5laOU5li)>rWi]>(b$mo5t_,B!_Pa$oEYF.r]pWY5sZXc#QkW(5t_,B
+!$Ln>!t[aa9)_*Y9#]%(c2[g_!C9?W5laOT5li)>rWic@(b$mo5tXF8r]p][6,ild9)_*V3W;;H
+3C,qkr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNE
+r]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNE
+r]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNEr]pNE
+r]pNEr]pNEr]pNEr]pNErBUEDr]piN6&YdC5rh4s9)_*V9)V$V+;"MX"qVV#.60[dr]pTX5p5e*
+!"f,q"%kjF+S5pA&4&TSr]pN,oEYO15s\-B5m'`ubpgs<s2>")9)_*V9)LsU+;"MX#S7h%.60[d
+5t_,B"\M)"s5lrQ5l`qE5m',55rnp1!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E
+!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1$E!'1!D!'1$E#rt;0s8PAF5s\-B5laOU5li)>
+rWi]>(b$mo5t_,B!_Pa$oEYF.r]pWY5sZXc#QkW(5t_,B!$Ln>!t[aa9)_*Y9#]%(J,~>
+%bfd%Q'%>oQ'%2oNIb5#r]CcX6rdfLNKoWkOd2&oQ/;Q/R=UL%OV,2)s,hG\Od2&oOd2&oNIb5#
+r]CTS6rdfLNKoWkOd2&7oK3@HJWZ([Od05E49n9*Od2&oO^7TA$:KH-Q'%>oQ/:M/c2S:-hN=(c
+Q'%>oOd1oW=[`6O&O8`aAV#i+Od2&oOd23gs6c;+OfXZW])VemFbu6GOd2&oOd1oW=[`6O$p[3\
+AV#i+Od2&oO^7TA#=O-*Od2&o?1^5a7"LJcOd2&7oK3IKJWZ4[Q'%?giaL.4%bfd%Q'%>oQ'%2o
+NIb5#r]CcX6rdfLNKoWkOd2&oQ/;Q/R=UL%OV,2)s,hG\Od2&oOd2&oNIb5#r]CTS6rdfLNKoWk
+Od2&7oK3@HJWZ([Od05E49n9*Od2&oO^7TA$:KH-Q'%>oQ/:M/J,~>
+s8Vi]!nEffrc86XF,Qj=k54QIp?qq[!Uf[\mJut[mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?BZ!;?E[s7ZKm
+"R`t[me6MF!nEffrc86XF,Qj=k54QHV"A^/Hd2KV!2T7.!IN)hmJs'TErgX4qsOLa!1_74p[/+5
+S9t6V"_r+:Us8'!mK*%Lrr3#epAXI[pAXI^p?qABrpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[
+rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rpBd[rU'[ZrpKg[s8N5i^#&2N
+qX+F8S9t6V"_r+:Us8'!mJs'TErgX4r9aQ\oQ(%[c2?u0V"A^/Hd2HUs8N(hbl@G*!nEffrc86X
+F,Qj=k54QIp?qq[!Uf[\mJut[mK<1Nme6YJ!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?BZ!;?E[s7ZKm"R`t[me6MF!nEff
+rc86XF,Qj=k54QHV"A^/Hd2KV!2T7.!IN)hmJs'TErgX4qsOLa!1\Q~>
+!QDbG5liu#r$_Y$3VPfK9%Et(>!Y/73C,Yk3B;RT3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Z%5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k3C,Yk3C0J@s&q-;
+3VPf?3ALF\!AQV05litpp)jAb3Vu)C3@XYE!@^&+5litpp)jAb3Vu,B`;h@3rrL*Pp-A^>1&NI$
+0feto%8,1Nk#t&25rh4k5rgrT5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k:dI*-3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3B9Ac5rh6,s8Q7W3B?h"!BDn4.02.`
+pd"p@.J=kb.678k!BDV&+9<oOq`t6C.J=kb.678ks2=secMmpa^%O_m3ALF\!AQV/5n-H:s5mKN
+3C,Yk3C,YcImH(\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3D`"%5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rgqk3C,YkV#UHu0f_8g5liu#r$_Y$3VYl@3@XYE!@^&+
+5litpp)jAb3Vu)C3@XYE!@^&+63"n(.=_~>
+s4RpIOd2&oOd22oQ&UK?C&VBMBm#,hQ'%>oQ'%>oOd5)/m\,2kYDj6Yb5_L8D1RP+Od2&oOd2&o
+NJ2Lhr`r64FbPg?Od2&oOd22_BiS;9=]JU)=]JU)Bn;P7Od2&oJSA+e<EW=)<EW=)<G@#LOd2&o
+Q%<XL=]JU)=]JU)=]K0eQ'%>oQ''qW@EniPg's=0Q'%>oQ'IJsNJ2Lhr`p+MFbPg?Od2&oOd2&k
+Q0/,7Tn/3,N>.Mts8Sd0JVfMOQ'%>oQ'%>kKlq,/>to$UKoM@[Q'%>oQ'Ho7<EW=)<EW=)<EW=9
+JX)L_Q'%>_BiS;9=]JU)=]JU)Bn;P3Q'%>sJSA+e<EW=)<EW=)<G@#LOd2&oOl"f#cN!pu%@*'@
+Od2&oQ'%>kKlq,/>nLdnKoM@[Q'%>oQ'%2ok5XkCJW6jm'TpQ<s.O:\M33pcOd2&oOd1o[F_Uh\
+9kea(NKoWkOd2&oQ%<XL=]JU)=]JU)=]K0eQ'IJsOd1K3<EW=)<EW=)<EW=9JX)@_Od22_BiS;9
+=]JU)=]JU)Bn;P3Q'%>ohV)Cg~>
+s8O&3me6)Bme6ABp?peNXIPNFXM*KYp?qYBp?qYRmf*7dmK_nBk3hC"k2q0]k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hA[mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"k3hC"k3hsCs7WPEk3h[2me6)Bme6)*]r[`gS?0E\me6)Bme6)Bp=67&P`(caP`(caP`)Wn
+p@^3.p?qY)XG`=$P`(caP`(caXO[%4p?qYJeZ=[nMj0-aMj0-aMlbJ&me6)Bmf3<_bPrOTme6)B
+me6ABp?peNXIPNFXM*KYp?qYBp?qYRmf*7dmK_nBk3hC"k2q0]k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hA[mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"k3hC"
+k3hsCs7WPEk3h[2me6)Bme6)*]r[`gS?0E\me6)Bme6)Bp=67&P`(caP`(caP`)Wnp@^3.p?qY)
+XG`=$P`(caP`(caXO[%4p?qYJeZ=[nMj0-aMj0-aMlbJ&me6)Bmf3<_bl8XUme6)Bme6ABp?peN
+XIPNFXM*KYp?qYBp?qYRmf*7dmK_nBk3hC"k2q0]k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hA[mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"k3hC"k3hsCs7WPE
+k3h[2me6)Bme6)*]r[`gS?0E\me6)Bme6)Bp=67&P`(caP`(caP`)Wnp@^3.p?qY)XG`=$P`(ca
+P`(caXO[%4p?qYJeZ=[nMj0-aMj0-aMlbJ&me6)Bmf3<_J,~>
+*ONL?5rh4k5rgqk3C,Yc0f^sK0f_6[3C,Yk3C,\)5n$ZAs8TH03C,Yk3C,r\3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk:H:^$
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5s[Ls6%e>"s&pj33W;<K3C,Yk3C,Yk3B8fS0f^sK3C,Yk3C,Yk3B9A[3AENK3AENK3AENK
+5rgqk3C,Yk0f^sK0f^sK0f^sK0gRfc3C,Yc5qtAS3AENK3AENK3AEf[5rh4k6+sr\c2Sfk]fAA=
+5rh4k3C,Yk3B8fS0f^sK3C,Yk3C,Yk3W;;Q;UtgIZs#IU3C,Yk6%:m\3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C-G$5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4s
+3C,r`k5YHb.60Ef6!H?83C,Yk3C,Yc0f^sK0f_6[3C,Yk3C,Yc5qtAS3AENK3AENK3AEf[3C,Yk
+3C,A[0f^sK0f^sK0f^sS3C,Yk3B9A[3AENK3AENK3AENK5rh4k5rh6E]d_8,*ONL?5rh4k5rgqk
+3C,Yc0f^sK0f_6[3C,Yk3C,\)5n$ZAs8TH03C,Yk3C,r\3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk:H:^$5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5s[Ls6%e>"
+s&pj33W;<K3C,Yk3C,Yk3B8fS0f^sK3C,Yk3C,Yk3B9A[3AENK3AENK3AENK5rgqk3C,Yk0f^sK
+0f^sK0f^sK0gRfc3C,Yc5qtAS3AENK3AENK3AEf[5rh4k6+sr\J,~>
+s4/-KOc>K_Oc>?_NKK3[JUr6#JW5YONKK3_NKK5"OTh04s8UN@JW7!q#a)R`s8Sd,I>.Z_(QFQ:
+Oc>K_Oc>?OJUN*#NK''[Oc>K_OoC=KJUMflH$ssdH$ssdJc:WEOc>K_NIcM'I<g6dI<g6dI=[B;
+Oc>M&N>@(nH$ssdH$ssdH$t7'NKK3_NKMfG@EniPef0U2NKK3_NK''[Oc>?OJUN*#NK''[Oc>K_
+OcB@&"e"BMs3dTlNO+TMOga]Xs.O.TL&R2NNKK3_NKK3_NK&L?I=Zs/NKK3_NKK3_rf%>;I<g6d
+I<g6dI<g6lrf%\UNKK3[JUMflH$ssdH$ssdJW5YONKO4"(4gmZI<g6dI<g6dI=[B;Oc>K_Ok/5p
+cN!pq)i]u>Oc>K_NKK3_NK&L?I=Zs/NKK3_NKK3_NW,%DRH"8Hd\25OZ],6Q[dO1qTkSq/rfJ"V
+Oc>K_Oc>K_NIcY/JUrf?Oc>K_Oc>M&N=:AdH$ssdH$ssdH$t8CN>@Y9Oc>?OI<g6dI<g6dI<g6l
+NK''[OoC=UJUMflH$ssdH$ssdJW5YONKK3_f%OP_~>
+!VZQdmK)J,rm_&+k4n?EpAXLYrrDcljob&6k3i62!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjKs6fpL!Uf[\rr_trc//-]
+!Tr8<eH+Ohp?hq2p<<Tfq<e75p<<Tfq<e75p<<TfqX4C`!1_=6!VZQdmK)J,rm_&+k4n?EpAXLY
+rrDcljob&6k3i62!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjKs6fpL!Uf[\rr_trc//-]!Tr8<eH+Ohp?hq2p<<Tfq<e75
+p<<Tfq<e75p<<TfqX4C`!1_@7!VZQdmK)J,rm_&+k4n?EpAXLYrrDcljob&6k3i62!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK!:KjK
+!:KjKs6fpL!Uf[\rr_trc//-]!Tr8<eH+Ohp?hq2p<<Tfq<e75p<<Tfq<e75p<<TfqX4C`!1\Q~>
+s0O:B3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh4k5rh4kXS2\om]<LBMh?Y3Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?7Z2nW
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?
+K8YA?K9Wa^rr6N93@Q[;3B9Ac5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5s[Ls3C,Yk3C,Yk3OH.Jc2[gN.mZ0]
+3C,Yk3C,Yk3C,qk5rh4k5rh4k5rh4k5rh4k5rl%?s8VMgXFlF`K7Af3Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh=KWK8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YAH
+[)N%EA@+?G0ek[K5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4s3C,Yk3C,Yk3C,[4Zn]l+s0O:B3C,Yk3C,Yk
+3C,Yk5rh4k5rh4k5rh4k5rh4k5rh4kXS2\om]<LBMh?Y3Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?
+Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?Mh?q?7Z2nWK8YA?K8YA?K8YA?
+K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K8YA?K9Wa^rr6N9
+3@Q[;3B9Ac5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5s[Ls3C,Yk3C,Yk3OH.JJ,~>
+*S/Z$NKK3_NKK3_NKK3_Oc>K_Oc>K_Oc>K_Oc>M%N<b<cqZ$TdcH_!P\[i-bdbaj#s43$@H%GpR
+>EOo-NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK?_Oc>K_Oc>K_Oc@r?@Enfmf$]\?Oc>K_Oc>K_Oc>KcNKK3_NKK3_
+NKK3_NKO1!#Dpb&s8VZ8c@NR;\dH=&hYR9Peqn*dJc1R4Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_
+Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_Oc>K_OcbWcNKK3_
+NKK3_NRlNdcMnp9dZKNONKK3_NKK3_NKK?_Oc>K_Oc>K_Oc>K_Oo:7EM9btts74I\J\&D'$Gt6J
+qZ$THM.q6drJb$DNKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_
+NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_NKK3_Oc>K_Oc>K_Oc>K_f$[uW~>
+s8W)d!9X:K!9X:K"6T%>k5OcKk5OcKk5OcQk3hC"k3hC0rrMinJbHVIr;R,thQ4]Hk2u*omcON:
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X7J!9X:K!9X:K"m57@s8Sn<s8MEdk5OcKk5OcNk3h["rpBdKrpBdKrpC!QmcNs"
+mcOHI!VZPEp:0horsJJVXMr`Pk3hC"k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5F]Jk5OcKk5OcPk3h[;s.mm=rpBdK
+rpBdKrpBmNmdB6:mJuDKmJuDKmKVhAk3hC"k5>5[pA]^;\G#k#$MN>X`RX,5mcNs"rpBdKrpBdK
+rpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdKrpBdK
+rpBdKrU'[JrpBdKrpBsPmdC,TUjr~>
+s/Z5]62ikE62ikE62NYB62ikE62ikE62ikM5rh4k5ri,MhLY^4rsHGS0ek[K5rh4k62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62`eD62ikE62ikH6*..:c2[gF!BEIF3<2AE3<2AB3<2AE3<2AE3<2AE3=%o25rh4k
+>--S3s0DY3]kT8V3B9Ac5rh713<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE
+3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AE3<2AD3<2AE3<2AE3<MRKX=;Hps/Z5]62ikE
+62ikE62NYB62ikE62ikE62ikM5rh4k5ri,MhLY^4rsHGS0ek[K5rh4k62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62`eD62ikE62ikH6*..:J,~>
+s3;R?NJWXONJWXONJWXOM2d@OM2d@OM2d@OM2dAiN<>$*cK]u\ZMt0\V.FLlJVf6_NE_7!M2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@KNJWXONJWXONJWY?dUCE#s3;R?NJWXONJWXONJWXOM2d@OM2d@OM2d@OM2dAi
+N<>$*cK]u\ZMt0\V.FLlJVf6_NE_7!M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@KNJWXONJWXONJWY?dUCH$s3;R?
+NJWXONJWXONJWXOM2d@OM2d@OM2d@OM2dAiN<>$*cK]u\ZMt0\V.FLlJVf6_NE_7!M2d@OM2d@O
+M2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@OM2d@O
+M2d@OM2d@KNJWXONJWXONJWY?dU@Y~>
+!VZQRjoFiKjoOoDJcDtS"R`@uc.2dT!:HfJ!quYac2Rh<s5W5Amf)>Lme253Yl=joXL-7&rT4+J
+W9+0Ts.%C7!VZQRjoFiKjoOoDJcDtS"R`@uc.2dT!:HfJ!quYaJ,~>
+*NZ&&3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4k5rh713<2AD3<M!.F*iJ.\XWkVC.^300erVe!($TE
+><t883C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,qk5rh4k5rh4k5rl$B.F%l5XJA-B5rh4k5rh4k5rh4s3C,Yk3C,Yk
+3C,Yk3C3X)!($QD"#3DhH\%]tS-FU\8hhbL1&X*462ilK5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5s[Ls3C,Yk
+3C,Yk3NT#*cMnodUd7",3C,Yk3C,Yk3C,qk5rh4k5rh4k5rh4k62ikE62`eG0hQM6JXj9@#(pY_
+0e"h3rAajDr]+1K3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk5rh4k5rh4k5rh4kXJ@:q~>
+.F-(qM2d@OM2d@OM2d@ONJWXONJWXONJWXONJWXONJWXONJWLCQ*.Fl`dbkF_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T#Bg`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4
+`koa4[]5U4BlS9HKo(XnNJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONK&dSM2d@OM2d@OM9a7Pc2T6<b)M7;
+M2d@OM2d@OM2dLONJWXONJWXONJWXONJWXONJWXOM1LqpZMqjn_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4:Vt,g`koa4`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`ko0a
+Q#UMXFb,7'M-l7!NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXSM2d@OM2d@OM2dA;b$iTq.F-(qM2d@OM2d@O
+M2d@ONJWXONJWXONJWXONJWXONJWXONJWLCQ*.Fl`dbkF_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4
+_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T'I4_T#Bg`koa4`koa4`koa4`koa4
+`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4`koa4[]5U4BlS9H
+Ko(XnNJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXONJWXO
+NJWXONJWXONJWXONJWXONJWXONJWXONK&dSM2d@OM2d@OM9a7PJ,~>
+!WVlTjoF9;jp0c*hVQfFmd>Z"\b?'k$Kf%']uAOPk2,7WVWIs[p8#q4!;>O:!8d_;#N"V"hUUcV
+mXb)BpAaOfk.Rk0`RWN$hWE[ljoYSVUs8o>p>tE:hYuXBhWE\Oe`Q;fJbHYJs6^6V]r\ode^`g=
+k2)ut!rqtiJ,~>
+-Cgkd3AENK3AENK3AENK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sKpb;atr\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%pb?5<
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sC3AENK3AENK3AEOaUaaRg-Cgkd3AENK3AENK3AENK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sKpb;atr\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%pb?5<0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sC3AENK3AENK3AEOaUaaUh-Cgkd3AENK3AENK3AENK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+pb;atr\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%r\4C%
+r\4C%r\4C%r\4C%r\4C%pb?5<0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK
+0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sK0f^sC3AENK3AENK3AEOaUa^f~>
+.`TVVI<g6dI<g6dI<g6dH$ssdH$ssdH$ssdH$ssdH$ssdH$ss`F`h\Drb[.!D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!i[Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$
+Bl.R$D/!j(EH-8L@XWNMH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$Og`I<g6dI<g6dIE'E<c2T95b'AD\
+I<g6dI<g6dI<g*dH$ssdH$ssdH$ssdH$ssdH$ssdH$OOTEH1tpIq`b6D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D+eS[Bl.R$Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.^$
+D/F94H$NkIH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ss`I<g6dI<g6dI<g7\b$iTq.`TVVI<g6dI<g6d
+I<g6dH$ssdH$ssdH$ssdH$ssdH$ssdH$ss`F`h\Drb[.!D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$
+D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!j$D/!i[Bl.R$Bl.R$Bl.R$Bl.R$
+Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$Bl.R$D/!j(EH-8L
+@XWNMH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$ssd
+H$ssdH$ssdH$ssdH$ssdH$ssdH$ssdH$Og`I<g6dI<g6dIE'E<J,~>
+*VTNPc,IrHc,IrHc,IrH`QcBH`QcBH`QcBH`QcBublu)2`PoO(rj70V[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gW$XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,),
+[/[i>`VRh``QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`Pp*@c,IrHc,IrHc1_1-c2SgXs2E7%c,IrHc,IrHc,IZH
+`QcBH`QcBH`QcBH`VRg_`QcB@]tOEPJ#p#Y[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9ZpLk$XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XSfI*^&Q(Jc!/03`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcB@c,IrHc,IrHc,Is$s.%C7*VTNPc,IrHc,IrHc,IrH`QcBH`QcBH`QcBH`QcBublu)2
+`PoO(rj70V[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gW$XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,),[/[i>`VRh``QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH
+`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`QcBH`Pp*@c,IrHc,IrH
+c1_1-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HWUBcdhsUIDJaTQ+"$)mI.F%koUmsI"mf*:Ymf*:*mf*9<m\9+O3LllocMmsAS2oKprrCa?
+rr@W<JaW@%"$)mI.=_~>
+!m8N2WUBcdhsUIDJaTQ+"+A23@EnfRb/Skamf*:Ymf*:*mf*9<m\9+OIE'E<cMmsg`dQb4rrCa?
+rr@W<JaW@%"+A23@=S~>
+!rqu=WTO3\hran<J``up"3pQ>SBV!6p<D@SrrDZQrrC""rr@W4U?2R&pA^Z-rrMi<hraq=g#i;7
+J`_OGq;qe(pA^Y5~>
+!h?&@qsO:\g[=q=ipQgHp?qeXna?DWs6fmei9pUFJaUkP"#6UA.F%koS>7n9mf*:]mf*:amf*:^
+mf*:ame["amf*:Ame["Rmf*9<m\9+O0r1<gcMms9UbVc7rrE&drrE&drrDTWrrDo`qZ,dHrrDZY
+rr@W<M=(I#Umrla~>
+!liB.qsO:\g[=q=ipQgHp?qeXna?DWs6fmei9pUFJaUkP"*r&/@EnfR`l`T'mf*:]mf*:amf*:^
+mf*:ame["amf*:Ame["Rmf*9<m\9+OH-4-8cMmscb'EmPrrE&drrE&drrDTWrrDo`qZ,dHrrDZY
+rr@W<M=(Ikb/Rk?~>
+!quZ5qr[_TgZJA5io^7@p?)5Pn`KiOs5s=]i9(%>J`b;@"3(<6Us8o@pA`,.k5PGUk5PGYk5PGV
+k5PGYk5,/Yk5PG9k5,/Jk5PF4k+^u?`W,Y-cMmt>s2FltrrE&\rrE&\rrDTOrrDoXqZ,d@rrDZQ
+rr@W4M<4oZs7W7=~>
+!i2>Hq!S.^n*^2Ur9jRbp$Vh[rU'XcipQgHp[8%]rU'Xcna?DWi9pUFJaU_L"$)mI.F%koUmsIA
+mf*:Ymf*:Zmf*:amf*:dmf*7gmJm7Amf*:dmf*:Wmf*9<m\9+O3LllocMmsAS2pH6!!*#drrE&d
+!!)NVrrDrarrE#c!!)0LrrDf]rr@W<L$f%'S>7Ta~>
+!m8N2q!S.^n*^2Ur9jRbp$Vh[rU'XcipQgHp[8%]rU'Xcna?DWi9pUFJaU_L"+A23@EnfRb/Sl+
+mf*:Ymf*:Zmf*:amf*:dmf*7gmJm7Amf*:dmf*:Wmf*9<m\9+OIE'E<cMmsg`dR^O!!*#drrE&d
+!!)NVrrDrarrE#c!!)0LrrDf]rr@W<L$f%k`l__?~>
+!rqu=pu_SVn)jWMr9""Zp#c8SrT4([io^7@pZDJUrT4([n`KiOi9(%>J`b/<"3pQ>SBV!6p<EHr
+rrDZQrrD]RrrDrYrrE&\rr<,_!!(d9rrE&\rrDTOrr@W4U?2R&pA^Z-rrMi<qW7bXroX4\roO1\
+nE0`Nqr[nYrT4([k2u[DpZDJUJ`_[K"3pQ>S:C~>
+!h?&@q!S.^rU0UarpKdds6]mfmem.bmem.cmf!4`mf*:amed(amem.amem.bmed(bmf*7gmJm7a
+mf*:_mf!4cmf*7imJm7Tmem+gmJm7Tmed(bmf*:emf*:emem+cmem.cmem+emJm7dmf!4cmf*7g
+mJm6<mbR:50r1<gc2Rj8UbV`6rrE)err<,g!!*#drr<&er;Zug!!)HTr;cibrrDrarrE&drr<5j
+!!)Ee!<2Eb!!)Hc!<)?a!<)?a!;c-`!<2Ed!<2Ec!<)?b!<2Ed!<;He!.jR7mK52>S12b`!h?&@
+qX4@`s6fjds6]jerpKacrpK^b!:Kabr9jRbq<n4^rpKO]rpK[as6fmerpK^bs6fgc!q$$grpKac
+rpKdd!q$$gJaSlm"#6UA.=_~>
+!liB.q!S.^rU0UarpKdds6]mfmem.bmem.cmf!4`mf*:amed(amem.amem.bmed(bmf*7gmJm7a
+mf*:_mf!4cmf*7imJm7Tmem+gmJm7Tmed(bmf*:emf*:emem+cmem.cmem+emJm7dmf!4cmf*7g
+mJm6<mbR:5H-4-8c2Rjbb'EjOrrE)err<,g!!*#drr<&er;Zug!!)HTr;cibrrDrarrE&drr<5j
+!!)Ee!<2Eb!!)Hc!<)?a!<)?a!;c-`!<2Ed!<2Ec!<)?b!<2Ed!<;He!.jR7mK7aW`aR0m!liB.
+qX4@`s6fjds6]jerpKacrpK^b!:Kabr9jRbq<n4^rpKO]rpK[as6fmerpK^bs6fgc!q$$grpKac
+rpKdd!q$$gJaSlm"*r&/@=S~>
+!quZ5pu_SVrT=%YroX4\s5j=^k5>;Zk5>;[k5GAXk5PGYk555Yk5>;Yk5>;Zk555Zk5PD_jo>DY
+k5PGWk5GA[k5PDajo>DDk5>8_jo>DDk555Zk5PG]k5PG]k5>8[k5>;[k5>8]jo>D\k5GA[k5PD_
+jo>C4k2#/%`W,Y-c2Rk=s2FisrrE)]rr<,_!!*#\rr<&]r;Zu_!!)0Dr;ciZrrDrYrrE&\rr<5b
+!!)-]!<2-Z!!)0[!<)'Y!<)'Y!;bjX!<2-\!<2-[!<)'Z!<2-\!<;0]!.j:/jo`U&p8$"6!quZ5
+qW@eXs5s:\s5j:]roX1[roX.Z!9X1Zr9""Zq<%YVroWtUroX+Ys5s=]roX.Zs5s7[!p0I_roX1[
+roX4\!p0I_J``<]"3(<6Ujr~>
+!i2>Hq!S.^rpKdds6fmes6fme#4;Hkmd:&Tr9jRbs6fme!q$$gr9jL`rU0Xb'(,`"mJm7TmJm7T
+mJm7TmJm7TrW)larW!#f!!)rbrrDo`rr<2i!!)HTrW!>o!!)HT!!)HT!!)Hd!"SDs!:K7T!:K7T
+!:K7T!<2C$!:K7T!:K7T!:K7T!:K7T!:BgemdC&S!q$$gJaVC_"$)mI.F%koUmsIAmf*:emf!2(
+mJm7TmJm7TmJm7TmJm7TmJu\C!!)HT!!)oarrE&drr<&erW!/j!!)HT!!*#d#QX;\!!)HT!!)oa
+rrE)errDrarrE&drrE)err<Vu!!)HT!!)Ee!:K7T!:BgeJaTB&"$)mI.F.qpUmsIAmf*:emf!1q
+mJm7TmJm7T!!)HT!!*#drr<,g!!)rbrrDo`rr<2i!!)HTrVurdrW!)h!!)HTrW"#-!!)Ee!:K7T
+!:K7T!:K7T!:K7T!:K7T!:BgemdC&S!q$$gJaSon"$)mI.=_~>
+!m8N2q!S.^rpKdds6fmes6fme#4;Hkmd:&Tr9jRbs6fme!q$$gr9jL`rU0Xb'(,`"mJm7TmJm7T
+mJm7TmJm7TrW)larW!#f!!)rbrrDo`rr<2i!!)HTrW!>o!!)HT!!)HT!!)Hd!"SDs!:K7T!:K7T
+!:K7T!<2C$!:K7T!:K7T!:K7T!:K7T!:BgemdC&S!q$$gJaVC_"+A23@EnfRb/Sl+mf*:emf!2(
+mJm7TmJm7TmJm7TmJm7TmJu\C!!)HT!!)oarrE&drr<&erW!/j!!)HT!!*#d#QX;\!!)HT!!)oa
+rrE)errDrarrE&drrE)err<Vu!!)HT!!)Ee!:K7T!:BgeJaTB&"+A23@F"lSb/Sl+mf*:emf!1q
+mJm7TmJm7T!!)HT!!*#drr<,g!!)rbrrDo`rr<2i!!)HTrVurdrW!)h!!)HTrW"#-!!)Ee!:K7T
+!:K7T!:K7T!:K7T!:K7T!:BgemdC&S!q$$gJaSon"+A23@=S~>
+!rqu=pu_SVroX4\s5s=]s5s=]#3Gmck2lXDr9""Zs5s=]!p0I_r9!qXrT=(Z''9/ojo>DDjo>DD
+jo>DDjo>DDrW)lYrW!#^!!)rZrrDoXrr<2a!!)0DrW!>g!!)0D!!)0D!!)0\!"S,k!9WDD!9WDD
+!9WDD!<2*q!9WDD!9WDD!9WDD!9WDD!9O7]k2uXC!p0I_J`bhO"3pQ>SBV!6p<EHrrrE)]rW!hu
+!!)0D!!)0D!!)0D!!)0D!9WDD!9WDD!;kpY!<2-\!!)0\!!_Qc!9WDD!<2*d!9WDD!9WDD!;kpY
+!<;3]!;kpY!<2-\!<;3]!"e8m!9WDD!9O7]k2lXDjo>C4k,%2Bc1_1-c2Rh<c2-T&!<;3\!"J&j
+!9WDD!9O7]k2lXDroX4\!p0I_r9""ZqW@eX"Qf[ak2uXC!9X7\"Qf[ak2uXC*p*G&jo>DDjo>DD
+jo>DDjo>DDjo>DDjo>DD!!)0DrW!#^!!%T4R-"LqpA^Y5~>
+!h?&@q!S.^rpKdds6fmerpKacrpKdd!:Kgd"mu?jmJm7dmed(bmed(bmf*:emf*8!mJm7TmJm7T
+mJm7TmJm7T!!)oarrE)errDubrrDrarrE&drr=51!!)HT!!)HT!!)HT!!)Ee!:K7T!:K7T!:K7T
+!:K7T!;l3a!<;Ke!<;Ke!!;Qg!<2Ed!!_ik!:K7T!.jRpmK52>S12__!h?&@qX4@`s6fmes6fme
+s6fmes6fmes6fmer9jRbs6fmeqsO=]s6fmes6fmes6fmeqsOIas6fjdr9jRbs6fmeqsO@^rpKdd
+rpK^brpKdd!:KdcJaT?%"#6UA.F.qpS>7n9mf*7emem+hmJm7T!!*#drr<Do!!)HT!!)HT!!)rb
+rrDrarrE&drr=J8!!)HT!!)HT!!)HT!!)HT!!)Ee!:K7T!:K7T!:K7T!:K7T!:BgerpKdd#4;Hk
+md:&TJaSon"#6UA.=_~>
+!liB.q!S.^rpKdds6fmerpKacrpKdd!:Kgd"mu?jmJm7dmed(bmed(bmf*:emf*8!mJm7TmJm7T
+mJm7TmJm7T!!)oarrE)errDubrrDrarrE&drr=51!!)HT!!)HT!!)HT!!)Ee!:K7T!:K7T!:K7T
+!:K7T!;l3a!<;Ke!<;Ke!!;Qg!<2Ed!!_ik!:K7T!.jRpmK7aW`aR-l!liB.qX4@`s6fmes6fme
+s6fmes6fmes6fmer9jRbs6fmeqsO=]s6fmes6fmes6fmeqsOIas6fjdr9jRbs6fmeqsO@^rpKdd
+rpK^brpKdd!:KdcJaT?%"*r&/@F"lS`l`T'mf*7emem+hmJm7T!!*#drr<Do!!)HT!!)HT!!)rb
+rrDrarrE&drr=J8!!)HT!!)HT!!)HT!!)HT!!)Ee!:K7T!:K7T!:K7T!:K7T!:BgerpKdd#4;Hk
+md:&TJaSon"*r&/@=S~>
+!quZ5pu_SVroX4\s5s=]roX1[roX4\!9X7\"m,dbjo>D\k555Zk555Zk5PG]k5PDnjo>DDjo>DD
+jo>DDjo>DD!!)oYrrE)]rrDuZrrDrYrrE&\rr=5)!!)0D!!)0D!!)0D!!)-]!9WDD!9WDD!9WDD
+!9WDD!;kpY!<;3]!<;3]!!;9_!<2-\!!_Qc!9WDD!.j:hjo`U&p8#t5!quZ5qW@eXs5s=]s5s=]
+s5s=]s5s=]s5s=]r9""Zs5s=]qr[bUs5s=]s5s=]s5s=]qr[nYs5s:\r9""Zs5s=]qr[eVroX4\
+roX.ZroX4\!9X4[J``cj"3(<6UsAuApA`,.k5PD]k5>8`jo>DD!!*#\rr<Dg!!)0D!!)0D!!)rZ
+rrDrYrrE&\rr=J0!!)0D!!)0D!!)0D!!)0D!!)-]!9WDD!9WDD!9WDD!9WDD!9O7]roX4\#3Gmc
+k2lXDJ``?^"3(<6Ujr~>
+!i2>Hq!S.^rpKX`rU0[crpKddr9jRb!q$$grpKddq<n4^#OVQlmd:&Tme["ameZtcmJm7amf*:e
+mf*:bmf*:amf*:dmf*81mJm7TmJm7TmJm7TmJm7T!!)HT!!)HT!!)HT!!)HT!!*#dquHcbrrE)e
+rr<,g!!*#drr<8k!!)HT!!%T<hX1J+S>7UYrrT!d3Vr1D!<;Ke!<;Ke!<;Ke!<;Ke!<;Ke!<;Kb
+!<;Ke!;l3a!;l3a!<;Ke!<;Ke!<2Ea!<2Eb!<2E`!;l3a!<2Ed!!;Qg!<2Eb!<2Ed!!)Hc!.jR6
+mK5J>UaaUh!i2>Hq<eUjmJu\C!:BjTmJm7dmf*7omJm7TmJm7TmJm7bmf*:amf*:dmf*8'mJm7T
+mJm7TmJm7TmJm7TmJm7T!!)HTqZ-ZarrE)err<,g!!*#drr<8k!!)HT!!%T<R-k&:S>7Ta~>
+!m8N2q!S.^rpKX`rU0[crpKddr9jRb!q$$grpKddq<n4^#OVQlmd:&Tme["ameZtcmJm7amf*:e
+mf*:bmf*:amf*:dmf*81mJm7TmJm7TmJm7TmJm7T!!)HT!!)HT!!)HT!!)HT!!*#dquHcbrrE)e
+rr<,g!!*#drr<8k!!)HT!!%T<hX1Jo`l_`7rrU?_IJWC3!<;Ke!<;Ke!<;Ke!<;Ke!<;Ke!<;Kb
+!<;Ke!;l3a!;l3a!<;Ke!<;Ke!<2Ea!<2Eb!<2E`!;l3a!<2Ed!!;Qg!<2Eb!<2Ed!!)Hc!.jR6
+mK7mWb$iTq!m8N2q<eUjmJu\C!:BjTmJm7dmf*7omJm7TmJm7TmJm7bmf*:amf*:dmf*8'mJm7T
+mJm7TmJm7TmJm7TmJm7T!!)HTqZ-ZarrE)err<,g!!*#drr<8k!!)HT!!%T<R-k')`l__?~>
+!rqu=pu_SVroX(XrT=+[roX4\r9""Z!p0I_roX4\q<%YV#Nc!dk2lXDk5,/Yk5,,[jo>DYk5PG]
+k5PGZk5PGYk5PG\k5PE)jo>DDjo>DDjo>DDjo>DD!!)0D!!)0D!!)0D!!)0D!!*#\quHcZrrE)]
+rr<,_!!*#\rr<8c!!)0D!!%T4hW=pbpA^Z,rrMi<qW@eXs5s=]s5s=]s5s=]s5s=]s5s=]s5s4Z
+s5s=]qr[nYqr[nYs5s=]s5s=]roX+YroX.ZroX(Xqr[nYroX4\!p0I_roX.ZroX4\!9X4[J``cj
+"3pQ>SB_'7p<EEq$NT;hk2l[+!9WDD!<2-\!".ig!9WDD!9WDD!;u!Z!;kpY!<2-\!#Obt!9WDD
+!9WDD!9WDD!9WDD!9O7]k2uO@s5s=]s5s=]!p0I_roX4\#3Gmck2lXDJ``?^"3pQ>S:C~>
+!h?&@q!S.^rpKddqX4=_rpKddr9jRb!q$$grpKddq!S.^$17cnmd:&TmJm7amf*:bmf*:amf*:e
+mf*:bmf*:amf*:dmf*8DmJm7TmJm7TmJm7TmJm7T!!)HT!!)HT!!)HT!!)HT!!)HT!!)HT!!)HT
+!!)HT!!)Ee!<2Ed!!_ik!:K7T!.jRpmK52>S12__!h?&@qX4@`s6fmes6fmes6fmes6fmes6fme
+$LRlomd:&Tmd:&TqsOIaqsOIas6fmes6fmes6fmes6fmer9jOas6fmep[8%]rU0UarpK^brpKdd
+!:KabJaTB&"#6UA.F.qpS>7n8mf!4dmf!4dmf*:dmf*7omJm7TmJm7TmJm7bmf*:amf*:dmf*8)
+mJm7TmJm7TmJm7TmJm7TmJm7T!!)HT!!)oarrE)err<,g!!*#drr<8k!!)HT!!%T<R-k&2Umrla~>
+!liB.q!S.^rpKddqX4=_rpKddr9jRb!q$$grpKddq!S.^$17cnmd:&TmJm7amf*:bmf*:amf*:e
+mf*:bmf*:amf*:dmf*8DmJm7TmJm7TmJm7TmJm7T!!)HT!!)HT!!)HT!!)HT!!)HT!!)HT!!)HT
+!!)HT!!)Ee!<2Ed!!_ik!:K7T!.jRpmK7aW`aR-l!liB.qX4@`s6fmes6fmes6fmes6fmes6fme
+$LRlomd:&Tmd:&TqsOIaqsOIas6fmes6fmes6fmes6fmer9jOas6fmep[8%]rU0UarpK^brpKdd
+!:KabJaTB&"*r&/@F"lS`l`T&mf!4dmf!4dmf*:dmf*7omJm7TmJm7TmJm7bmf*:amf*:dmf*8)
+mJm7TmJm7TmJm7TmJm7TmJm7T!!)HT!!)oarrE)err<,g!!*#drr<8k!!)HT!!%T<R-k'%b/Rk?~>
+!quZ5pu_SVroX4\qW@bWroX4\r9""Z!p0I_roX4\pu_SV$0D3fk2lXDjo>DYk5PGZk5PGYk5PG]
+k5PGZk5PGYk5PG\k5PE<jo>DDjo>DDjo>DDjo>DD!!)0D!!)0D!!)0D!!)0D!!)0D!!)0D!!)0D
+!!)0D!!)-]!<2-\!!_Qc!9WDD!.j:hjo`U&p8#t5!quZ5qW@eXs5s=]s5s=]s5s=]s5s=]s5s=]
+$K_<gk2lXDk2lXDqr[nYqr[nYs5s=]s5s=]s5s=]s5s=]r9!tYs5s=]pZDJUrT=%YroX.ZroX4\
+!9X1ZJ``fk"3(<6UsAuApA`,-k5GA\k5GA\k5PG\k5PDgjo>DDjo>DDjo>DZk5PGYk5PG\k5PE!
+jo>DDjo>DDjo>DDjo>DDjo>DD!!)0D!!)oYrrE)]rr<,_!!*#\rr<8c!!)0D!!%T4R-"Lis7W7=~>
+!i2>Hq!S.^rpKacr9jRb#4;Hkmd:&Tr9jRb!:Kgd!q$$gr9aObrU0[c"7?-hmf!1dmf!4amf!4a
+mf*:bmf*:emf*:amf*:cmem,$mJm7TmJm7TmJm7TmJm7TmJm7T!!)Hd!<;Ka!<;Ke!<;Ke!<;Ke
+!<;Ke!<;Ke!!)Hd!"/,o!:K7T!:K7T!.jRpmK5J>UaaRg!i2>HqX4@`s6fmes6fmes6fmes6fme
+s6fme$LRlomd:&Tmd:&TqsOIaqsOIas6fmes6fmes6fmes6fmes6]jerpKdds6fjdq!S.^rU0R`
+"7?-hmf!1mmJm7TmJm7T!!%T<V="FGS>7UZrrT!d3Vi+B!<;Kd!<;Kd!"82p!:K7T!:K7T!:Kgd
+qsOIarU0Ua'CGi#md:&Tmd:&Tmd:&Tmd:&Tmf!1hmJm7Tmf!4amf*:emf*7emf!1nmJm7TmJm7T
+mJm6<m[3DE3LlloJ,~>
+!m8N2q!S.^rpKacr9jRb#4;Hkmd:&Tr9jRb!:Kgd!q$$gr9aObrU0[c"7?-hmf!1dmf!4amf!4a
+mf*:bmf*:emf*:amf*:cmem,$mJm7TmJm7TmJm7TmJm7TmJm7T!!)Hd!<;Ka!<;Ke!<;Ke!<;Ke
+!<;Ke!<;Ke!!)Hd!"/,o!:K7T!:K7T!.jRpmK7mWb$iQp!m8N2qX4@`s6fmes6fmes6fmes6fme
+s6fme$LRlomd:&Tmd:&TqsOIaqsOIas6fmes6fmes6fmes6fmes6]jerpKdds6fjdq!S.^rU0R`
+"7?-hmf!1mmJm7TmJm7T!!%T<V="G6`l_`8rrU?_IJN=1!<;Kd!<;Kd!"82p!:K7T!:K7T!:Kgd
+qsOIarU0Ua'CGi#md:&Tmd:&Tmd:&Tmd:&Tmf!1hmJm7Tmf!4amf*:emf*7emf!1nmJm7TmJm7T
+mJm6<m[3DEIE'E<J,~>
+!rqu=pu_SVroX1[r9""Z#3Gmck2lXDr9""Z!9X7\!p0I_r8mtZrT=+["6KR`k5G>\k5GAYk5GAY
+k5PGZk5PG]k5PGYk5PG[k5>8qjo>DDjo>DDjo>DDjo>DDjo>DD!!)0\!<;3Y!<;3]!<;3]!<;3]
+!<;3]!<;3]!!)0\!".ig!9WDD!9WDD!.j:hjo`m%s.%=5!VXe7k5PG]k5PG]k5PG]k5PG]k5PG]
+k5PDgjo>DDjo>DDjo>DYk5PGYk5PG]k5PG]k5PG]k5PG]k5PG]jo>D\k5PG]k5GAUk5PG[k552]
+jo>DDrW!8e!!)0D!!)-]!.j:/jo`m%s.%@6!VXe6k5GA\k5GA\k5G>gjo>DDjo>DDjo>DDrW)iX
+rrE#[r;[Mn!!)0D!!)0D!!)0D!!)0D!!)0\!!MEa!9WGC!;u!Z!<;3]!!)0\!".ig!9WDD!9WDD
+!.j:"jo`m%s."T~>
+!h?&@q!S.^r9jL`s6^!imd:&TrpKddr9jRbs6fjdqsO=]s6fdbrU0UarU0UarpK^bs6fmes6fme
+qX44\s6fjdrpKdds6fmes6fmes6fmes6fdbrpKdd#4;Hkmd:&TrpK[arpKdd!q$$grpKacrpKdd
+s6fmeJaVC_"#6UA.F%koS>7n9mf*:emf*:emf*:emf*:dmf*7imJm7Tmed(bmf*:amf*:amf*:e
+mf*:emf*:dmed(bmed(_mem._meQq_mf!4bmf!4cmf*:emf*9<m\]CS0r1<gcMms9UbV]5rrE&d
+rrDubrW)rcrrE&dquHT]qZ-ZarW)rcrrE)errE)errE)equHcbrrE#cr;cibrr<,g!!*#drW)rc
+rrE)err@W<R-k&2Umrla~>
+!liB.q!S.^r9jL`s6^!imd:&TrpKddr9jRbs6fjdqsO=]s6fdbrU0UarU0UarpK^bs6fmes6fme
+qX44\s6fjdrpKdds6fmes6fmes6fmes6fdbrpKdd#4;Hkmd:&TrpK[arpKdd!q$$grpKacrpKdd
+s6fmeJaVC_"*r&/@EnfR`l`T'mf*:emf*:emf*:emf*:dmf*7imJm7Tmed(bmf*:amf*:amf*:e
+mf*:emf*:dmed(bmed(_mem._meQq_mf!4bmf!4cmf*:emf*9<m\]CSH-4-8cMmscb'EgNrrE&d
+rrDubrW)rcrrE&dquHT]qZ-ZarW)rcrrE)errE)errE)equHcbrrE#cr;cibrr<,g!!*#drW)rc
+rrE)err@W<R-k'%b/Rk?~>
+!quZ5pu_SVr9!qXs5jFak2lXDroX4\r9""Zs5s:\qr[bUs5s4ZrT=%YrT=%YroX.Zs5s=]s5s=]
+qW@YTs5s:\roX4\s5s=]s5s=]s5s=]s5s4ZroX4\#3Gmck2lXDroX+YroX4\!p0I_roX1[roX4\
+s5s=]J`bhO"3(<6Us8o@pA`,.k5PG]k5PG]k5PG]k5PG\k5PDajo>DDk555Zk5PGYk5PGYk5PG]
+k5PG]k5PG\k555Zk555Wk5>;Wk5#)Wk5GAZk5GA[k5PG]k5PF4k,.8C`W,Y-cMmt>s2FfrrrE&\
+rrDuZrW)r[rrE&\quHTUqZ-ZYrW)r[rrE)]rrE)]rrE)]quHcZrrE#[r;ciZrr<,_!!*#\rW)r[
+rrE)]rr@W4R-"Lis7W7=~>
+!i2>Ha6rs-\*j7rJaTl4"$)mI.F%koUmsGrmXaf,mK5J>UaaUh!i2>H]^Ge"JaS*Wo'QT?S>7Ta~>
+!m8N2a6rs-\*j7rJaTl4"+A23@EnfRb/Sj\mXaf,mK7mWb$iTq!m8N2]^Ge"JaS*Wo'QU.`l__?~>
+!rqu=a6*C%\*!\jJ`a<$"3pQ>SBV!6p<A0NJ`a#q"3pQ>SB_'7p<C84rr@W4J`cOc"3pQ>S:C~>
+!h?&@a6rs-]C,RsJaTi3"#6UA.F%koS>7ljmXaf,mK52>S12b`!h?&@]^Ge"JaS*Wo'QT7Umrla~>
+!liB.a6rs-]C,RsJaTi3"*r&/@EnfR`l`RXmXaf,mK7aW`aR0m!liB.]^Ge"JaS*Wo'QU*b/Rk?~>
+!quZ5a6*C%]B9"kJ`a9#"3(<6Us8o@pA`*_k(2Zqjo`U&p8$"6!quZ5]]T4oJ`_OGo&^%ns7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HqsK#5JPrsTqsFPHS>7UYrrT!d3W&5q;Lq`T;Z#ka3LllocMmsAS2pK7JPq%s[o3+k"$)mI
+.=_~>
+!m8N2qsK#8JQ90ZqsFQ7`l_`7rrU?_IJ`G`<In/Z<Vu1dIE'E<cMmsg`dRaPJQ78$[oN=n"+A23
+@=S~>
+!rqu=qrWH-JPrsTqrS"*pA^Z,rrMi<qrWH-JPrsTqrS"*pA^Z-rrMi<qrWH-JPrsTqrS"*pA^Y5~>
+!h?&@qsK%8JcE4ZqsFP@UmrmYrrS^d1&LBis+13Zs823d0r1<gcMms9UbVc7JcC<$\,Z?n"#6UA
+.=_~>
+!liB.qsK%8JcE4ZqsFQ3b/Rl7rrU3_H2I#\s+13Zs823dH-4-8cMmscb'EmPJcC<$\,Z?n"*r&/
+@=S~>
+!quZ5qrWJ0JcE4ZqrS""s7W85rrVoo`V\eKs+13Zs81p\`W,Y-cMmt>s2FltJcC<$\,Z?f"3(<6
+Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3Vr1@!<;He!8HoA!:oOX!;l0a!:0%Q!;l0a!;Z$_!:]CV!8d,D
+!:0%Q!5Iq%!3kkn3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJWC/!<;He!8HoA!:oOX!;l0a!:0%Q!;l0a!;Z$_!:]CV!8d,D
+!:0%Q!5Iq%!3kknIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qW@YTs5j:]gZAJ9o&]oPqrRkYlfJ0IqrRkYq;qYWnE']NhW=e<
+lfJ0I^ZGLrYiZ&4pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&C;<!<)?c!!2Kfg[5%Alg=`Qlg=`Qo'QJXnEp8VhX1@Dlg=`Q
+^[;(%YjMTJUmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2?q/!<)?c!!2Kfg[5%Alg=`Qlg=`Qo'QJXnEp8VhX1@Dlg=`Q
+^[;(%YjMU=b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`VS]s!<)'[!!23^gZAJ9lfJ0IlfJ0Io&]oPnE']NhW=e<lfJ0I
+^ZGLrYiZ&,s7W86rrVoo`I[0&k,[VH`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3Vr.D!;u6d!:BjAmJm7QmJm7QmJm7XmJm7VmJm7DmJm7QmJm7%
+mJm6kmK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJW@3!;u6d!:BjAmJm7QmJm7QmJm7XmJm7VmJm7DmJm7QmJm7%
+mJm6kmK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qW7bXr8n%\joF/u!!)?I!!)?I!!)TP!!)NN!!(m<!!)?I!!'dr
+!!'7c"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&C;<!;u6d!:Bjdmf!4cmem.bmem.amf!4^mem.bmf!4bmem+d
+mK!7Sr;cibrW)i`!!*#d!!*#d!s%`hmf!4dmJm7dmem+emJu\S!;l0d!:BgerpBdemf!4dmK3IW
+!:KdcrpK^brU0XbqX+FcmJm7cmem.amem.bmKEUYmJu\Cr;c`_rrE&d!W_ZVr;cib!!*#d!!)oa
+!<DQe!<2Ec!<)?b!<)?a!<;He!42(q0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2?q/!;u6d!:Bjdmf!4cmem.bmem.amf!4^mem.bmf!4bmem+d
+mK!7Sr;cibrW)i`!!*#d!!*#d!s%`hmf!4dmJm7dmem+emJu\S!;l0d!:BgerpBdemf!4dmK3IW
+!:KdcrpK^brU0XbqX+FcmJm7cmem.amem.bmKEUYmJu\Cr;c`_rrE&d!W_ZVr;cib!!*#d!!)oa
+!<DQe!<2Ec!<)?b!<)?a!<;He!42(qH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`VS]s!;ts\!9O:\k5GA[k5>;Zk5>;Yk5GAVk5>;Zk5GAZk5>8\
+joGDCr;ciZrW)iX!!*#\!!*#\!s%H`k5GA\jo>D\k5>8]joFQC!;km\!9O7]roO4]k5GA\joYVG
+!9X4[roX.ZrT=(ZqW7k[jo>D[k5>;Yk5>;ZjokbIjoFQ+r;c`WrrE&\!W_BFr;ciZ!!*#\!!)oY
+!<D9]!<2-[!<)'Z!<)'Y!<;0]!41ei`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3Vr.D!<)?c!!qummd:)CmJm7amK3IWmK!.P"9@lX!!)oarrE)e
+$NTV_!:K7T!:K7T!<)<q!:K7T!:K7Tmd:)CmJm7bmf*:emf*:emL90a!!)HT!:K7Tmd:&TrU0[c
+s6]jeqsOIa%IO2rmd:&Tmd:)CmJm7amK3IWmK!.P"9@lX!!)oarr=#+!!)HT!!)HT!!)HT!!)HT
+!!)HT!:Bgemd:)LmJm7dmKrs^!!)HT!!)HT!<2Bd!;l3a!<;I%!:K7Tmd:&Tmd:)CmJm7TmJm7T
+mJsKZ"$)mI.F.qpUmsGrmXaf,mK5J>Ua^f~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJW@3!<)?c!!qummd:)CmJm7amK3IWmK!.P"9@lX!!)oarrE)e
+$NTV_!:K7T!:K7T!<)<q!:K7T!:K7Tmd:)CmJm7bmf*:emf*:emL90a!!)HT!:K7Tmd:&TrU0[c
+s6]jeqsOIa%IO2rmd:&Tmd:)CmJm7amK3IWmK!.P"9@lX!!)oarr=#+!!)HT!!)HT!!)HT!!)HT
+!!)HT!:Bgemd:)LmJm7dmKrs^!!)HT!!)HT!<2Bd!;l3a!<;I%!:K7Tmd:&Tmd:)CmJm7TmJm7T
+mJsKZ"+A23@F"lSb/Sj\mXaf,mK7mWb$ff~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qW7bXrT=+[#j)-LjoFQ+!!)oY!s%KG!;km]!9WDD!;kpY!<;0h
+!9WDDk2lXDk2lXDrT4Rik2lXDk2l[+joFQ+!!)rZrrE)]rrE)]%05Mj!9WDDk2l[+jo>D[k5PG]
+jo>DYk5PDjjo>DDjo>DDjoFQ+!!)oY!s%KG!;km]!9WDD!;kpY!#t&#!9WDD!9WDD!9WDD!9WDD
+!9WDDjo>DDjoG/<!!*#\$392g!9WDD!9WDDroO1\qr[nYs5k$rk2l[+jo>DDjoFQ+!!)0D!!)0D
+!3kSfc1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&C>8!<;Hh!:BgerpBadqsFRemd:&TrU0[crpBadqsFFarpBjg
+mJm7dmK3IWmK!1Q!s%cW!<2Bg!:BgerpBadqsFajmJuYTmJu\C!<2Bj!:K7Tmd:)QmJm7dmJm7a
+mJm7dmK3IWmK!7S!s%cW!;c*d!:K7T!<)?c!<2Bd!;l0a!<2Bg!:K7TrU'afmd:)RmKEUYmJuYT
+rpKddq!J=dmd:)CmK!4R!s%cW!<2Bd!;l0a!<2Bg!:BgerpBjgmJm7dmK3IWmK!7S!!'7k"#6UA
+.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2?t+!<;Hh!:BgerpBadqsFRemd:&TrU0[crpBadqsFFarpBjg
+mJm7dmK3IWmK!1Q!s%cW!<2Bg!:BgerpBadqsFajmJuYTmJu\C!<2Bj!:K7Tmd:)QmJm7dmJm7a
+mJm7dmK3IWmK!7S!s%cW!;c*d!:K7T!<)?c!<2Bd!;l0a!<2Bg!:K7TrU'afmd:)RmKEUYmJuYT
+rpKddq!J=dmd:)CmK!4R!s%cW!<2Bd!;l0a!<2Bg!:BgerpBjgmJm7dmK3IWmK!7S!!'7k"*r&/
+@F"lS`l`RXmXaf,mK7aW`aOA~>
+!quZ5J`_OGX6'N's7W85rrVoo`VS`o!<;0`!9O7]roO1\qrS"]k2lXDrT=+[roO1\qrRkYroO:_
+jo>D\joYVGjoG>A!s%KG!<2*_!9O7]roO1\qrS1bjoFNDjoFQ+!<2*b!9WDDk2l[Ajo>D\jo>DY
+jo>D\joYVGjoGDC!s%KG!;bg\!9WDD!<)'[!<2*\!;kmY!<2*_!9WDDrT41^k2l[BjokbIjoFND
+roX4\puVb\k2l[+joGAB!s%KG!<2*\!;kmY!<2*_!9O7]roO:_jo>D\joYVGjoGDC!!'7c"3(<6
+UsAuApA`*_k(2Zqjo`U&p8!3~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3Vr.D!;c*a!:K^arpK^brpKacs6faaqsFFarpBdeme["amJm7b
+mK3IWmK!7S!<DQb!;l0j!:BjT!:BjTmK!7S"p")Z!:K7Tr9aObrpBadqsFFarpBjgmd:)SmK3IW
+mK!4Rr;cibrW)udqZ-N]!!*#d!s%cW!<)<f!:K7TrU'dgmd:&Tr9jOaqX4@`"RZ9XmK!4R!s%cW
+!<2Bd!;l0a!<2Be!:K^a!:K^as6]jerpBadYjMTRS>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJW@3!;c*a!:K^arpK^brpKacs6faaqsFFarpBdeme["amJm7b
+mK3IWmK!7S!<DQb!;l0j!:BjT!:BjTmK!7S"p")Z!:K7Tr9aObrpBadqsFFarpBjgmd:)SmK3IW
+mK!4Rr;cibrW)udqZ-N]!!*#d!s%cW!<)<f!:K7TrU'dgmd:&Tr9jOaqX4@`"RZ9XmK!4R!s%cW
+!<2Bd!;l0a!<2Be!:K^a!:K^as6]jerpBadYjMUA`l_`8rrU?_I=^g;m]5aXIE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qW7bXqW7eYk5,/Xk5>;Zk5GA\k5,/Ujo>D\joGJEqZ-ZY!!)rZ
+!s%KG!<2*]!9X.YqrS1bjoFNDjoFQ+!<2*b!9WDDk2l[Ajo>D\jo>DYjo>D\joYVGjoGDC!s%KG
+!<)'Y!<2-[!<;3Y!;kmY!<2*_!9WDDrT41^k2l[Bjob\Hjo>DZk5GAWk5PDajoFQ+!<)$^!9WDD
+roO1\qrRkYroO4]k5,,Yk5,/Yjo>D\jo>Ccjo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&C;<!;c*c!:BgeqsFFarpBadr9jRb!q$$gp[/"]rpBjgmJm7a
+mJm7bmK3IWmK!7S!s%`h!;Gmf!:BjT!:BjTmK!7S"p")Z!:K7Tr9aObrpBadqsFFarpBjgmd:)S
+mK3IWmK!7S!!*#d!!)rbrr<,g!!)c]!!*#d!s%cW!<)<f!:K7TrU'ghmd:)C!;l3a!;c-_!<;He
+!<)<f!:K7TrpBadqsFFarpBjgmJm7bmf*:amJm7dmJm6kmK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2?q/!;c*c!:BgeqsFFarpBadr9jRb!q$$gp[/"]rpBjgmJm7a
+mJm7bmK3IWmK!7S!s%`h!;Gmf!:BjT!:BjTmK!7S"p")Z!:K7Tr9aObrpBadqsFFarpBjgmd:)S
+mK3IWmK!7S!!*#d!!)rbrr<,g!!)c]!!*#d!s%cW!<)<f!:K7TrU'ghmd:)C!;l3a!;c-_!<;He
+!<)<f!:K7TrpBadqsFFarpBjgmJm7bmf*:amJm7dmJm6kmK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`VS]s!;bg[!9O7]qrRkYroO1\r9""Z!p0I_pZ;GUroO:_jo>DY
+jo>DZjoYVGjoGDC!s%H`!;GU^!9O:D!9O:DjoGDC"p!fJ!9WDDr8mtZroO1\qrRkYroO:_k2l[C
+joYVGjoGDC!!*#\!!)rZrr<,_!!)cU!!*#\!s%KG!<)$^!9WDDrT47`k2l[+!;kpY!;bjW!<;0]
+!<)$^!9WDDroO1\qrRkYroO:_jo>DZk5PGYjo>D\jo>Ccjo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3Vr.D!;c*c!:K7TqsFFarpBadqsFOdmd:)LmKWa[mJm7TmK!.P
+rrE#c$39M^!:K7T!:K7Tp[8%]rpKdds6]jerpC!kmd:)CmJm7cmJm7dmJm7amKWa[mJm7TmK!7S
+!s%cW!<2Bd!<2Bd!;l0d!:K7Tp[/q"md:&Tmd:&Tmd:&Tmd:&Tmd:&Tmd:)CmK!.P!!)l`rrE&d
+rrE)errE)e"9@lX!!)oa!!*#d!s%cW!;l0a!;l0e!:K7T!3kkn3LllocMmsAS2l/gJaTT,"$)mI
+.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJW@3!;c*c!:K7TqsFFarpBadqsFOdmd:)LmKWa[mJm7TmK!.P
+rrE#c$39M^!:K7T!:K7Tp[8%]rpKdds6]jerpC!kmd:)CmJm7cmJm7dmJm7amKWa[mJm7TmK!7S
+!s%cW!<2Bd!<2Bd!;l0d!:K7Tp[/q"md:&Tmd:&Tmd:&Tmd:&Tmd:&Tmd:)CmK!.P!!)l`rrE&d
+rrE)errE)e"9@lX!!)oa!!*#d!s%cW!;l0a!;l0e!:K7T!3kknIE'E<cMmsg`dNF+JaTT,"+A23
+@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qW7bXqW7k[k2l[@jo>D\jo>DYjoYVGjoG/<#6<oK!!)0D!;kpY
+!<)$e!9WDDk2lXDk2l[<k5PG\k5PG]jo>D\jp(nKjoFQ+!!)u[!!*#\!!)oY#6<oK!!)0D!<2*_
+!9WDDroO1\roO1\qrRt\k2l[<jr+6^jo>DDjo>DDjo>DDjo>DDjo>DDjoFQ+!;kmY!;bjX!<2-\
+!<;3]!<;0a!9WDD!;kmY!<2*_!9WDDqrRkYqrS"]k2lXDYiZ&4pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&C;<!;c*`!<2Eb!<;Ka!!)Hc!<)?a!;c-`!!2KfrpK^brpK^b
+!U]semf*7fmK!7Sr;c]^!!*#d!!*#d!!*#d!s%cW!<2Eb!!2KfrpBadqsOC_rpBadrpBjgmd:)S
+meZtamem.amem._mem.amem.amem.bmKEUYmJm7Tr;cZ]rrE#cr;cibrVuue!;l0a!<2Bd!<2Eb
+!<2Eb!<2Ed!!M]imd:(]mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2?q/!;c*`!<2Eb!<;Ka!!)Hc!<)?a!;c-`!!2KfrpK^brpK^b
+!U]semf*7fmK!7Sr;c]^!!*#d!!*#d!!*#d!s%cW!<2Eb!!2KfrpBadqsOC_rpBadrpBjgmd:)S
+meZtamem.amem._mem.amem.amem.bmKEUYmJm7Tr;cZ]rrE#cr;cibrVuue!;l0a!<2Bd!<2Eb
+!<2Eb!<2Ed!!M]imd:(]mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`VS]s!;bgX!<2-Z!<;3Y!!)0[!<)'Y!;bjX!!23^roX.ZroX.Z
+!TjC]k5PD^joGDCr;c]V!!*#\!!*#\!!*#\!s%KG!<2-Z!!23^roO1\qr[hWroO1\roO:_k2l[C
+k5,,Yk5>;Yk5>;Wk5>;Yk5>;Yk5>;ZjokbIjo>DDr;cZUrrE#[r;ciZrVuu]!;kmY!<2*\!<2-Z
+!<2-Z!<2-\!!MEak2lZMjo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J-Z!!3Y_i!.jS<mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=gke!3Y_i!.jS<mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<K'!%5Y3#]aJ`d!p"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nSfn!3Y_i!.jS<mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%PGa!3Y_i!.jS<mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`Id4P!3YGa!.j;4jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LBi;Lq`U;?6aomK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I#\<In/[<<3'rmK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\eK;Lq`U;?6aojo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HmI'iOcgCc5qsOF`ea<D;r9aObJaTo5"$)mI.F%koUmsIBmK-;262ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE62ikE
+62ikE62ikE62ikE62ikE62ikH5rgqkr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sE
+r]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr](*I3@W3=
+r]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sE
+r]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]'sEr]('H3B9D)3<2AE3<2AE3<2AE3<2AE3<2AE
+3<2AE3<2AE3<;GGqsFPHS>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2mI'iOcgCc5qsOF`ea<D;r9aObJaTo5"+A23@EnfRb/Sl,mK$>-JN1G)!@5[93;kf:s823d
+IE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=mH49GcfP3-qr[kXe`Hi3r8mtZJ`a?%"3pQ>SBV!6p<EKs!E-o93<1f53<1f53<1f53<1f5
+3<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f5
+3<1f53<1f53<1f53<1f53<1f23<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f5
+3<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<V&s3?Z<?3<1f5
+3<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f5
+3<1f53<1f53<1f53<1f53<1f53<1f53<1f53<1f23<1f53<1f53<1f53<1f53<1f53<1f53<1f5
+3<Coqs81p\c1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@mdC)TrU'XccgCc5qsFFae*[29JaT]/"#6UA.F%koS>7n:mK$5cJbHnQ!L3V8pAO[bs823d
+0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.mdC)TrU'XccgCc5qsFFae*[29JaT]/"*r&/@EnfR`l`T(mU]Dumdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff6J+E$umdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdcA;
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mUPhUo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mf31P"*r&/@F"lS`l`RXmXaf,mK7aW`aOA~>
+!quZ5mcONLrT4([cfP3-qrRkYe)gW1J`a,t"3(<6Us8o@pA`,/k%.Hjk3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hBoJ*uIek3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3e0-
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k%!iAmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k5Y>@"3(<6UsAuApA`*_k(2Zqjo`U&p8!3~>
+!i2>Hn*^2UamK-/qsFFae*[29kO&<Mo'QJXJaV4Z"$)mI.F%koUmsIBmJp.9s1eR6S:U_;s823d
+3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2n*^2UamK-/qsFFae*[29kO&<Mo'QJXJaV4Z"+A23@EnfRb/Sl,mJp7<s1eR6Q%Au4s823d
+IE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=n)jWMalWR'qrRkYe)gW1kN2aEo&]oPJ`bYJ"3pQ>SBV!6p<EKs!)idq!;?El!;?El!;?El
+!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El
+!;?El!;?El!;?El!;?El!;?El!;?<i!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El
+!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El"8;cpPl:U^
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+pAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpAY'lpA=jipAY'lpAY'lpAY'lpAY'lpAY'lpAY'l
+pAY'npAb0ijo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@n*U/Up[7t[rpBdemf!1dmf!4dmK!=UrVurdrW)udr;cib!<DQe!<2Eb!;u9a!<;Kc!<2Bf
+!:Bjbmem.bmK3IW!!)ucrW)rcr;cib$39M^!:K7Tmd:)CrW)rcr;cc`rW)udrW)rc!!*#dr;Zic
+r;cib!!%T<j6d"(UmrmYrrS^d1&LA=;M"k_rrA:7s82inmK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.n*U/Up[7t[rpBdemf!1dmf!4dmK!=UrVurdrW)udr;cib!<DQe!<2Eb!;u9a!<;Kc!<2Bf
+!:Bjbmem.bmK3IW!!)ucrW)rcr;cib$39M^!:K7Tmd:)CrW)rcr;cc`rW)udrW)rc!!*#dr;Zic
+r;cib!!%T<j6d"pb/Rl7rrU3_H2I"0<It1brrA=8s82inmK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5n)aTMpZDDSroO4]k5G>\k5GA\joGJErVur\rW)u\r;ciZ!<D9]!<2-Z!;u!Y!<;3[!<2*^
+!9O:Zk5>;ZjoYVG!!)u[rW)r[r;ciZ$395N!9WDDk2l[+rW)r[r;ccXrW)u\rW)r[!!*#\r;Zi[
+r;ciZ!!%T4j5pH_s7W85rrVoo`V\ct;M"k_rr@t.s82injo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>Hn*U/Uq!S.^s6fmes6fmes6fmes6^6pmd:&Tmd:&Tmd:)PmLB6bmJm7TmJu\C!!)HT!;l0m
+!:K7T!:K7T!:K7T!;l0a!;l3a!"&&n!:K7Tmd:&TqsG7#md:)C!!)HT!:K7T!:K7Tmd:&Tmd:)P
+mLoTgmJu\C!!)HT!!)Eemd:)CmJqh+h!P8)S>7UYrrT!d3W&4E;M"k_rrAR?s82inmK5J>UaaUh
+!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2n*U/Uq!S.^s6fmes6fmes6fmes6^6pmd:&Tmd:&Tmd:)PmLB6bmJm7TmJu\C!!)HT!;l0m
+!:K7T!:K7T!:K7T!;l0a!;l3a!"&&n!:K7Tmd:&TqsG7#md:)C!!)HT!:K7T!:K7Tmd:&Tmd:)P
+mLoTgmJu\C!!)HT!!)Eemd:)CmJqh+h!P8m`l_`7rrU?_IJ`F4<It1brrA=8s82inmK7mWb$iTq
+!m8N2JaS*WX6p(<`l__?~>
+!rqu=n)aTMpu_SVs5s=]s5s=]s5s=]s5j[hk2lXDk2lXDk2l[@jphCRjo>DDjoFQ+!!)0D!;kme
+!9WDD!9WDD!9WDD!;kmY!;kpY!"%cf!9WDDk2lXDqrS[pk2l[+!!)0D!9WDD!9WDDk2lXDk2l[@
+jq@aWjoFQ+!!)0D!!)-]k2l[+joBtpgu\^`pA^Z,rrMi<qrRlVJcELb!0i'7qu?QU"3pQ>SB_'7
+p<A0NJ`a#q"3pQ>S:C~>
+!h?&@n*U/Uq!J+^rU'afmd:)SmJm7dmK3IWmK!7S!!*#d!!)oa!s%cW!<2Bg!:K7TrpBadqsFOd
+md:)RmK3IWmK!+OrrDub!!*#d!s%`h!<2Bd!;l0f!:K7TmK!7S!s%cW!<2Bg!:K7TrpBadqsFOd
+mJm7dmJm7dmf!4dmK<OXmJm6<mbR:50r1<gc2Rj8UbVc7!)eCJ^]+:uJcGWIqsFP@UmrmZrrS^d
+0nJbDm]5aX0r1<gJ,~>
+!liB.n*U/Uq!J+^rU'afmd:)SmJm7dmK3IWmK!7S!!*#d!!)oa!s%cW!<2Bg!:K7TrpBadqsFOd
+md:)RmK3IWmK!+OrrDub!!*#d!s%`h!<2Bd!;l0f!:K7TmK!7S!s%cW!<2Bg!:K7TrpBadqsFOd
+mJm7dmJm7dmf!4dmK<OXmJm6<mbR:5H-4-8c2Rjbb'EmP!*+UM^]+:rJcGWIqsFQ3b/Rl8rrU3_
+H%GC7m]5aXH-4-8J,~>
+!quZ5n)aTMpuVPVrT41^k2l[Cjo>D\joYVGjoGDC!!*#\!!)oY!s%KG!<2*_!9WDDroO1\qrRt\
+k2l[BjoYVGjoG8?rrDuZ!!*#\!s%H`!<2*\!;km^!9WDDjoGDC!s%KG!<2*_!9WDDroO1\qrRt\
+jo>D\jo>D\k5GA\job\Hjo>C4k2#/%`W,Y-c2Rk=s2Flt!`K'lrr2ulrr2ulrr2ulrr2ulrr2ul
+rr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ulrr2ul
+rr2ulrr2ulrr2ulrr3)os8VflrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDcl
+rrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrri&qMuWMMrrDcl
+rrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDcl
+rrDclrrDclrrDclrrDclrrDclrrDclrrDclrr_ups7ZHl!;?El!;?El!;?El!;?El!;?El!;?El
+!;?El!VZQjjo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>Hn*U/Uq!J+^rU'afmd:)SmJm7dmK3IWmK!7S!!*#d!!*#dr;clc!!*#d!s%cW!<2Bd!;l0d
+!:K7TrU'afmd:)Nmf!4cmJm7dmK!=UqZ-W`r;clcrrE#c!s%cW!<2Bg!:K7TrpBadqsFIbme["`
+mf*:dmJm7dmf!3;mbdF73Llloc2Rj@S2pK7!)iapquH0b!!%TMh>[JFJcGWIqsFPHS>7UZrrT!d
+3J$ULm]5aX3LlloJ,~>
+!m8N2n*U/Uq!J+^rU'afmd:)SmJm7dmK3IWmK!7S!!*#d!!*#dr;clc!!*#d!s%cW!<2Bd!;l0d
+!:K7TrU'afmd:)Nmf!4cmJm7dmK!=UqZ-W`r;clcrrE#c!s%cW!<2Bg!:K7TrpBadqsFIbme["`
+mf*:dmJm7dmf!3;mbdF7IE'E<c2Rjf`dRaP!*/ssquH0b!!%TMh>[J?JcGWIqsFQ7`l_`8rrU?_
+I=^g;m]5aXIE'E<J,~>
+!rqu=n)aTMpuVPVrT41^k2l[Cjo>D\joYVGjoGDC!!*#\!!*#\r;cl[!!*#\!s%KG!<2*\!;km\
+!9WDDrT41^k2l[>k5GA[jo>D\joGJEqZ-WXr;cl[rrE#[!s%KG!<2*_!9WDDroO1\qrRnZk5,/X
+k5PG\jo>D\k5G@3k25;'c1_1-bl7_;c26W';Z6UqpA=pjrrDclrrDclrrDclrrDclrri#qs8Vfl
+rrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDcl
+rrDcirrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDcl
+rrDclrrDclrrDclrrDclrrDclrrDclrrDclrrDclrr_ups-3K^!;?El!;?El!;?El!;?El!;?El
+!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El!;?El
+!;?El!;?El!;?El!;?<i!;?El!;?El!;?El!;?El!;?El!;?El!;?El!quZoqrS"*pA^Z-rrMi<
+J`_OGX6'N/pA^Y5~>
+!h?&@n*^2Uq<e4_rU'afmd:)SmJm7dmK3IWmK!7S!!*#d!s%cW!<2Bg!:K7TrpBjgmd:)SmJm7a
+mK3IWmK!4R!s%cW!;Gp]!<;He!<2Bg!:BgeqsFFarpBpimd:)C!<2Bg!:K7TrpBjgmd:)SmJm7a
+mK3IW!!)l`rW)ud!!)rbrr@W<i9g\%UmrmYrrS^d1&LA=;Z-Op!<3#u!:Tpf!.k1+rrA:7s82in
+mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.n*^2Uq<e4_rU'afmd:)SmJm7dmK3IWmK!7S!!*#d!s%cW!<2Bg!:K7TrpBjgmd:)SmJm7a
+mK3IWmK!4R!s%cW!;Gp]!<;He!<2Bg!:BgeqsFFarpBpimd:)C!<2Bg!:K7TrpBjgmd:)SmJm7a
+mK3IW!!)l`rW)ud!!)rbrr@W<i9g\mb/Rl7rrU3_H2I#@<WDpqqYpQqqYpNqqZ$ElqZ$ElqZ$El
+qZ$ElqYpQqqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqYG^AqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElOoP:XqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$D%s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)TlqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqsFQ3b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5n)jWMq;qYWrT41^k2l[Cjo>D\joYVGjoGDC!!*#\!s%KG!<2*_!9WDDroO:_k2l[Cjo>DY
+joYVGjoGAB!s%KG!;GXU!<;0]!<2*_!9O7]qrRkYroO@ak2l[+!<2*_!9WDDroO:_k2l[Cjo>DY
+joYVG!!)lXrW)u\!!)rZrr@W4i8t-\s7W85rrVoo`V\cu;ZH^h!!*#lrrDN]!!%TDh=^l-s+0nB
+p&P-ijo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HmdC)TrU($nmd:&Tmd:&Tmd:)SmJm7dmK3IWmK!7S!!*#d!s%cW!<2Bg!:K7TrpC!kmd:)C
+mJm7amL'$_mJm7TmJm7TmJutK$39M^!:K7T!:K7TqsFFarpC0pmd:)CmJu\C!:K7TrpC!kmd:)C
+mJm7amK3IWmK!.P"p")Z!:K7TqsFFaJaVIa"$)mI.F%koUmsIBmJp/_rr<&trr<&frr<%Ms5!\T
+S:U_;s823d3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2mdC)TrU($nmd:&Tmd:&Tmd:)SmJm7dmK3IWmK!7S!!*#d!s%cW!<2Bg!:K7TrpC!kmd:)C
+mJm7amL'$_mJm7TmJm7TmJutK$39M^!:K7T!:K7TqsFFarpC0pmd:)CmJu\C!:K7TrpC!kmd:)C
+mJm7amK3IWmK!.P"p")Z!:K7TqsFFaJaVIa"+A23@EnfRb/Sl,mU]DuqY'dZ!;?9_q>gBcqY'dZ
+qY'dZqY'dZqY'dZ!;?9_qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'd^J+ia4qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY$3S
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqIB6qpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqZ$H\"+A23@F"lSb/Sj\mXaf,mK7mWb$ff~>
+!rqu=mcONLrT4Ifk2lXDk2lXDk2l[Cjo>D\joYVGjoGDC!!*#\!s%KG!<2*_!9WDDroOFck2l[+
+jo>DYjpM1Ojo>DDjo>DDjoG,;$395N!9WDD!9WDDqrRkYroOUhk2l[+joFQ+!9WDDroOFck2l[+
+jo>DYjoYVGjoG;@"p!fJ!9WDDqrRkYJ`bnQ"3pQ>SBV!6p<EKs#?(Tqme6>Smf)n[!<2Zlmf)n[
+mf)n[mf)n_me6>Smf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n^me6ABrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6K_PlLIF
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6H^p@dqRp&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&P-ijo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@mI'lPrU0UarpBadrpBadrpBjgmd:)SmJm7dmK*CVmeZtbmK!7S!!*#drr<)f!;l0a!<2Eb
+!<2Bd!;c-^!<2Eb!<)?a!<;Ka!"/,omd:&TmJu\C!<2Bd!<2Ed!!2KfqsOIas6fgc$LRlomd:&T
+mJm7Tr;cib!!%T<j6d"(UmrmYrrS^d1&LAK;ZHIjpAY-mpAagdpAajb!!E8ps7ZBk9)nVb!<;`m
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAaj[J,f6BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpA^BWpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdp1+-rs7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb$X
+"#6UA.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.mI'lPrU0UarpBadrpBadrpBjgmd:)SmJm7dmK*CVmeZtbmK!7S!!*#drr<)f!;l0a!<2Eb
+!<2Bd!;c-^!<2Eb!<)?a!<;Ka!"/,omd:&TmJu\C!<2Bd!<2Ed!!2KfqsOIas6fgc$LRlomd:&T
+mJm7Tr;cib!!%T<j6d"pb/Rl7rrU3_H2I"><WDX`o(E(Wo(MVSo(MYQ!!Drcp@A.^9(qiL!;>s`
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYFJ+iI,o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(J4Go(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJo(MYJo(MYJnmhCap@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo)JUT
+"*r&/@F"lS`l`RXmXaf,mK7aW`aOA~>
+!quZ5mH4<HrT=%YroO1\roO1\roO:_k2l[Cjo>D\joPPFk5,,ZjoGDC!!*#\rr<)^!;kmY!<2-Z
+!<2*\!;bjV!<2-Z!<)'Y!<;3Y!".igk2lXDjoFQ+!<2*\!<2-\!!23^qr[nYs5s7[$K_<gk2lXD
+jo>DDr;ciZ!!%T4j5pH_s7W85rrVoo`V\cu;ZH^`!!)uc!!*#dr;cfar;cib!s%cW!.jRrmK&7G
+JaWL)!<;rY"3(<6UsAuApA`*_k(2Zqjo`U&p8!3~>
+!i2>HPjSMOg@"t@JaUDC"$)mI.F%koUmsIBmK$5crUp3krq6<lrq??ls7ZHms7ZHms7ZHms7QNp
+p&G)Dp>GWFSH"06rUp6kqsFPHS>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2PjSMOg@"t@JaUDC"+A23@EnfRb/Sl,mU]Duo'Z):!:KFG!:KFG!!)TX!!)TX!!)TX!!)TX
+!:Bgeo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z)>J*umqo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'VeCo'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):nmh+Ymdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o)JUT"+A23@F"lSb/Sj\mXaf,mK7mWb$ff~>
+!rqu=Pi_rGg?/D8J`ai3"3pQ>SBV!6p<EKs!E/ssmMt?hmdB3;mdB3;!:JtL!:JtL!:JtL!:JtL
+mJm7dmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDK
+mJuDKmJuDHmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDK
+mJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmKD\?mZdbNmJuDKmJuDKmJuDKmJuDK
+mJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDK
+mJuDKmJuDKmJuDKmJuDKmJuDHmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmK2P=s81p\c1_1-
+c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@k3i$F\*a4rh<t4AJaUAB"#6UA.F%koS>7n:mKHMgme6)Br;^'ip?qVSp?qYB!:KO\p?qYB
+!:KO\p&OgSp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?q?up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp6>UFp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBA+o?ame6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6):p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBs823d0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.k3i$F\*a4rh<t4AJaUAB"*r&/@EnfR`l`T(mKHVjlL*s*r;^'emcs3?mcs6*!:&tPmcs6*
+!:&tPmJu\?mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs(emcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mZmh;mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*A+&XMlL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s&mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*s823dH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5k2uI>\)mYjh<+Y9J`af2"3(<6Us8o@pA`,/joJBRrT=%YrT4([rT41^k2l[BjokbIjoFND
+J`bkP!K6Z&k5FEBs81p\`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&5U;ZHIYp?hqKp?hn\p?hqKp?qVSp?hqKp?qVSp?hn\p?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp@a"(p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBSH&<Np?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qWame6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6ABp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYSqsFPH
+S>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F5<WE$_!!*#`rrE)a!!)u_!s%WO!<)0c!:&hL!.jFll2d1M
+Ja34!!<;ra"+A23@F"lSb/Sj\mXaf,mK7mWb$ff~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRoWs8D'[!<2-\!<;0]!<)$^!9WDDrT44_k2lXDJ`bhO!L3V8
+k5FEBs81p\c1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA>;ZH^`!!)uc!s%cW!<)<f!:K7TrU'ghmd:)C!.jRqmK&jX
+JaWL)!<;ra"#6UA.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"1<WE$[!!)u[!s%KG!<)$^!9WDDrT47`k2l[+!.j:ijoLbI
+J`cpn!<;ra"*r&/@F"lS`l`RXmXaf,mK7aW`aOA~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\cu;YL+H*9I7XhWEYphW=gphWEYphW=gphWEYphW=gp!9X:;
+!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;
+!9X18!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;
+!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;"QnRtMt[/,!9X:;!9X:;!9X:;!9X:;!9X:;
+!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;
+!9X:;!9X:;!9X:;!9X18!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!9X:;!p8A>qrS""s7W86rrVoo
+`I[0&k,[VH`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4F;ZH^`!!)uc('*dj!!)HT!!)HT!!)HT!!)HT!:K7TJaVIa
+!MoaHmeuPRs823d3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F5<WE$[!!)u[('*LZ!!)0D!!)0D!!)0D!!)0D!9WDDJ`bnQ
+!M07Ak5FEBs823dIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrVHfs5r2#h>lEphW=h#h>dQ<h>dQ<h>dQ<h>dQ<h>lEp!9W/#
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\Wk'u7MhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE[bs5r2#hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWA>)k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2tO_hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWFk8jo`m%
+s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA>;ZH^`quH]`r;cfar;cib"9@lX!!%T<iU-`:s+0V:mK!:a
+mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"1<WE$[quH]Xr;cfYr;ciZ"9@TH!!%T4iT:0/s+0>2joGGY
+mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\d$;YJu0hWF_9"6SJ&hYdEVk2,7Wr;]IPhW=h#h>dQ<hWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hVNbEhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WPkNtrhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE[)k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2+tWhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\pqrS""s7W86
+rrVoo`I[0&k,[VH`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&5U;ZHIYp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp@a"(p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBV#U/Vp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qWame6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6ABp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYSqsFPH
+S>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F5<W@X8_!1ros+0J6l2^k]mK7mWb$iTq!m8N2JaS*WX6p(<
+`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRoWs+0=JjoM"PJ`cpn!<;rY"3pQ>SB_'7p<A0NJ`a#q"3pQ>
+S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LBM;ZH1Yme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bmd>Sume6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BV#TlVme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6'Yp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qABme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)KqsFP@
+UmrmZrrS^d0sC"rp5\k9mK52>S1/s~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I#@<WD@PlL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lKWlelL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*U&XEGlL*s*lL*s*lL*s*lL*s*
+lL*s*lL*s*lL*s*lL*qImcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs**lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s;qsFQ3
+b/Rl8rrU3_H*?XOo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)>
+@.*URo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o("*po'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'l&LH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\cu;YG\(^ubZfp4;B)joGGYjo`U&p8$"6!quZ5YNCE(NpcE!
+"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4F;ZD=A_"If9s+0nBp&P-imK5J>UaaUh!i2>HY3p&ume6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bmd=KVme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6):,kg["me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6,;
+"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`GD<WDXXo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o(%:uo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):WrMYXo'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z'Ymdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdfr:o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)KqsFQ7
+`l_`8rrU?_IBN!Qo'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'YpR
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):mNhAko'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z);mK7mWb$ff~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRoWs8MEdk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k54QHk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcOk3hZ5s8MEdk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcK
+k5OcKk5OcKk5OcKk54QHk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcMk3i9Hjo`m%s.%@6!VXd@
+k%a>HmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"k$[W>mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNXWmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mdK9?c1_1-J,~>
+!h?&@JaS*WeF*A1mJm4[nEpB5UmrmYrrS^d1&LA>;ZD=A_"If1s+0nBp&P-imK52>S12b`!h?&@
+YO;GaJcCu7rV#aK"#6UA.=_~>
+!liB.JaS*WeF!G0meZeNs8Vorp@@\?"*r&/@EnfR`l`T(mK$>fJaU>A!NQ0NmeuPRs823dH-4-8
+cMmscb'C2Y"7kmRqLS[6rrr8mmdff:nEpC(b/Rk?~>
+!quZ5J`_OGeE6f!s7Qs&pAajdpAajdpAajdpAb-cs6fC="3(<6Us8o@pA`,/k%.Hjk3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBoJ*uIek3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3f&Fk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k%!iAmcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k5Y>@"3(<6UsAuApA`+8k5XlJp1=9ts7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmIeNg8s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s8VfmpAajdpAajdpAajdpAajdpAajdpAajdpAajdrV$3XnE'hls7W7=~>
+!i2>HnEtj*JPti4!9X.G!WVlmrsn2Zk3hC"k3hC"k3hC"k5P)DmK5J>UaaRg!i2>HqsFJ_s+0mZ
+p&VQ#JbK'9!<;ra"$)mI.F.qpUmsHJmf3"Ys8VLqk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k2q$Yk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBomcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs8jok,Gp?qYCmK5J>Ua^f~>
+!m8N2nEtj-JQ;&:!9X.Gs7-Zrs8(a;io]7_io]7_io^7"!q,XMnEpC,`l_`7rrU?_IJ`F5<W@X<
+_!V6+s+0V:mK!:amK7mWb$iTq!m8N2Y3u>\s7U()qXWq6io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io5CKio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7[k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO[h?W&sio]\"mdfi7"+A23@=S~>
+!rqu=nE,:"JPti4q<%_Frq?BK!7h#(!7h)*"kDJ[k3h[,jo`m%s.%=5!VXe8k%.HjmcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs*J*-1]mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcL>FmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mUPDIk3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mf31H"3pQ>SB_'7p<Bc&s6^-cmf3"KhVQf^h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*hZ).*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hZ).*
+h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*hYbn,hWF7gmdK9?c1_1-J,~>
+!h?&@nEp9SJcC<$mJd1KqsFR[k3hs7s8D*JmK52>S12__!h?&@qsFJ_s+0URmK']pJaWL)!<;ra
+"#6UA.F.qpS>7mCmKE7OmcO4os.0/kmcNC)k5P)DmK52>S1/s~>
+!liB.nEp9VJcC<$mJd1KqsG9kio]P+s8)HcpA4LZpA4LZp>Xrcg>_DemK7aW`aR-l!liB.qsFJb
+s+0=JjoMXbJ`cpn!<;ra"*r&/@F"lS`l`S0mKV\5ip-C?s8Mk&pA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZqL&#5pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4XZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'Uhk2+\Gg>:iWmdfl8"*r&/@=S~>
+!quZ5nE'^KJcC<$mJm%F#O^I*k5YJTmf)n]me6)Jp&XU<rm_#*n)a_ks7W85rrVoo`V\e/;ZGn9
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2q0Mk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7WV#TT6k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,61hWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEtWk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,8#qrS""s7W86rrVoo`NSD(mf)&Ek4\iPp&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OOZp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OOZp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[pAaO^hUTmLec,"+jo`U&p8!3~>
+!i2>HnEp9SJcC<$mJd1KqsOIG!:KIY!;?BR!8d55"$)mI.F%koUmsIBmU];YXL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(1J$c;aXL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9
+XL,(kXL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XL,(9XCJW=[&gX9[&gX9[&gX9[&gX9[&gX9
+[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9[&gX9XL,(9XL,(9XL,(9XL,(9
+XL,(9XL,(9XL,(9XL,(9XT/1c"$)mI.F.qpUmsHKmf2GKhLY]srrV?>ec"@mmK5J>Ua^f~>
+!m8N2nEp9VJcC<$mJd1KqsFdIg>_8gs8VrqqYpKuqZ$Els6fg=nEpC,`l_`7rrU?_IJ`GD<T:$]
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiCQOWiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)V;eMXWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)Wii@3Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\M)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiB%qsFQ7`l_`8rrU?_IBW&=hYl..pAP#"qZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqYFV"qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$Eg+923;qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqY'(&df%l"lL4-CIE'E<J,~>
+!rqu=nE'^KJcC<$mJm%Fs4./+!quZorq6EnpAb-c!rqu^r71<!"3pQ>SBV!6p<EKs!E.d*Uqic,
+SDJgmrM0GnqrS"*pA^Z-rrMi<YNGc5"Rc!`pA]^;U@ni[hTa<qc.1A4jo`m%s."T~>
+!h?&@nEp9SJcC<$mJd1KqsFU;k2,7ooD\s]e_]05nEpB5UmrmYrrS^d1&LA=;M"k!s1&++mK52>
+S12b`!h?&@YO2SNk2t4Np4<76rs%W9e`P`=hXBk70r1<gJ,~>
+!liB.nEp9VJcC<$mJd1KqsFU4g=kESo`#*gimQQ7cLC6(H-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3
+b/Rl8rrU3_H*?W>db<F'f(+ClSc8rghU9j/g<SF@mK7aW`aOA~>
+!quZ5nE'^KJcC<$mJm%F(WFqLeaEJ2s7ZKds7ZKds7ZK\hSn$i`UN!l`W,Y-c2Rk=s2Flt!)eCJ
+JcE7[qrS""s7W86rrVoo`NSD-c.1@hc0kH.!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j
+!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j
+!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;?El$23f;
+c-=ehc.27Ojo`U&p8!3~>
+!i2>HnEp9SJcC<$mJd1KqsFR2k2+tjrr_trKD,<E"Rb.'k0<D`"$)mI.F%koUmsIBmJp/Zrr<%M
+s+13fs823d3LllocMmsAS2me@!R9d+eH#;os.')hmf(`=hTa=-nEpB=S>7Ta~>
+!m8N2nEp9VJcC<$mJd1KqsFX-g=FjGqYU:#p9KPGs8Vr\f$`9hnEpC,`l_`7rrU?_IJ`F4<VQLn
+!.k0$s24m6mK7mWb$iTq!m8N2YO2V7g="9pmeVM7T)T)ik0D9#g;_:pnEpC,`l__?~>
+!rqu=nE'^KJcC<$mJm%F(VSADc0k<*pAajdpAa!opAaj[k0;0$^$t.dc1_1-bl7_;c26W';YU1k
+!.k0$s24m6jo`m%s.%@6!VXdAjoN0Grl#*(me6ASpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c
+!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c
+!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c
+!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c
+!rquorq6EnpAb-c"TS2qmb[r^"4b*(hXKY0c1_1-J,~>
+!h?&@nEp9SJcC<$mJd1KqsFU#hUUKNqu6fUUt+Utrr3,pe^`NinEpB5UmrmYrrS^d1&LA=;X4;S
+!.k0$s4mYOmK52>S12b`!h?&@YO2S5hUTm$mXbD.rs.uBc.1sq^#nhP"#6UA.=_~>
+!liB.nEp9VJcC<$mJd1KqsG93g<S.7pA4gcs8(HCdc.,"s7Ym/db;;%mK7aW`aR-l!liB.qsFGa
+lMpJVJcC<$h#I9>"*r&/@F"lS`l`S1mK^J[d`0`#pA0@?T`5>pp>XB;db;FLipc@<H-4-8J,~>
+!quZ5nE'^KJcC<$mJm%F"K^.mc0"os%.<!Gs4-i:mcML5c*[!&"3(<6Us8o@pA`,/joA<Es7?;B
+s+14*s81p\`W,Y-cMmt>s2D2("glh)^!5^<p4*,9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7T^tpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdrUpKQ`P'OH[(Y>cjo`U&p8!3~>
+!i2>HnEp9SJcC<$mJd1KqsG9-hUU.tP`(H7p:[j$p?o$4s8VNDc/,hsmK5J>UaaRg!i2>HqsFG^
+p\t3np&FXaJcC<$h#I9>"$)mI.F.qpUmsI6mJm7(mK']OrlkK3p<N^8!:g'k!<<'!q#:<op\t3n
+r;Q`srr;lrq#:<oli-qbr;Q`srr;lr^&J-,mf(H5hR'uQnEpB=S>7Ta~>
+!m8N2nEp9VJcC<$mJd1KqsG9+f$;^+ZEgWmo"M9lo'3("qY'4&b1a#fmK7mWb$iQp!m8N2qsFGa
+p\t3np&FXaJcC<$h#I9>"+A23@F"lSb/SkumJm7(mK^&Kb/2<`o(LE+qZ-0_!s&2o!;QBj!;H<i
+!;uZn!<2im!;QBj!:0I]!;uZn!<2im!5A:9p@@@g_TLH8]&)rE"+A23@=S~>
+!rqu=nE'^KJcC<$mJm%F$`qUl`SU%Vp>56"mf*7djp(PIhTa$iV"!LKc1_1-bl7_;c26W';YU1k
+!;6Ba!.k0$s4mYOjo`m%s.%@6!VXe,jo>CujoqR*`P&tArpBg\mf)n]me6)Jp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&XUTqZ$Warq6E]p?qqR!q,dMrq6Ttp?hqSp?qYBrq6E]
+!:Kj[!q,dMrq6Bnp?qqR!s&&_pA=pip&a[Umf)n]!;>j[p&a[Umf)n]me6)Jp($Name6>Sme6)B
+p&OOSmed%bmf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]
+me6)Jp&a[Umf)n\me6YJ#N!/-`Qb3ceaV]'c1_1-J,~>
+!h?&@nEp9SJcC<$mJd1KqsG8rhTaSK]r[`NK@U#%mdB4ik4\5fc./obmK52>S12__!h?&@qsFG^
+lMpkaq#C?opAY*mo)Aaks8W&unc/Rgqu?Zrqu6Wrli-qbj8T)ZjSo2[JcG?AqsFP@UmrmZrrS^d
+1%4N1!5e./XPV4@e`QT!r;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qups8N*!s7ZBj!;??j
+!;??j!VQNlrrDcjrrVoo!<2uupAFpkp&P'k#5/&srrE)mr;Qcjr;Q`sr;Qcjr;Qcjr;Qcjr;Q`s
+r;Qs$s8N*!s7ZBj!!)rs!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;?Els7Q][
+e]#eiXM*ccmK52>S1/s~>
+!liB.nEp9VJcC<$mJd1KqsG8od`0Rdmc)s'NRn.'k2tNWhX9OOb0m!QmK7aW`aR-l!liB.qsFGa
+lMpkaq#C?opAY*mo)Aaks8W&unc/Rgqu?Zrqu6Wrli-qbj8T)ZjSo2[JcG?AqsFQ3b/Rl8rrU3_
+H11/$!5e./V:*N#b22^[J+iI,o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MVSo(MYJo(MYJo(MYJo(MYJo(MYJnc87So(MYJo(MYJo(E(Wo(MYJo(MYJnc87So(MVS
+o(E(Wo(MYJo(MYJo(MYJ!;?!Wo(MYJnnRmhp@@qJp@@qJp@@qJp&OgWp@@nWp@84Sp@@qJp@@nW
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJo%qO'b0m,thXKq8H-4-8J,~>
+!quZ5nE'^KJcC<$mJm%F"J!`M`TI1"!qtLEr;R#PmcNBF`QaqBjo`U&p8#t5!quZ5qrRlVlMpka
+q#C?opAY*mo)Aaks8W&unc/Rgqu?Zrqu6Wrli-qbj8T)ZjSo2[JcG?AqrS""s7W86rrVoo`UDph
+!5dk*Us6lc`RXD=p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]
+p?hq[mK3+MpAXI]p?qYRmK3+MpAXI]!:KR[mK3+MpAXI]p&OgcmK3+MpAXI]!:KR[mK`g\p&OOK
+p?qYRmKiOSp?q>Kp?qYRmK3+MpAXI]p?qYRmLJsYp?q>Kp?qYBmJutK!<2Blp?qYBmJutKpAXI]
+p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmL8gWp?qA!
+`O*V/UpT"Jjo`U&p8!3~>
+!i2>HnEp9SJcC<$mJd1KqsFHSrm_Zcc)dG2pAb0\mcMcPPigNHc/+u[mK5J>UaaRg!i2>HqsFG^
+qu?H1q>^Hpq#C?opAY*moD]$qs8N'!s8N)irr<&ps8N)rrr<&brr<&Zrr<&[rrW9$rr@WMpAb$X
+"$)mI.F.qpUmsI6mJm7(mKf?>`Pp*ame6@(s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKdrrE)ms7ZKds7ZKds7ZKds7ZKds7ZHms7ZKds7ZKds7ZKd!;?Hds7ZKd
+s7ZHms7ZKdrrE)m!;?Hds7ZKds7ZKds7QHds7ZKds7ZKdC&do,pAajdpAajdpAagdpAajdp&Ogd
+!<;cmpAajdpAY-mpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdp@dq:c,IZYSA!eKmK5J>Ua^f~>
+!m8N2nEp9VJcC<$mJd1KqsG8cd`Tjls5q%qo)JRSlJg6WU#+5C`mU.AmK7mWb$iQp!m8N2qsFGa
+qu?H2q>^Hpq#C?opAY*moD]$qs8N'!s8N)irr<&ps8N)rrr<&brr<&Zrr<&[rrW9$rr@WMpAb$X
+"+A23@F"lSb/SkumJm7(mKSs)_S4%Hm`tA'!:97V!;5m_!;H$a!;uBi!:o[\o^Vt^lLFoTr:0pi
+o'ueUnc/[,nd+[?`kK=<Q+GiAmK7mWb$ff~>
+!rqu=nE'^KJcC<$mJm%F#aETQ`TI4#p>5]H#km-*ma]:ic&;)R"3pQ>SBV!6p<EKs!)i^opq?M'
+rrDiorrDcm!!)Wj#6=f(!!*'!!:p-i!;ZZp!;lcr!:0Xb!9=(Z!9F.^!<<'!JcGHDqrS"*pA^Z-
+rrMi<n)aTM_WD&ec+UKte`P0F!!)BR!!)][!!)c]!!)rb!s%cW!;,[Z!:&tP!;u6e!:K7Tq!J+^
+_X7]le\/?'c'5TcnE'htpA^Y5~>
+!h?&@nEp9SJcC<$mJd1KqsF]IhTaSSc()cMrs=$E@R4Hhc-=e'nEpB5UmrmYrrS^d1&LA=;Z$Io
+`VTT7`VKQ6!;QTo!;?Em!;$3m!<<'!rr;uuoD\djqYpTsrrDrr!!)?b!!)'Z!!)Ti!!)Zk!!*#u
+!!%TMp](-Y"#6UA.F.qpS>7n.mJm7amem.bmK!=UrW)rcr;clc!!*#d!W_ZVr;cfar;cibrW)rc
+!!)l`"dIQ^^!5EYp&G*hp&P0erW)rkr;clk"T\8i!;?-b!<2Zm!;?Blqt:!ir:U6np@\Idp@\Id
+rV$3jrq6?mpAP'ep&G*jp&kBhp&G*gpAY-<pA"^ep'9a)^!5)l^#nhP"#6UA.=_~>
+!liB.nEp9VJcC<$mJd1KqsF]Gd`0Rhs165KrsS\sQ#VXpJQ^.8cAh>]"*r&/@EnfR`l`T(mJp8a
+rrC(8rrC(7s8N)os8N)mrr<&jrrW9$rrE&urrDZj!!)lq!W`6#qu6Wrli-qbj8T)Zo)A[io`"mk
+rr2ruJcGKEqsFQ3b/Rl8rrU3_H11/$!;l3_!<2Be!:KgdrpK^bs6]jerpBgfmdC#RrU0UarpKac
+rpBadqX+TNd`/l<g?RtLmJm7`mK!=UrW)rcr;clc"T[uY!:K:R!<2Be!:KgdqsFFar9a[fmd:&T
+p?hn\rU0XbrpBdemf!4]mJm7bmK<OXmJm7_mf*:4meHk_mf2PWg;^_DdZM,tnEpC(b/Rk?~>
+!quZ5nE'^KJcC<$mJm%F#D::7`TI3gk55/]k2,OVhYkCnKCJ"*`W,Y-c2Rk=s2Flt!)i^o!587/
+!584.rrDiorrDcm!!)Wj!s&B$!<3#u!;$3j!;c]s!<3&rrr<&brr<&Zrr<&irr<&krr<&urr<%M
+s7cQjjo`U&p8$"6!quZ5n)aTMqr[hWroO4]k5GA[k5>;[jo>D\joPPFk5>;Yk5>;Zk5GA[jo>DX
+k!P'G]sPK'k2u*omcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+!9W_3mcNs"!9X7\!p8q5r;[)jjoFQ3!:K"J!!M`PmJu\S!$L^lmcNs"!9W_3mcFN3mJm7LmcNs"
+mcNs"mcFN3mcNs:!!M`PmJu\S!)W+GmcNs"mcNp;mcNs"mJu\;!!)HLmcNs"mcFKLmcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs5!"7rWk2t4-[(X_B[,1<7
+"3(<6Ujr~>
+!i2>HnEp9SJcC<$mJd1KqsG8Ye]l?:c'3:6P`(HP=ufbP8g#k=c/+*BmK5J>UaaRg!i2>HqsFG^
+qu6Z8rr2rurr2u;q>^Hpq#C?oq>^Bnrr;rtqYpNqrr2rurVlitqZ$Kos8W&uqu6]trrDrr!s&?$
+!<)rr!<)rr!<3!%!<<'!s8W#tqZ$KorVuisrr2rurr;rtrVu]os8W&urVufrrr;uuJcGNFqsFPH
+S>7UZrrT!d3UcA9!;Gmn!:K7T!:K7Tmd:&Tmd:)CmK!7S!!)oa%KPqb!!)HT!:K7Tmd:&Tp[/'7
+ec*MfhYuqVp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp&OgS
+p?qYBp&G*\p&OgS!!)`\!:KO\p?hqKp&OgSp?qYB!!)`\!:KRKp?qVSp?qYBp&OgSpAP%Bp?qYB
+p?qYBp&OgSp&OgS!!)`\!!)`\!:KRKp?qYBp?hqKp?qYB!:KRKrW#"Ip?qYBp?hqKp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?q_V!;?E[#Nj"=`SQ6\hXKq8
+3LlloJ,~>
+!m8N2nEp9VJcC<$mJd1KqsG8Sd`0F`s1XW$Y,\=lI;,+3R9`5+`mTG-mK7mWb$iQp!m8N2qsFGa
+qu6Z9rr2rurr2u<q>^Hpq#C?oq>^Bnrr;rtqYpNqrr2rurVlitqZ$Kos8W&uqu6]trrDrr!s&?$
+!<)rr!<)rr!<3!%!<<'!s8W#tqZ$KorVuisrr2rurr;rtrVu]os8W&urVufrrr;uuJcGNFqsFQ7
+`l_`8rrU?_IIHS(!;Gmn!:K7T!:K7Tmd:&Tmd:)CmK!7S!!)oa%KPqb!!)HT!:K7Tmd:&Tp[/6>
+d_`T4g?-]G!!)l\rrE)a&-2"\!!)<L!:&hLlKSB7l2^_HrrE)a!!)o]!!)r^!!*#`rW)`Y!!*#`
+$NTJW!!)<L!!)<L!;PgZ!;u*^!<29_!;bs\!7'm*!<26hk1[\`_U=.LhXKq8IE'E<J,~>
+!rqu=nE'^KJcC<$mJm%F#_UC@`TI3ok4\fB!p8@rrr3/i`PoO8Hgp/"c1_1-bl7_;c26W';Z$Io
+^&J$3!<2uu^%q^.!;QTo!;ZZn!<3#t!;c]q!<2uu!<)ot!;c`o!<<)u!;lct!<3&rrrW9$!!)ut
+r;cfrr;cis"T\T&!<<)t!;c`o!<)rs!<2uu!<3#t!<)ro!<<)u!<)rr!<3#u!.k1Fs81p\c1_1-
+c2Rh<c0scp!;GUf!9WDD!9WDDk2lXDk2l[+joGDC!!)oY%KPYR!!)0D!9WDDk2lXDpZ;g0c+UKt
+e_]HFk2-+"!oE(rroO:=k2-+"!oE(rroO:=k2-+"!oE(rroO:=k2-+"!oE(rroO:=joGDC)W'W5
+jo>D<joFQ+!!)0<!9WDDk2$+#joFQ#roOLC!!)0D!8ckproO7^k2-+"!s%K?k5G>]k2-+"']/!/
+joFQ#joFQ+!!)0<!!)0<!8d_;%c6@)k2l[#k2,7_!8ckprW!#Vk2-+"!o<q6roO:=k2-+"!oE(r
+roO:=k2-+"!oE(rroO:=k2-+"!oE(rroO:=k2-+""Q&:tk2uI>$g-=.hUT<H^!1o2eaV]'c1_1-
+J,~>
+!h?&@nEp9SJcC<$mJd1KqsG8IhSm`;eP]kXUm-LQC2,a`+960$c..11mK52>S12__!h?&@qsFG^
+qu6Z8rr2rurr2u;q>^Hpq#C?oqZ$Qqs8N<(s8N*!rr<&rrr<&urr<&trr<&rs8N*!s8N*!rr<&r
+rrW9$rrDrrrr=#<!!*'!!!*'!!!*'!!!*'!!!*'!!<3$!s8N)nrr<&rrt5>3rr<'!rrE*!!<<'!
+!<<'!!<)p-!<<'!s8N'!s8N'!s8N)trr<%Ms7lWkmK52>S12b`!h?&@n*U/Up[/+`md:)SmK3IW
+mK!7S!s%cW!<2Bd!;l0d!:K7TrpBjgmJm7dmJm7]mK\Bpc+VBYmcOH8!9X4I!9X4I!9X4I!9X4I
+!9X4I!9X4I!9X4I!p8q=qZ-Za#6<oSmJu\C!<2Bn!:JtLmd:)Cjo>D\mK2P=!<2Bd!;u6cjoGAJ
+!TjC\mJuDK!<;Hek5F]Y!9W\L!:K:;!:K7TmcNp;rpBdKr9aObr9aObr9jOarpBjMmK!7S!9X4I
+!9X4I!9X4I!9X4I!9X4I!9X4I!9X4I!9X4I!9X.YrpC*TmbZ4%c..H[k4%d@0r1<gJ,~>
+!liB.nEp9VJcC<$mJd1KqsG8Cd_a.\s,i;\`kJaTRAGUg=Vu/$`m/l!mK7aW`aR-l!liB.qsFGa
+qu6Z9rr2rurr2u<q>^Hpq#C?oqZ$Qqs8N<(s8N*!rr<&rrr<&urr<&trr<&rs8N*!s8N*!rr<&r
+rrW9$rrDrrrr=#<!!*'!!!*'!!!*'!!!*'!!!*'!!<3$!s8N)nrr<&rrt5>3rr<'!rrE*!!<<'!
+!<<'!!<)p-!<<'!s8N'!s8N'!s8N)trr<%Ms7lWkmK7aW`aR0m!liB.n*U/Up[/+`md:)SmK3IW
+mK!7S!s%cW!<2Bd!;l0d!:K7TrpBjgmJm7dmJm7]mQ#jH`k'1@io9+[k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_qZ&G7iW/!#iW/!#!9W;'!9W8@ioU7'iW&u@
+io]7_!9W;'!9W;'io]5#io]7_iW/!#io]8"!%['kio]7_iW/!#!!)$@iW/!#!9W;'!9W;'io]7_
+ioU7'io]7_!9W;'io^4?3Tf>`ioU7'io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7t!"A#Lk2PCO`k'1<J\'_-mK7aW`aOA~>
+!quZ5nE'^KJcC<$mJm%F#BS/'`TI3gk5PA^pAajcrs%o1`P&t(F7A;o`W,Y-c2Rk=s2Flt!)i^o
+!58C3!!*#u!584.rrDiorrDoqrrE*!#6=f(!<<'!!;lcr!<2uu!<)ot!;lfr!<<*!!<<'!!;lcu
+!<<'!qu?Zr)ufm<s8N'!s8N'!s8N'!s8N'!s8N*!!!*'!!;HKn!;ld/!<<'!!<<'!s8N*!rr<'!
+rr<&trsf&/rrE*!!!*'!!!*'!!<)ot!.k1Fs81p\`W,Y-cMmt>s2FHh!!)cU!s%KG!<2*_!9WDD
+roO:_k2l[Cjo>DYjoYVGjoGDC!s%H`!<2*\!;GU\Hd072^!5EaceeO!s5!_Urn[_WhVJ83h?j8>
+h>lEh!8cQ4!;t[R!<1gT!;kUQ!;t[R!;t^Q!;bOT!8cQ4!<1gW!8cQ4rn[VTptbuNr8%DRr8.DQ
+r8%DRc//<tr8%\']sPJlHaMZ!jo`U&p8!3~>
+!i2>HnEp9SJcC<$mJd1KqsG8Ae]l?2`Auf*hQ2?55p.!M(_Dq^c/*O2mK5J>UaaRg!i2>HqsFG^
+qu6]9s82j#s2G!<rrE#trrDiorrDoq!!*#u!s&?$!<2uu!;lcr!<2uu!<)ot!;lcr!<)p"!<<'!
+r;Q`srr2ruqu6Wrrr3'#s8N)trrW9$rrE#t"T\T&!<3&us8N)os8N)ts8N)urrrK'rrE'!!<3!#
+!<<'!r;Qj!rr<&urrW9$rrE&u!!)ut!!%TMq#C6Z"$)mI.F.qpUmsI6mJm7`mem.cmJm7dmK3IW
+mK!7S!s%cW!<2Bd!<2Eb!<;He!<2Be!:K^ap[/3+hSm1IhYuY3mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mJu\;mcNs"mJu\;mJu\;!9W_3!9W\LmcFN3mcOKK
+-KaaY!9W_3!9W_3mcNp;mcNs"mJu\;mcNs"mJm7LmcNs"mJu\;qZ'dejoFQ3joFQ3k3hC"k3h@3
+k3hC"joFQ3k3hC"jo>DLk3h@3k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k5>8amcNs"mcNC*`<4Y3^#&8H"$)mI.=_~>
+!m8N2nEp9VJcC<$mJd1KqsG8?d`0F\p2TN_s5(>TJRqM#+<6rp`mS_nmK7mWb$iQp!m8N2qsFGa
+qu6]:s82j#s2P'=rrE#trrDiorrDoq!!*#u!s&?$!<2uu!;lcr!<2uu!<)ot!;lcr!<)p"!<<'!
+r;Q`srr2ruqu6Wrrr3'#s8N)trrW9$rrE#t"T\T&!<3&us8N)os8N)ts8N)urrrK'rrE'!!<3!#
+!<<'!r;Qj!rr<&urrW9$rrE&u!!)ut!!%TMq#C6Z"+A23@F"lSb/SkumJm7`mem.cmJm7dmK3IW
+mK!7S!s%cW!<2Bd!<2Eb!<;He!<2Be!:K^ap[/6.d_`T4f&"^3!!)lT!!*#X!s%??!<1s^!92u<
+io0t;ir/rWiW&uXiW&uUiW&uViW&uTir9#UiW9,>iqi`UiW&uXiW&uRiW&uViW&uTir9#WiW&u&
+ir&lTiX"Dl_RdV4Fh6H!mK7mWb$ff~>
+!rqu=nE'^KJcC<$mJm%F!,DMP!oEt6qYplqk0:lY`PoO8C@L?fc1_1-bl7_;c26W';Z$Ip^&S!1
+"ol:9!<3&ts8N)os8N)qrr<&urrW9$!!*#u!!)or!!*#u!!)ut!!)or!!)ut!s&B$!;uis!<2uu
+!;lcr!<3!#!<<'!rVls"s8N)trriE&rrE'!rr;uuq#C?orVultrr30&s8N*!!!*#u!s&B$!;uj!
+!<3$!rr3'#s8N)urr<&trr<%Ms7lWkjo`m%s.%@6!VXe,jo>DXk5>;[jo>D\joYVGjoGDC!s%KG
+!<2*\!<2-Z!<;0]!<2*]!9X.YpZ>Lkc*Xjkc.1\$hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5h>lE_hUUK5h>lE_h>lE_!7frV!7fp+hUMVVhUVT*-Ipu'!7frV
+!7frVhUUH_hUUK5h>lE_hUUK5h>dQ+hUUK5h>lE_qZ'dUeH".VeH".Ve_\j5e_\gVe_\j5eH".V
+e_\j5eGoU+e_\gVe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5eboIWhUUK5hUTla['\(m[+4[."3pQ>S:C~>
+!h?&@nEp9SJcC<$mJd1KqsG80hSm`;K50PMP]KGO(^L*A(b*/Cc.-RumK52>S12__!h?&@qsFG^
+qu6Z8rr2rurr2u;q>^Hpq#C?oqYpNqrr3!!s8)fnrr<&urr<&trr<&rrr<&trrW9$rrDusqZ-Qo
+!!*#u!s&B$!<)p"!<<'!rVm!#s8N'!r;Z`rq>^Eos8Vrrs8N*"s8)frrr<&srrE-"qZ-Zr!!*#u
+!!)ut!!%TMq#C6Z"#6UA.F.qpS>7n.mJm7amJm7dmK3IWmK!7S!s%cW!<2Bg!:K7TrpBjgmd:)S
+mK3IWmK!7S!s%`h!;#U^F4JOKc/-_-!!)lX!!*#\!s%KG!<2*b!9WDDk2l[Ak5PG]jo>D\jo>DY
+jo>DZjo>DWjo>DYjob\Hjo>DYjo>D\jo>DVjo>DZjo>DWjo>D[jo>D)k5PGXjp0bf^!5)K^#nhP
+"#6UA.=_~>
+!liB.nEp9VJcC<$mJd1KqsG83d_a.\_NFlP`ib/8:bWk+,WNNX`mSGfmK7aW`aR-l!liB.qsFGa
+qu6Z9rr2rurr2u<q>^Hpq#C?oqYpNqrr3!!s8)fnrr<&urr<&trr<&rrr<&trrW9$rrDusqZ-Qo
+!!*#u!s&B$!<)p"!<<'!rVm!#s8N'!r;Z`rq>^Eos8Vrrs8N*"s8)frrr<&srrE-"qZ-Zr!!*#u
+!!)ut!!%TMq#C6Z"*r&/@F"lS`l`SqmJm7amJm7dmK3IWmK!7S!s%cW!<2Bg!:K7TrpBjgmd:)S
+mK3IWmK!7S!s%`h!;#V^D:6G8_UdT#ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\Oini\Oini\Oina[lini\Oina[lina[liW.upiW.up!8c]8ini\OiW&s+hVnOphVnOphW!DO
+h>lElhW!AlhW!DOhW!DO!92kphW!AlhVnM8Dr0L1iniYpiniYpini\Oini\OiW.upiniYpini\O
+ini\O!8c_liW.upini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\O
+ini\O!!)$8ini\OhU]QT`mS_8hXKq8H-4-8J,~>
+!quZ5nE'^KJcC<$mJm%F#%Gij`THm^qu7#kk0:la^!47(`FA?!"3(<6Us8o@pA`,/joA<VrrBb3
+rr<&urrBb.s8N)os8N)qrr<&urrE-"qZ-Nn!!*#u!!)ut!!)or!!)ut!s&B$!;ulo!;uis!<3!#
+!<<'!rVls"s8N)trr`?%rr<&ss8E#os8E#us8)frrrE-"qZ-Zr!!)rs!<E/s!<<'!!<2uu!<)ot
+!.k1Fs81p\`W,Y-cMmt>s2FHh!!)oY!!*#\!s%KG!<2*_!9WDDroO:_k2l[CjoYVGjoGDC!s%KG
+!<2*_!9O7]oB'4k`P&Xlc/."-e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5eH".Ve_\j5eH".VeH".V!8c8_!8c6+e_U;_e_\j5!!"Csh>lE_h>lE_hUUK5!7frV
+hUMVVhUUK5hUUH_hUUK5hUMVVh>dOoe_\j5e_U;_e_U;_e_\j5e_\j5!8c8_e_U;_e_\j5e_\gV
+e_\j5!8c8_e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\gV
+!8c8_e_\j5c+U3lc"aWBnE'hls7W7=~>
+!i2>HnEp9SJcC<$mJd1KqsFo&e]l?:>,8iaC0F4Y#lXf.#ZBO0c/)q!mK5J>UaaRg!i2>HqsFG^
+qu6Z8rr2rurr2u;q>^Hpq#C?oqYpNqrr3'#rr<&nrr<&urr<&us8N)rrr<&trrW9$rrDio!!)or
+!!*#u!s&B$!<)p"!<<'!rVm$$s8N*!!;lfr!;QTo!!<0#!;lcu!<3$!qu6Wrr;Qj!rr<&rrr<&u
+rr<&trr<%Ms7lWkmK5J>UaaUh!i2>Hn*U/UqsFFarpBjgmd:)SmL]HemJu\C!!)HT!:K7T!:K7T
+rpC*nmd:)CmJm7TmJukH!FjUY`W+e6k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,5#k2,7Wk2,5#k2,5#k2$*pjo>D<joFQ#!8ckpk2,5#k2$*pk2$*pk2,7W
+jo>D<k2$(<k2$*pk2,5#!.*MahWE\W!9W/#!9W/#hWEYphWEYphWE\WhWE\Wh>dQ<hW=e<hW=h#
+hWEYp!9W/#!!(m<hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhVQ5b`SP(;hXKq83LlloJ,~>
+!m8N2nEp9VJcC<$mJd1KqsG8/d`0F`Oi$P3V4E<O4=DHl'Ns#0`mS/^mK7mWb$iQp!m8N2qsFGa
+qu6Z9rr2rurr2u<q>^Hpq#C?oqYpNqrr3'#rr<&nrr<&urr<&us8N)rrr<&trrW9$rrDio!!)or
+!!*#u!s&B$!<)p"!<<'!rVm$$s8N*!!;lfr!;QTo!!<0#!;lcu!<3$!qu6Wrr;Qj!rr<&rrr<&u
+rr<&trr<%Ms7lWkmK7mWb$iTq!m8N2n*U/UqsFFarpBjgmd:)SmL]HemJu\C!!)HT!:K7T!:K7T
+rpC*nmd:)CmJm7TmJukH#%>rs]"ZbLrn_MGhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-fdhV-i?hV-fdhV-fdhV%t`h>dQ0h>lEd!8?;`hV-fdhV%t`hV%t`hV-i?
+h>dQ0hV%r0hV%t`hV-fd!,gNIg>:Q?!8cGd!8cGdg>:N`g>:N`g>:Q?g>:Q?g&M-0g>2f0g>2hd
+g>:N`!8cGd!!(a0g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?gA]q7g=F!L_U;l(hXKq8IE'E<J,~>
+!rqu=nE'^KJcC<$mJm%F#$T9j^#%oFr;R/umbZL=]tM\0^!0aMjo`m%s.%=5!VXe8joA<VrrBb3
+rr<&urrBb.s8N)os8N)qrr<&urrW9$!!)cn!!*#u!!*#urrDrr!!)ut!s&B$!;QQo!;lcr!<3!#
+!<<'!rVls"s8N)trriE&rrE'!qu?Zrq#C?o!ri6#qu6`urr<&rrr<&srrW9$!!)or!!*#u!!)ut
+!!%TMq#C6R"3pQ>SB_'7p<E'g!!)oY!!*#\!s%KG!<2*m!9WDDk2lXDk2l[+jo>DDjoGDC$395N
+!9WDD!9WDDoB$6\c+UKkc-?7<D9^VUe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXheH".Ee]lXheH".EeH".E!6s$o!6s$oe]e*=e]lXheH".E!6s'=!6s'=e]lVE!6s'=
+!!(Qo!6s'=eGoSec.1(hc.)gEc.)gEc.1(hblH#=blH#=c.1(hc.1&=!7f?E!!(9o!7f?Ebl@ao
+c.)doc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1)<ec3noZin(e>-uiLjo`m%s."T~>
+!h?&@nEp9SJcC<$mJd1KqsG7uhTa;*;SC>^S;V_t5s[Lk(j"QYc.-"emK52>S12__!h?&@qsFG^
+qu6Z8qYpQ7q>^Hpq#C?oqYpd#s8N'!s8N)nrr<&us8N*!rr<&qs8N*!s8N*!rr<&orr<&rru(n;
+rr<'!rr<'!rr<'!rr<'!rr<'!rrE*!!;lcr!;HKq!<<'!qu6`us8N)rs8N)trrW9$rrDrr"9AK%
+!!*#urr@WMq#C6Z"#6UA.F.qpS>7n.meZtameZtbmK!7S!!*#drr</h!:K:S!!DWhmdBrPs6fme
+!U]semem.cmJm7`mQ"b,c+VBYk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wq>_5d!8ckp!8ckp!!)-]k2$*pjoFQ#r;[>ihW=h#hW=h#hWE\WhWF_9!p8A%
+qZ%#\k2,7Wk2,5#k2,8!!"e#L!9W/#!9W/#hWE\WhWE\m!!;$>hYR:Hk2,7W!8ckpk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2+@rc.-::
+k4%d@0r1<gJ,~>
+!liB.nEp9VJcC<$mJd1KqsG8#d`0FDM;%CS_QokdBjk"4/:H6pb0j;ZmK7aW`aR-l!liB.qsFGa
+qu6Z9qYpQ8q>^Hpq#C?oqYpd#s8N'!s8N)nrr<&us8N*!rr<&qs8N*!s8N*!rr<&orr<&rru(n;
+rr<'!rr<'!rr<'!rr<'!rr<'!rrE*!!;lcr!;HKq!<<'!qu6`us8N)rs8N)trrW9$rrDrr"9AK%
+!!*#urr@WMq#C6Z"*r&/@F"lS`l`SqmeZtameZtbmK!7S!!*#drr</h!:K:S!!DWhmdBrPs6fme
+!U]semem.cmJm7`mQ"S$`k'%8g=kE;hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?q>_5`!8?;`!8?;`!!(jUhV%t`h>lEdr;[>ag>2hdg>2hdg>:Q?g>;`-!oDYf
+qZ%#XhV-i?hV-fdhV-ib!"dl@!8cGd!8cGdg>:Q?g>:Q]!!:m2gA:kDhV-i?!8?;`hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?g=!jL`mS/(
+hXKq8H-4-8J,~>
+!quZ5nE'^KJcC<$mJm%F"]EUY`STbTrs\Vhk2t4=]uAO8`Q_<Mjo`U&p8#t5!quZ5qrRlVqu6Z0
+qYpQ/q>^Hpq#C?oqYpd#s8N'!s8N)nrr<&us8N*!rr<&qs8N*!s8N*!rr<&orr<&rru(n;rr<'!
+rr<'!rr<'!rr<'!rr<'!rrE*!!;lcr!;HKq!<<'!qu6`us8N)rs8N)trrW9$rrDrr"9AK%!!*#u
+rr@WMq#C6R"3(<6UsAuApA`,#k5,,Yk5,,ZjoGDC!!*#\rr</`!9WGC!!D?`k2uO@s5s=]!TjC]
+k5>;[jo>DXjonr5]sPJtc.2Xj!S%2LeGoUKec,UUeH".M!7fU"e^aTurm^uKrm^uKqUPKDrmglG
+q:,HFrmgrIs4%)Lrm^uKpXT0ArmglGrRClJ_:8e8]sPJt>.!/Ujo`U&p8!3~>
+!i2>HnEp9SJcC<$mJd1KqsFVchUU-fF8c+JmcNBV`P&WEXPVLXhGWk2"$)mI.F%koUmsIBmJp/^
+s7jS/s7?<es8N'"rrE&ur;c]o!!*#urW)`nr;cis!!)fo!!)orr;cfrr;cfrr;cis"T\T&!!*&t
+!;c`o!<)rr!<<'!!<3#s!<3#s!!N<%!<<)t!<3#u!!3*"rr2ruJcGKEqsFPHS>7UZrrT!d3S3^!
+!:K:T!:]DN;Vo[;`STJ6hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\W!!#:@k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7W!8ckpk2,7Wk2,7Wk2,7Wq>adWk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+hSmIYhGV&DnEpB=S>7Ta~>
+!m8N2nEp9VJcC<$mJd1KqsFVaf$;E'RK!3rp?LYgd_`T$<MeEpb1]PYmK7mWb$iQp!m8N2qsFGa
+qu?H2q>^'eq>^Hp!WN0!s8;rorr<&us8E#ns8;rsrr<&orr<&rs8;rrs8;rrs8;rsrriE&rr<'!
+r;c]or;cfrr;clt!!*#ur;cisr;[!#!!*'!r;cisrr<*"!<2uu!.k1Es823dIE'E<cMmsg`dQJ,
+rrDKTrrDQV"]a-n^;A=1gA_0"g&M-DgA1g;g&M,gg'?3G^;e`(]&)rE"+A23@=S~>
+!rqu=nE'^KJcC<$mJm%F"\R%Y`QdiLs8VfmmK;V.e]%O4!l`\^nE'htpA^Z,rrMi<qrRlVqu?H)
+q>^'eq>^Hp!WN0!s8;rorr<&us8E#ns8;rsrr<&orr<&rs8;rrs8;rrs8;rsrriE&rr<'!r;c]o
+r;cfrr;clt!!*#ur;cisr;[!#!!*'!r;cisrr<*"!<2uu!.k1Es81p\c1_1-c2Rh<c.D+X!:K"L
+!:],F;U)n^^!4gPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(h!!#:/e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXh!6s'=e]lXhe]lXhe]lXhq>adFe]lXhe]lXhe]lXhe]lXhe]e*=e]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhc+UKt
+bu1q!nE'htpA^Y5~>
+!h?&@nEp9SJcC<$mJd1KqsFVRhUU-f[/Bq4mcN'=]sKNNk1/#=9(;6N0r1<gc2Rj8UbVc7!)i+^
+oDn(S!!%ZO!!%TMpAb$X"#6UA.F.qpS>7n/meQqSmem.Tmem.SmKHMFe]#e`roQH%k2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,8!!.Wkf
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Wh>lEphWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhW?-@k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2+A%e_X3;k4%d@0r1<gJ,~>
+!liB.nEp9VJcC<$mJd1KqsFVUg<Ru+`r5oHqWceW_Qp=0f%SEtejT#q"*r&/@EnfR`l`T(mJp8P
+s7?<Srr<%Orr<%Ms7ZKimK7aW`aR0m!liB.nF$,Qo'ZGVnF$5Tn*W_?f$;.Pdb`^7g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?r;_?$
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV%t`hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-g4g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:E#_Tp_+]&)rE"*r&/@=S~>
+!quZ5nE'^KJcC<$mJm%F"[UDP`Qe,Srs\Vhk2+Y=^"(ZPc-8QDjo`U&p8#t5!quZ5qrRlVlMpJV
+kPkM^KDtoOJcGHDqrS""s7W86rrVoo`UN$d!:o:N!:].L!:T%R9$P>g^!4:Ar;b-n!!&A9#L0rh
+`Q_#^hXKY0`W,Y-J,~>
+!i2>HnEp9SJcC<$mJd1KqsFVcc/-tV3W25Q3ADs3+<V5!mcNB_eOo?!"$)mI.F%koUmsIBmJp/Z
+rr<&Drr<%Ms+14Fs823d3LllocMmsAS2me@#smFuc,JPrk2,8"h>l^9h>l^9h>l^9h>l^9h>l^9
+h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9
+h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9
+h>l^9h>l^;h?i?$hTa<qhEej3nEpB=S>7Ta~>
+!m8N2nEp9VJcC<$mJd1KqsG7ob1>!#Bl.^$AR/G483f9k@H-.pf$6\QmK7mWb$iQp!m8N2qsFGa
+p\t3nc2RbDJcC<$q#C6Z"+A23@F"lSb/Sk5mKZ/2cGm`Lg>7D7T\9_/g=FEdcIt[thXKq8IE'E<
+J,~>
+!rqu=nE'^KJcC<$mJm%F(J;Zk`P'gPhUU0$c+Uft[&gste]l@X61F"=c1_1-bl7_;c26W';YU1k
+!6tND!.k0$s7lWkjo`m%s.%@6!VXdAjp",r`P&t0c%"9ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]hm[c.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(`]tMD86+#23jo`m%s."T~>
+!h?&@nEp9SJcC<$mJd1KqsG80[,0ZihVRDOk2,7Wk2,7Wk3hZohR$2MmK52>S12__!h?&@qsFG^
+JcC<$\GuHo"#6UA.F.qpS>7mCmKZq?hTaU$hVS1m!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9
+!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9
+!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9
+#N""]hT\s3k4%d@0r1<gJ,~>
+!liB.nEp9VJcC<$mJd1KqsG8/Y1D1Pg=kE;hV-i?hV-i?hWj7Wg9+9AmK7aW`aR-l!liB.qsFGa
+JcC<$\GuHo"*r&/@F"lS`l`S1mKZb7f#l.`g=h&5g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:OuhV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hVR8GcHb"`9Y0*MmK7aW`aOA~>
+!quZ5nE'^KJcC<$mJm%F!Eu;ublcM@e]n*D!mT9?rmh&*"3oAl;XifN`W,Y-c2Rk=s2Flt!)eCJ
+JcE7[qrS""s7W86rrVoo`NSD-;T6o"`Q`taS^e#&c-=5P`CdMonE'hls7W7=~>
+!i2>HnEtkiJ`c:\qsFZH;UsXdhX:C*!q,4=roOIRk5Y/CeP]lGmK5J>UaaRg!i2>HqsFG^p\t3n
+JcC<$_uKW%"$)mI.F.qpUmsHKmK[g7hVQf5hVS1m!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d\:!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d\:!8d_;!8d_;!8d_;!8d_;
+!8d_;!8d_;"Q&;'mcON*"0>tFk4%d@3LlloJ,~>
+!m8N2nEtkiJ`c:\qsG8S9[;5Cf&GQGhW!DOhW!DOhX^*odSOBAmK7mWb$iQp!m8N2qsFGap\t3n
+JcC<$_uKW%"+A23@F"lSb/Sk5mK[a3g="9lf%U,[@+sJkhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hVN\7hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-iCg>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:QCiX"]'f$`9T?+Sn^mK7mWb$ff~>
+!rqu=J`_OGeE.R"9#]'*c/."-e_\j5e_\j5eaDSVbu.a7jo`m%s.%=5!VXe8joA<Rrr<%Ms+13f
+s81p\c1_1-c2Rh<c*-77F/7@2`Pp*HJ^pIErn[n1c-=e7>.!/Ujo`m%s."T~>
+!h?&@JaS*We*[<Z6*/?'h?E?(Zq=6inEpB5UmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@
+YO2J*;U,3t!nH/aJ``Zg$1@NTk2t2lMoFQBmK52>S1/s~>
+!liB.JaS*We*[uk7&A&[f%S^/f%S^/f%S^/lIrC3<V#YI"*r&/@EnfR`l`T(mJp7<s+13[s823d
+H-4-8cMmscb'C2Y#eE^Pf%/9tf%P]3U#$+8mcNB_c:ir+hXKq8H-4-8J,~>
+!quZ5J`_OGe)hEe6);KMc.1(hc.1(hc.1(hk1-7n;XX&:"3(<6Us8o@pA`,/joA;1s+13[s81p\
+`W,Y-cMmt>s2D2(!jkS=rlkM`c-:giU"'J+k2+Y=`CbcreaV]'`W,Y-J,~>
+!i2>HJaS*WeF*A1'oP[E.5<8+.5<8+.5<8+.5<PC@eTNbmK5J>UaaRg!i2>HqsFG^p\t3nJcC<$
+_uKW%"$)mI.F.qpUmsHKmKWBC9!$S"k5O4Gk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2q*Kk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7_hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\Wjp1>:hR#mi[*A(-"$)mI.=_~>
+!m8N2JaS*WeF"+CmY+1g-nHbt-nHbt-nHbt-nI&;@IimT"+A23@EnfRb/Sl,mJp8]rr<%Ms+13f
+s823dIE'E<cMmsg`dP&Y#P*jBV9[ZGeq)PKg&U"/iWdu:885BPk4%d@IE'E<J,~>
+!rqu=J`_OGeE6f!!eX*"o-jes6!E^EnE'htpA^Z,rrMi<qrRlVp\t3nJcC<$_uKVr"3pQ>SB_'7
+p<Bf'C[R*QUrCU/c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(heUPioc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1@he]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXp
+hVJF\Ue5*t`UDpkc1_1-J,~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;X4;S!.k0$s4mYOmK52>S12b`!h?&@Y3lMf]kT8N.5C`L
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=F$!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=F$!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%s"OXSK=&>Kn*U94Umrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<U0VV!.k0$s4mYOmK7aW`aR0m!liB.Y3p&q[Uh9H-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n&IS-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbp,qLGq-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt1f]78^=qlAmK7aW
+`aOA~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;X4;S!.k0$s4mYOjo`U&p8$"6!quZ5Y3#iSZskb@.@M[h
+0iEY*^")T6"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;YU1k!;6Ba!.k0$s4mYOmK5J>UaaUh!i2>HYO;D`"7G<r
+`IY^k]`c=!k3hs4mK5J>Ua^f~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<VQLn!;6Ba!.k0$s4mYOmK7mWb$iTq!m8N2YO2VcmdfZ"
+b//_@R^rX=b22FSnEpC,`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVp\t3np&FXaJcC<$h#I96"3pQ>SB_'7p<Bf'rpFI^hSm18
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd@'mVS]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]tG`!]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]uAjjmdT?@
+c1_1-J,~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;X4;^!;QTo!9X:_!<<)u!:g*g!;lfr!;lcr!:0Xb!9=(Z
+!9F.[!.k1As823d0r1<gcMms9UbT%?CA.)hmdArohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\O@-6>.hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVKO?hWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhX9h*n*U94Umrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<U0Va!;QTo!9X:_!<<)u!:g*g!;lfr!;lcr!:0Xb!9=(Z
+!9F.[!.k1As823dH-4-8cMmscb'C/X"S2!KlK3ZSR,.l+lL+'BH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;X4;^!;QTo!9X:_!<<)u!:g*g!;lfr!;lcr!:0Xb!9=(Z
+!9F.[!.k1As81p\`W,Y-cMmt>s2D/'C@:6Pk2t4Ne_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j,@,BGje_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^Yr%e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e`Q#^n)a_ks7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;Z$Lh`VKQ6!;QTo!9a@e!<<'!!<<'!o)A[iq>^Hpqu6Wr
+li-qbj8T)ZjSo;^s8N(Ms7ZKimK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<Vugk`qfZ7!;QTo!9a@e!<<'!!<<'!o)A[iq>^Hpqu6Wr
+li-qbj8T)ZjSo;^s8N(Ms7ZKimK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVqu?H)q>^Hpq#C?okPkbes8N'!s8N)irr<&ps8N)rrr<&b
+rr<&Zrr<&[rrW9$rr@WMpAb$P"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;Z$Io`VTT7`VKQ6!;QTo!9a@a!<<'!rr;uuoD\djqYpTs
+rrDrr!!)?b!!)'Z!!)Ti!!)Zk!!*#u!!%TMp](-Y"#6UA.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<Vudr`qo]8`qfZ7!;QTo!9a@a!<<'!rr;uuoD\djqYpTs
+rrDrr!!)?b!!)'Z!!)Ti!!)Zk!!*#u!!%TMp](-Y"*r&/@F"lS`l`RXmXaf,mK7aW`aOA~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;Z$Io^&%a/^%q^.!;QTo!9a@a!<<'!rr;uuoD\djqYpTs
+rrDrr!!)?b!!)'Z!!)Ti!!)Zk!!*#u!!%TMp](-Q"3(<6UsAuApA`*_k(2Zqjo`U&p8!3~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;Z$Io`W#l;!<2uu`VKQ6!;QTo!;ZZo!<3!!!<<#uqu6Wr
+rr2rurVlitqZ$Kos8W&uqu6]trrDrr!s&?$!<)rr!<)rr!<3!%!<<'!s8W#tqZ$KorVuisrr2ru
+rr;rtrVu]os8W&urVufrrr;uuJcGNFqsFPHS>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<Vudr`r>u<!<2uu`qfZ7!;QTo!;ZZo!<3!!!<<#uqu6Wr
+rr2rurVlitqZ$Kos8W&uqu6]trrDrr!s&?$!<)rr!<)rr!<3!%!<<'!s8W#tqZ$KorVuisrr2ru
+rr;rtrVu]os8W&urVufrrr;uuJcGNFqsFQ7`l_`8rrU?_I=^g;m]5aXIE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVqu6Z0rr2rurr2u3q>^Hpq#C?oq>^Eorr3!!s8E#qrr<&u
+rr<&trr<&qs8;rts8E#qrrN3#!;lcu!<3$!rVufrrVufrrr3-%s8N*!s8;ros8;rrs8E#trr<&u
+s8E#ss7u`qs8E#ss8;rss8N(Ms7lWkjo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;Z$Io`W#l;!<2uu`VKQ6!;QTo!;c^'!<<'!!<<'!!<<'!
+qu6Wrrr2rurVlitqu?Zrs8W*!s8N'!qu6`us8N)rs8N'<rr<'!rr<'!rr<'!rr<'!rr<'!rrE'!
+!<<'!p\t3nqu79/s8N'!s8N*!rrE*!!!*'!!!)ut%KQP/!<<'!!<<'!!<<'!rVlitJcGNFqsFP@
+UmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<Vudr`r>u<!<2uu`qfZ7!;QTo!;c^'!<<'!!<<'!!<<'!
+qu6Wrrr2rurVlitqu?Zrs8W*!s8N'!qu6`us8N)rs8N'<rr<'!rr<'!rr<'!rr<'!rr<'!rrE'!
+!<<'!p\t3nqu79/s8N'!s8N*!rrE*!!!*'!!!)ut%KQP/!<<'!!<<'!!<<'!rVlitJcGNFqsFQ3
+b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;Z$Io^&J$3!<2uu^%q^.!;QTo!;c^'!<<'!!<<'!!<<'!
+qu6Wrrr2rurVlitqu?Zrs8W*!s8N'!qu6`us8N)rs8N'<rr<'!rr<'!rr<'!rr<'!rr<'!rrE'!
+!<<'!p\t3nqu79/s8N'!s8N*!rrE*!!!*'!!!)ut%KQP/!<<'!!<<'!!<<'!rVlitJcGNFqrS""
+s7W86rrVoo`I[0&k,[VH`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;Z$Ip`W,i9"olRA!<3&ts8N)os8N)rs8N)urrW9$rrE&u
+!!)or!!*#u!!)ut!!)or!!)ut!s&B$!;uis!<2uu!;lcr!<3!#!<<'!rVls"s8N)trriE&rrE'!
+rr;uuq#C?orVultrr30&s8N*!!!*#u!s&B$!;uj!!<3$!rr3'#s8N)urr<&trr<%Ms7lWkmK5J>
+UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<Vuds`rGr:"olUB!<3&ts8N)os8N)rs8N)urrW9$rrE&u
+!!)or!!*#u!!)ut!!)or!!)ut!s&B$!;uis!<2uu!;lcr!<3!#!<<'!rVls"s8N)trriE&rrE'!
+rr;uuq#C?orVultrr30&s8N*!!!*#u!s&B$!;uj!!<3$!rr3'#s8N)urr<&trr<%Ms7lWkmK7mW
+b$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVqu6]1s82j#s1SF4rrE#trrDiorrDrrrrE&u!s&B$!<2uu
+!;lcr!<2uu!<)ot!;lcr!<)p"!<<'!r;Q`srr2ruqu6Wrrr3'#s8N)trrW9$rrE#t"T\T&!<3&u
+s8N)os8N)ts8N)urrrK'rrE'!!<3!#!<<'!r;Qj!rr<&urrW9$rrE&u!!)ut!!%TMq#C6R"3pQ>
+SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;Z$Io`W#l;!<2uu`VKQ6!;QTo!;lfn!<<'!!<2uu!;lcr
+!<2uu!<)ot!;lcr!<)p"!<<'!r;ZWor;Q`srr3'#s8N)trrW9$rrE#t"9AK%!!)rsrW)corW)uu
+qZ-Zr!<E/s!<<'!!;uit!<;ors8N'!rr2rurVlitJcGNFqsFP@UmrmZrrS^d0nJbDm]5aX0r1<g
+J,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<Vudr`r>u<!<2uu`qfZ7!;QTo!;lfn!<<'!!<2uu!;lcr
+!<2uu!<)ot!;lcr!<)p"!<<'!r;ZWor;Q`srr3'#s8N)trrW9$rrE#t"9AK%!!)rsrW)corW)uu
+qZ-Zr!<E/s!<<'!!;uit!<;ors8N'!rr2rurVlitJcGNFqsFQ3b/Rl8rrU3_H%GC7m]5aXH-4-8
+J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;Z$Io^&J$3!<2uu^%q^.!;QTo!;lfn!<<'!!<2uu!;lcr
+!<2uu!<)ot!;lcr!<)p"!<<'!r;ZWor;Q`srr3'#s8N)trrW9$rrE#t"9AK%!!)rsrW)corW)uu
+qZ-Zr!<E/s!<<'!!;uit!<;ors8N'!rr2rurVlitJcGNFqrS""s7W86rrVoo`I[0&k,[VH`W,Y-
+J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;Z$Io`W#l;!<2uu`VKQ6!;QTo!;lfr!;lcr!<2uu!;lcr
+!<2uu!<3#u!;lcr!<)p"!<<'!q#:<oqu6Wrrr3'#s8N)trrW9$rrE#t"T\T&!<3&rs8N)os8N'#
+rr<&rrrW9$!!)or!!)rs!s&?$!;lcr!<2uu!<)ot!.k1Fs823d3LllocMmsAS2l/gJaTT,"$)mI
+.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<Vudr`r>u<!<2uu`qfZ7!;QTo!;lfr!;lcr!<2uu!;lcr
+!<2uu!<3#u!;lcr!<)p"!<<'!q#:<oqu6Wrrr3'#s8N)trrW9$rrE#t"T\T&!<3&rs8N)os8N'#
+rr<&rrrW9$!!)or!!)rs!s&?$!;lcr!<2uu!<)ot!.k1Fs823dIE'E<cMmsg`dNF+JaTT,"+A23
+@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVqu6Z0rr2rurr2u3q>^Hpq#C?oqu?Zrqu6Wrrr2ruqu6Wr
+rr2rurr;uuqu6WrrVls"s8N)orr<&rrr<&urrW9$rrE#t!s&B$!<)p$!<<'!rrDrrrrDiorr<-#
+!!)or!s&?$!;lcr!;uj!!<3$!qu6Wrrr2rurVlitJcGNFqrS"*pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;Z$Io`VTT7`VKQ6!;QTo!;c]q!;lcr!<2uu!;lcr!<3#u
+!<<'!!;c`q!<<*!!<<'!!;QQo!;ld7!<<'!!<<'!!<<'!!<<'!!<<'!!<<'!s8N)rrr<&nrrW9$
+rrDrr!s&B$!;lfr!<)p"!<<'!qu6d!s8N'!rr;uuJcGNFqsFP@UmrmZrrS^d0nJbDm]5aX0r1<g
+J,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<Vudr`qo]8`qfZ7!;QTo!;c]q!;lcr!<2uu!;lcr!<3#u
+!<<'!!;c`q!<<*!!<<'!!;QQo!;ld7!<<'!!<<'!!<<'!!<<'!!<<'!!<<'!s8N)rrr<&nrrW9$
+rrDrr!s&B$!;lfr!<)p"!<<'!qu6d!s8N'!rr;uuJcGNFqsFQ3b/Rl8rrU3_H%GC7m]5aXH-4-8
+J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;Z$Io^&%a/^%q^.!;QTo!;c]q!;lcr!<2uu!;lcr!<3#u
+!<<'!!;c`q!<<*!!<<'!!;QQo!;ld7!<<'!!<<'!!<<'!!<<'!!<<'!!<<'!s8N)rrr<&nrrW9$
+rrDrr!s&B$!;lfr!<)p"!<<'!qu6d!s8N'!rr;uuJcGNFqrS""s7W86rrVoo`I[0&k,[VH`W,Y-
+J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;Z$Lh`VKQ+!;ZZn!<<'!!<2uu!;c]q!<3#t!;QTm!<2uu
+!;QQo!;lfp!<)rr!<)rr!<3!%!<<'!!<;utqZ$KorVufrs8N'!rr;osrr;os"TJH%s8W#trr;uu
+!WN0!rr<%Ms7cQjmK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<Vugk`qfZ,!;ZZn!<<'!!<2uu!;c]q!<3#t!;QTm!<2uu
+!;QQo!;lfp!<)rr!<)rr!<3!%!<<'!!<;utqZ$KorVufrs8N'!rr;osrr;os"TJH%s8W#trr;uu
+!WN0!rr<%Ms7cQjmK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVqu?H)q>^'eq>^Bns8N'!rr2ruqYpNqrr;rtq#C9mrr2ru
+q#:<oqu?TprVufrrVufrrr3-%s8N'!s8;ros8;rrs8;rtrr<&us8;rss8;p#rr<'!s8;rss8N'"
+rrE&u!!%TMp](-Q"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;X4;S!9a@^!/(:O!.k1Ds823d0r1<gcMms9UbRGgJaTT,
+"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<U0VV!9a@^!/(:O!.k1Ds823dH-4-8cMmscb'AR+JaTT,
+"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;X4;S!9a@^!/(:O!.k1Ds81p\`W,Y-cMmt>s2BQOJ`a#q
+"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;YU1k!6tND!.k0$s7lWkmK5J>UaaUh!i2>HJaS*WX6p'M
+S>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<VQLn!6tND!.k0$s7lWkmK7mWb$iTq!m8N2JaS*WX6p(<
+`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVp\t3nc2RbDJcC<$q#C6R"3pQ>SB_'7p<A0NJ`a#q"3pQ>
+S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;YU1k!.k0$s24m6mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<VQLn!.k0$s24m6mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVp\t3nJcC<$_uKVr"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;YU1k!.k0$s24m6mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<VQLn!.k0$s24m6mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVp\t3nJcC<$_uKVr"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@mI'iOs6]jeZ0h\omd:(+m[W\I0r1<gc2Rj8UbVc7!)i+^oDjIBJcFO*qsFP@UmrmZrrS^d
+0nJbDm]5aX0r1<gJ,~>
+!liB.mI'iOs6]jeZ0h\omd:(+m[W\IH-4-8c2Rjbb'EmP!*/=aoDjIBJcFO*qsFQ3b/Rl8rrU3_
+H%GC7m]5aXH-4-8J,~>
+!quZ5mH49Gs5j:]Z/u,gk2lYpk+(Q9`W,Y-c2Rk=s2Flt!)i+^oDjIBJcFO*qrS""s7W86rrVoo
+`I[0&k,[VH`W,Y-J,~>
+!i2>HmdC)TrU'afmd:([mJm6<m[<JF3Llloc2Rj@S2pK7!)iRk!!)]loDjIBJcFO*qsFPHS>7UZ
+rrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2mdC)TrU'afmd:([mJm6<m[<JFIE'E<c2Rjf`dRaP!*/dn!!)]loDjIBJcFO*qsFQ7`l_`8
+rrU?_I=^g;m]5aXIE'E<J,~>
+!rqu=mcONLrT41^k2lZKjo>C4k*b?6c1_1-bl7_;c26W';YU1k!;6Ba!.k0$s4mYOjo`m%s.%@6
+!VXchk(2Zqjo`m%s."T~>
+!h?&@n*^2Uq<e4_j6cmId-^l6JaSro"#6UA.F%koS>7n:mJp/Ms8N)os8N)^rrN3#s8E#gs8E#q
+s8N)rrr<&brr<&Zrr<&[rr<%Ms763emK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.n*^2Uq<e4_j6cmId-^l6JaSro"*r&/@EnfR`l`T(mJp8Ps8N)os8N)^rrN3#s8E#gs8E#q
+s8N)rrr<&brr<&Zrr<&[rr<%Ms763emK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5n)jWMq;qYWj5p=Ad,k<.J``B_"3(<6Us8o@pA`,/joA<Es8N)os8N)^rrN3#s8E#gs8E#q
+s8N)rrr<&brr<&Zrr<&[rr<%Ms763ejo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>Hn*U/Uq!J._mf!4dmem.bmK3IW!:KdcrU0L^s6fjdrpBgfmK!.PrW)rc!<DQe!<2Eb!<;Kc
+!<)?a!<;Hi!:K7Tmf!4cmem.cmJm6<m]GmZ3Llloc2Rj@S2pK7!)i^opr3(/rrDiorrD9_#6=f(
+!!*'!!:p-i!;ZZp!;lcr!:0Xb!9=(Z!9F.^!<<'!JcGECqsFPHS>7UZrrT!d3J$ULm]5aX3Lllo
+J,~>
+!m8N2n*U/Uq!J._mf!4dmem.bmK3IW!:KdcrU0L^s6fjdrpBgfmK!.PrW)rc!<DQe!<2Eb!<;Kc
+!<)?a!<;Hi!:K7Tmf!4cmem.cmJm6<m]GmZIE'E<c2Rjf`dRaP!*/prpr<.0rrDiorrD9_#6=f(
+!!*'!!:p-i!;ZZp!;lcr!:0Xb!9=(Z!9F.^!<<'!JcGECqsFQ7`l_`8rrU?_I=^g;m]5aXIE'E<
+J,~>
+!rqu=n)aTMpuVSWk5GA\k5>;ZjoYVG!9X4[rT<qVs5s:\roO7^joG;@rW)r[!<D9]!<2-Z!<;3[
+!<)'Y!<;0a!9WDDk5GA[k5>;[jo>C4k,mbJc1_1-bl7_;c26W';Z$Lh^%q^.!;QTo!9jFf!<<'!
+!<<'!o)A[iq>^Hpqu6Wrli-qbj8T)ZjSo;^s8N(Ms7QEhjo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@n*U/Uq!S.^s6]jeqsFRemd:&TqsFRemd:&TrU($nmd:)CmJm7TmJm7amLK<cmJm7TmJm7T
+mJu\C!!)ucrrE)errE)errE)e&HM7e!:K7T!:K7Tmd:&Tmd:(+m],[W0r1<gc2Rj8UbVc7!)i^o
+!6+g7!6+d6rrDiorrD9_!s&B$!<3#u!;$3j!;c]s!<3&rrr<&brr<&Zrr<&irr<&krr<&urr<%M
+s7ZKimK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.n*U/Uq!S.^s6]jeqsFRemd:&TqsFRemd:&TrU($nmd:)CmJm7TmJm7amLK<cmJm7TmJm7T
+mJu\C!!)ucrrE)errE)errE)e&HM7e!:K7T!:K7Tmd:&Tmd:(+m],[WH-4-8c2Rjbb'EmP!*/pr
+!64m8!64j7rrDiorrD9_!s&B$!<3#u!;$3j!;c]s!<3&rrr<&brr<&Zrr<&irr<&krr<&urr<%M
+s7ZKimK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5n)aTMpu_SVs5j:]qrS"]k2lXDqrS"]k2lXDrT4Ifk2l[+jo>DDjo>DYjpqISjo>DDjo>DD
+joFQ+!!)u[rrE)]rrE)]rrE)]&HLtU!9WDD!9WDDk2lXDk2lYpk,RPG`W,Y-c2Rk=s2Flt!)i^o
+!587/!584.rrDiorrD9_!s&B$!<3#u!;$3j!;c]s!<3&rrr<&brr<&Zrr<&irr<&krr<&urr<%M
+s7ZKijo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>Hn*U/Uq!J+^rpBadqsFOdmd:)OmK3IWmK!1Q!s%`h!<2Bg!:K7TqsOIarpBjgmd:)SmK3IW
+mK!1Q!!)uc!s%cW!<2Bj!:K7Tmd:)SmK3IWmK!7S!!%T<WpTsLS>7UYrrT!d3W&4E;Z$Io`W#l;
+!<2uu`VKQ6!;QTo!;c`o!<<*!!<2uu!;uis!<2uu!<)ot!;c`o!<<)u!;lct!<3&rrrW9$!!)ut
+r;cfrr;cis"T\T&!<<)t!;c`o!<)rs!<2uu!<3#t!<)ro!<<)u!<)rr!<3#u!.k1Es823d3Lllo
+cMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2n*U/Uq!J+^rpBadqsFOdmd:)OmK3IWmK!1Q!s%`h!<2Bg!:K7TqsOIarpBjgmd:)SmK3IW
+mK!1Q!!)uc!s%cW!<2Bj!:K7Tmd:)SmK3IWmK!7S!!%T<WpTt;`l_`7rrU?_IJ`F4<Vudr`r>u<
+!<2uu`qfZ7!;QTo!;c`o!<<*!!<2uu!;uis!<2uu!<)ot!;c`o!<<)u!;lct!<3&rrrW9$!!)ut
+r;cfrr;cis"T\T&!<<)t!;c`o!<)rs!<2uu!<3#t!<)ro!<<)u!<)rr!<3#u!.k1Es823dIE'E<
+cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=n)aTMpuVPVroO1\qrRt\k2l[?joYVGjoG>A!s%H`!<2*_!9WDDqr[nYroO:_k2l[CjoYVG
+joG>A!!)u[!s%KG!<2*b!9WDDk2l[CjoYVGjoGDC!!%T4WoaE.pA^Z,rrMi<qrRlVqu6Z0rr2ru
+rr2u3q>^Hpq#C?oqZ$Kos8W*!rr2rur;Q`srr2rurVlitqZ$Kos8W&uqu6]trrDrr!s&?$!<)rr
+!<)rr!<3!%!<<'!s8W#tqZ$KorVuisrr2rurr;rtrVu]os8W&urVufrrr;uuJcGKEqrS"*pA^Z-
+rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@n*U/Uq!J+^rpBadrpK^bs6]jerU0Uas6]jer9aRcme["amJm7ame["amJm7dmK3IWmK!1Q
+!!)uc!s%cW!<2Bj!:K7Tmd:)SmK3IWmK!7S!!%T<WpTsDUmrmYrrS^d1&LA=;Z$Io`W#l;!<2uu
+`VKQ6!;QTo!;c]q!;lcr!<2uu!;uis!<2uu!<)ot!;lfr!<<*!!<<'!!;lcu!<<'!qu?Zr)ufm<
+s8N'!s8N'!s8N'!s8N'!s8N*!!!*'!!;HKn!;ld/!<<'!!<<'!s8N*!rr<'!rr<&trsf&/rrE*!
+!!*'!!!*'!!<)ot!.k1Es823d0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.n*U/Uq!J+^rpBadrpK^bs6]jerU0Uas6]jer9aRcme["amJm7ame["amJm7dmK3IWmK!1Q
+!!)uc!s%cW!<2Bj!:K7Tmd:)SmK3IWmK!7S!!%T<WpTt7b/Rl7rrU3_H2I"0<Vudr`r>u<!<2uu
+`qfZ7!;QTo!;c]q!;lcr!<2uu!;uis!<2uu!<)ot!;lfr!<<*!!<<'!!;lcu!<<'!qu?Zr)ufm<
+s8N'!s8N'!s8N'!s8N'!s8N*!!!*'!!;HKn!;ld/!<<'!!<<'!s8N*!rr<'!rr<&trsf&/rrE*!
+!!*'!!!*'!!<)ot!.k1Es823dH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5n)aTMpuVPVroO1\roX.Zs5j:]rT=%Ys5j:]r8n"[k5,/Yjo>DYk5,/Yjo>D\joYVGjoG>A
+!!)u[!s%KG!<2*b!9WDDk2l[CjoYVGjoGDC!!%T4WoaE&s7W85rrVoo`V\ct;Z$Io^&J$3!<2uu
+^%q^.!;QTo!;c]q!;lcr!<2uu!;uis!<2uu!<)ot!;lfr!<<*!!<<'!!;lcu!<<'!qu?Zr)ufm<
+s8N'!s8N'!s8N'!s8N'!s8N*!!!*'!!;HKn!;ld/!<<'!!<<'!s8N*!rr<'!rr<&trsf&/rrE*!
+!!*'!!!*'!!<)ot!.k1Es81p\`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>Hn*^2Uq<e4_rpBjgmd:)SmK3IWmK!7S!!*#d!s%cW!;u6e!:BgeqsFFaqsOIaqsFFarpBjg
+md:)QmJm7cmK3IWmK!7S"p")Z!:K7TrpBjgmd:)SmJm6<m],[W3Llloc2Rj@S2pK7!)i^o!QG*:
+!!WDArrE'!rVultq#C?oqZ$Qqr;Qj!s8N)rrr<&urr<&trr<&rrr<&trrW9$rrDus!!*#u!!)or
+!!*#u!s&B$!<)p"!<<'!rVm$$s8N*!!<3#u!;QTo!<)rt!<3!&!<<'!rr<&urrW9$rrDus!s&?$
+!<3!#!<<'!rr2rurVlitJcGKEqsFPHS>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2n*^2Uq<e4_rpBjgmd:)SmK3IWmK!7S!!*#d!s%cW!;u6e!:BgeqsFFaqsOIaqsFFarpBjg
+md:)QmJm7cmK3IWmK!7S"p")Z!:K7TrpBjgmd:)SmJm6<m],[WIE'E<c2Rjf`dRaP!*/pr!QP0;
+!!WDBrrE'!rVultq#C?oqZ$Qqr;Qj!s8N)rrr<&urr<&trr<&rrr<&trrW9$rrDus!!*#u!!)or
+!!*#u!s&B$!<)p"!<<'!rVm$$s8N*!!<3#u!;QTo!<)rt!<3!&!<<'!rr<&urrW9$rrDus!s&?$
+!<3!#!<<'!rr2rurVlitJcGKEqsFQ7`l_`8rrU?_I=^g;m]5aXIE'E<J,~>
+!rqu=n)jWMq;qYWroO:_k2l[CjoYVGjoGDC!!*#\!s%KG!;ts]!9O7]qrRkYqr[nYqrRkYroO:_
+k2l[Ajo>D[joYVGjoGDC"p!fJ!9WDDroO:_k2l[Cjo>C4k,RPGc1_1-bl7_;c26W';Z$Ip^&S!1
+"ol:9!<3&ts8N)os8N)qs8N)srrW9$rrDrr!!*#u!!)ut!!)or!!)ut!s&B$!;uis!<2uu!;lcr
+!<3!#!<<'!rVls"s8N)trriE&rrE'!rr;uuq#C?orVultrr30&s8N*!!!*#u!s&B$!;uj!!<3$!
+rr3'#s8N)urr<&trr<%Ms7cQjjo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@mdC)TrU'afmd:)SmK3IWmK!7S!s%cW!<2Bd!<2Bh!:K7T!<)<f!:K7TqsFFaqX+=`qsFFa
+rpBmhmd:&TrU0[cs6fmes6^3omd:&Tmd:)CmK!7S#6=2[!:K7T!.jR<mK52>S12__!h?&@qsFG^
+qu6Z8rr2rurr2u;q>^Hpq#C?oq>^Eorr;uu!WN/srr<&urr<&trr<&rrr<&trrW9$rrDusqZ-Qo
+!!*#u!s&B$!<)p"!<<'!rVm!#s8N'!r;Z`rq>^Eos8Vrrs8N*"s8)frrr<&srrE-"qZ-Zr!!*#u
+!!)ut!!%TMp](-Y"#6UA.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.mdC)TrU'afmd:)SmK3IWmK!7S!s%cW!<2Bd!<2Bh!:K7T!<)<f!:K7TqsFFaqX+=`qsFFa
+rpBmhmd:&TrU0[cs6fmes6^3omd:&Tmd:)CmK!7S#6=2[!:K7T!.jR<mK7aW`aR-l!liB.qsFGa
+qu6Z9rr2rurr2u<q>^Hpq#C?oq>^Eorr;uu!WN/srr<&urr<&trr<&rrr<&trrW9$rrDusqZ-Qo
+!!*#u!s&B$!<)p"!<<'!rVm!#s8N'!r;Z`rq>^Eos8Vrrs8N*"s8)frrr<&srrE-"qZ-Zr!!*#u
+!!)ut!!%TMp](-Y"*r&/@F"lS`l`RXmXaf,mK7aW`aOA~>
+!quZ5mcONLrT41^k2l[CjoYVGjoGDC!s%KG!<2*\!<2*`!9WDD!<)$^!9WDDqrRkYqW7bXqrRkY
+roO=`k2lXDrT=+[s5s=]s5jXgk2lXDk2l[+joGDC#6<oK!9WDD!.j:4jo`U&p8#t5!quZ5qrRlV
+qu6Z0rr2rurr2u3q>^Hpq#C?oq>^Eorr;uu!WN/srr<&urr<&trr<&rrr<&trrW9$rrDusqZ-Qo
+!!*#u!s&B$!<)p"!<<'!rVm!#s8N'!r;Z`rq>^Eos8Vrrs8N*"s8)frrr<&srrE-"qZ-Zr!!*#u
+!!)ut!!%TMp](-Q"3(<6UsAuApA`*_k(2Zqjo`U&p8!3~>
+!i2>HmI'lPrpBadrpBgfmdBrP!U]seme["amem+gmJm7Tmem.cmJm7_mem.cmJm7dmJm7dmem.c
+mem.amf*7lmJu\C!:K7TrpBadrpKdd"RZ9XmJqh+XmQ9OS>7UYrrT!d3W&4E;Z$Io`W#l;!<2uu
+`VKQ6!;QTo!;HNn!<3!"!<3&rrr<&urr<&us8N)rrr<&trrW9$rrDio!!)or!!*#u!s&B$!<)p"
+!<<'!rVm$$s8N*!!;lfr!;QTo!!<0#!;lcu!<3$!qu6Wrr;Qj!rr<&rrr<&urr<&trr<%Ms7cQj
+mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2mI'lPrpBadrpBgfmdBrP!U]seme["amem+gmJm7Tmem.cmJm7_mem.cmJm7dmJm7dmem.c
+mem.amf*7lmJu\C!:K7TrpBadrpKdd"RZ9XmJqh+XmQ:>`l_`7rrU?_IJ`F4<Vudr`r>u<!<2uu
+`qfZ7!;QTo!;HNn!<3!"!<3&rrr<&urr<&us8N)rrr<&trrW9$rrDio!!)or!!*#u!s&B$!<)p"
+!<<'!rVm$$s8N*!!;lfr!;QTo!!<0#!;lcu!<3$!qu6Wrr;Qj!rr<&rrr<&urr<&trr<%Ms7cQj
+mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=mH4<HroO1\roO7^k2uO@!TjC]k5,/Yk5>8_jo>DDk5>;[jo>DWk5>;[jo>D\jo>D\k5>;[
+k5>;Yk5PDdjoFQ+!9WDDroO1\roX4\"Qf^HjoBtpXl]`1pA^Z,rrMi<qrRlVqu6Z0rr2rurr2u3
+q>^Hpq#C?op](6nrr3$"rrDrr!!*#u!!*#urrDrr!!)ut!s&B$!;QQo!;lcr!<3!#!<<'!rVls"
+s8N)trriE&rrE'!qu?Zrq#C?o!ri6#qu6`urr<&rrr<&srrW9$!!)or!!*#u!!)ut!!%TMp](-Q
+"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@K^Sj?JaTQ+"#6UA.F%koS>7n:mJp/^rrC%7rrC%6s8N)os8N)mrr<&us8N)qrr<&us8N*!
+rr<&qs8N*!s8N*!rr<&orr<&rru(n;rr<'!rr<'!rr<'!rr<'!rr<'!rrE*!!;lcr!;HKq!<<'!
+qu6`us8N)rs8N)trrW9$rrDrr"9AK%!!*#urr@WMp](-Y"#6UA.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.K^Sj?JaTQ+"*r&/@EnfR`l`T(mJp8arrC(8rrC(7s8N)os8N)mrr<&us8N)qrr<&us8N*!
+rr<&qs8N*!s8N*!rr<&orr<&rru(n;rr<'!rr<'!rr<'!rr<'!rr<'!rrE*!!;lcr!;HKq!<<'!
+qu6`us8N)rs8N)trrW9$rrDrr"9AK%!!*#urr@WMp](-Y"*r&/@F"lS`l`RXmXaf,mK7aW`aOA~>
+!quZ5K]`:7J``up"3(<6Us8o@pA`,/joA<VrrBb/rrBb.s8N)os8N)mrr<&us8N)qrr<&us8N*!
+rr<&qs8N*!s8N*!rr<&orr<&rru(n;rr<'!rr<'!rr<'!rr<'!rr<'!rrE*!!;lcr!;HKq!<<'!
+qu6`us8N)rs8N)trrW9$rrDrr"9AK%!!*#urr@WMp](-Q"3(<6UsAuApA`*_k(2Zqjo`U&p8!3~>
+!i2>H[I3kkg@"n>JaTN*"$)mI.F%koUmsIBmJp/^s7jS/s7?<fs8;rrs8N)prr<&us8E#ns8;rs
+rr<&orr<&rs8;rrs8;rrs8;rsrriE&rr<'!r;c]or;cfrr;clt!!*#ur;cisr;[!#!!*'!r;cis
+rr<*"!<2uu!.k1Ds823d3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2[I3kkg@"n>JaTN*"+A23@EnfRb/Sl,mJp8as7jV0s7?<fs8;rrs8N)prr<&us8E#ns8;rs
+rr<&orr<&rs8;rrs8;rrs8;rsrriE&rr<'!r;c]or;cfrr;clt!!*#ur;cisr;[!#!!*'!r;cis
+rr<*"!<2uu!.k1Ds823dIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=[H@;cg?/>6J``ro"3pQ>SBV!6p<EKs!)i^opq?M'oDnafr;cfrrrDlp!!*#urW)`nr;cis
+!!)fo!!)orr;cfrr;cfrr;cis"T\T&!!*&t!;c`o!<)rr!<<'!!<3#s!<3#s!!N<%!<<)t!<3#u
+!!3*"rr2ruJcGHDqrS"*pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;X4;S!9jF_!/(:O!.k1Cs823d0r1<gcMms9UbRGgJaTT,
+"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<U0VV!9jF_!/(:O!.k1Cs823dH-4-8cMmscb'AR+JaTT,
+"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;X4;S!9jF_!/(:O!.k1Cs81p\`W,Y-cMmt>s2BQOJ`a#q
+"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;T&M7!.k0$s7cQjmK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<Q"h:!.k0$s7cQjmK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlV_uB]:JcC<$p](-Q"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HnF$>MJcC<$e,TC?nEpB=S>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'M
+S>7Ta~>
+!m8N2nEpDLme6L.s+14%rrr8mmdff:nEpC,`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2
+JaS*WX6p(<`l__?~>
+!rqu=nE0c=rUsh&pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds'YR#pAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb/!pAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajds7ZKkpAOFKjo`m%s.%=5!VXe8joA;1s+13[s81p\c1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@n*^5Lr;Zfb@HR"?mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNY>mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"k$%38mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mec,Lme6ABp@%DO0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.n*^5Hs7U()qXWq6io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io4A.io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7[A`i"7io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_iniPOhW!\co'Z);mK7aW`aR-l!liB.qsFGaJcC<$\GuHo"*r&/@F"lS`l`RXmXaf,mK7aW
+`aOA~>
+!quZ5n)jZ<#PRTcp?peoec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+G*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+G*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+G&
+eHFakmcNs+jo`U&p8#t5!quZ5qrRlVJcC<$\GuHg"3(<6UsAuApA`*_k(2Zqjo`U&p8!3~>
+!i2>HnEpGQmdB62JcC<$h#@HDk2-(!rq>jL"$)mI.F%koUmsIBmJp.9s+13[s823d3LllocMmsA
+S2l/gJaTT,"$)mI.=_~>
+!m8N2n*UD>k2P\&s8W)p@.sHjqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqYFUnqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'd^B(l)pqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'(.f&#-;ipQ7*nEpC,`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<
+`l__?~>
+!rqu=nE'`=rn[_=pAb$`!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:KgZ!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:KgZ!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj["n)*P
+hUTmLec,"+jo`m%s.%=5!VXe8joA;1s+13[s81p\c1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@nF$>=rn`5+JcFL)!p8@irSHu1"#6UA.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9UbVB,
+rr2ulrr2ulrr2ulrr2ulJaS*WbjGQfUmrla~>
+!liB.nEp;5rRq8FrVp=&s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqI'@"s8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)S"s8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)clqY'(&df%l"lL4-CH-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3b/Rl8rrU3_H1:53p@@qJp@@qJ
+p@@qJp@@p.mXafLmK7aW`aOA~>
+!quZ5nE0Z!"Rc!`pA]^;JbJ'r#O^Hnc.1(heaDQ%`W,Y-c2Rk=s2Flt!)eCJJcE7[qrS""s7W86
+rrVoo`UN$gmJut[mJut[mJut[mXaMOk02ri`W,Y-J,~>
+!i2>HnEpJ:k2t4Np4<6ps7-*lpAajdp@/(dk1/#EhUUKOmK5J>UaaRg!i2>HqsFG^JcC<$\GuHo
+"$)mI.F.qpUmsI7mJu,9rrM!MJaS*WbjGQnS>7Ta~>
+!m8N2nEpJ.g=k!+nq$gls7-*llMp/LlLFlZp>46GhV-9/n*U:+`l_`7rrU?_IJ`F4<It1$s1&++
+mK7mWb$iTq!m8N2nEp;1o`"sGnq$4[m`b)$IE'E<J,~>
+!rqu=nE'o!e^_phmeZq`pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpj
+pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpj
+pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpj
+pAFpjpAFpjpAFppp?)D;s5s%QrrDcjrs\W$s7Ym2c-=ehc.27Ojo`m%s.%=5!VXe8joA;1s+13[
+s81p\c1_1-c2Rh<c1'iqeb&kBc0g/FJ`b2="3pQ>S:C~>
+!h?&@nEp>%k5Nm2p4<6ps7-*lmf2_TmdU5Vmf(`=hTa=-nEpB5UmrmYrrS^d1&LA=;M"k!s1&++
+mK52>S12b`!h?&@nEpe:s8U?oc.1(hc.1)=s4)\gJaU_L"#6UA.=_~>
+!liB.nEpM#g="9pmeVM7JcG<@"R?$Ps6B.S#km9'cI1Fdb3&3]"*r&/@EnfR`l`T(mJp7<s+13[
+s823dH-4-8cMmscb'ELE&'FqP`lc<D`lc<D`rH(]l@JASm`b)$H-4-8J,~>
+!quZ5nE(+le]l(PmdBfBs7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9f
+s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9f
+s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9f
+s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9f
+s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M^%s7ZKdp>5i+s5*JCs7ZKlp&b9f
+s8DWts6ea_`QcrH`SU+H"3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2FKi%`S/A]u@\(
+]u@\(^&S,OJ`_OGbN8oGs7W7=~>
+!i2>HnEpJ!hVQN-mXbChs7-*lmf2_TmdU5]ma]S=k/G=%nEpB=S>7UYrrT!d3W&4E;M"k!s1&++
+mK5J>UaaUh!i2>HnEph#s8Q8+@Tm5E@Tm7@s1R:bme[!umem.Jmem.ameQq5mK3IWmJutK!!%iC
+"$)mI.=_~>
+!m8N2nEpOqg="!hlMC@.s+14ArrhKak5XT7rsAPqim,Qlg:kG`nEpC,`l_`7rrU?_IJ`F4<It1$
+s1&++mK7mWb$iTq!m8N2nEpCes8Q6t?2sp*[bCQFqZ+@ur;c!Jr;cfaq>f%5!s%cW!;>g\!/U%F
+IE'E<J,~>
+!rqu=nE'nfe]kePk5G"'s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKdJ,f6BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdp)a8-s7ZKds7ZKds7YUKk4[s2s7ZKds7ZKd
+s7ZKds8M]shSm1Qe\/ZQnE'htpA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<E*h&$5g2>$>B=
+@Tm5E@fQJ0ebSA)!5@Uo!9WGB!<)'V!7^-5!9WDDp>u>TLunfapA^Y5~>
+!h?&@nEp=ahYtb"mXbChs7-*lk5XTDk4/HPp?qq)"5^DuhXKq80r1<gc2Rj8UbVc7!)eCJJcE7[
+qsFP@UmrmZrrS^d1%=TAXT/<0mcNs"mcNs"s8T1FqX4@`rU'Xc^[;(%rpKddkjAENrpKddrpBjg
+md:)&mJm6<meQ8Q0r1<gJ,~>
+!liB.nEpOig<.FXlLOY"qLSM7q?5[OhYQ+"q?cldk/t]dg:"`PnEpC(b/Rl7rrU3_H2I"0<It1$
+s1&++mK7aW`aR0m!liB.nEpg`s8QNiio]7_io]8#s/"$;mf*:cmJm7%mJm7dmf*:NmJm7dmf*:d
+mK3IWmJtZ&!!%T<q<e?1b/Rk?~>
+!quZ5nE'qVc,IB8k3dfoJbJ[."P*4rp=8^,#k$Q_]uAO'^")W7"3(<6Us8o@pA`,/joA;1s+13[
+s81p\`W,Y-cMmt>s2FKi&#B7*@clP0hWE\WhZ*VOc2-T&!<)$[!5IXr!<2-\!9iPF!<2-\!<2*_
+!9WDDdH1E/J`cdj"3(<6Ujr~>
+!i2>HnEpXjhUTTqk5Y/TrrD3]!!)ip!W`6#rr;lrr;Z]qq#C9mrr;oss8Vusrr;rtJcF'r"QoaH
+s5rnP$24D]e]$(q[(YVkmK5J>UaaRg!i2>HqsFG^JcC<$\GuHo"$)mI.F.qpUmsI7mK8^Rs)[r7
+!L2.3mf*:/mJm7Ymf*:cmf*:Pmf*:cmf*:emK3IWmJtZ&!!)`\!!%`@"$)mI.=_~>
+!m8N2nEr-9f#kkPipu[:p&Og_pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZp&Og_pA4LZpA+dc!;cEc
+qu?lrpA4LZr;[,sqY'dZqY'dZr;ZoqpA4^f!VZBf!!<#jqYgJEqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ:\se]pA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4L:p=f5opA4LZpA4LZpA4LZpA4XV
+o&@g/b1<`,hXKq8IE'E<c2Rjf`dRaP!*+UMJcE7[qsFQ7`l_`8rrU?_IIQY,OoPH$p\t8VcMR&0
+!6OX/!;#XY!<)?c!:'"P!<)?c!<;Hh!:K7TdI$u7p?hn\L$f%k`l__?~>
+!rqu=nE)R/c,I'/hX9h*mJu\Kme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmJu\Kme6)Bme-YS!;>jS
+qu?lnme6)Br;[,kp?qYBp?qYBr;Zomme6SZ!Uf[Z!!;l^pAP&Ap?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB:\O5Mme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)!ma^aUme6)Bme6)Bme6)Bme6AB
+ma]:i`QbKkhXKY0c1_1-bl7_;c26W';M"k!s1&++jo`m%s.%@6!VXe-jo^PAs)[r7!K55"k5PG'
+jo>DQk5PG[k5PGHk5PG[k5PG]joYVGjoEfk!!)`T!!%`8"3pQ>S:C~>
+!h?&@nEpIUhTa$ak5P'arrE)ms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKdrrE)ms7ZKdrrE)m!;?Em
+s7ZKds7ZKdrrE)mrr<&ms7ZKds7QHds7QEmrrE)mrr<&m!;?Hds7ZHms7ZHms7ZKds7ZKdrW%HA
+s7ZHms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZIGpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpA`\Cec42"pAajdp]1<e
+#Nj:Mc/,80hXKq80r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d1%=T5MuWfup\t8Pebeb7
+!;Gp[!<2Be!:Kgd!:Kgds6]shmJm7dmem.bmK<OX!:K:S!;l3`!<;Kc!;c*`!;l0g!:K7TmJm7c
+mf!4cmK!=UrW)ud!!)oa!<DQb!!2KfrpK^bs6fjdqX4:^rpBmhmJu\Cr;c]^r;clc!!*#dq>^Qa
+!<2Eb!<2Be!:Kgds6fgcrpBdemf!4cmK*CV!3>Mi0r1<gJ,~>
+!liB.nEt+`f#GGDhX9t*p&OgWp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp&OgWp@@qJp&OgW!:og`
+p@@qJp@@qJp&OgWp&G*`p@@qJp@84Sp@81`p&OgWp&G*`!:ojSp@@nWp@@nWp@@qJp@@qJrW%H=
+p@@nWp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ
+p@@qJp@@o1o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(MYJo(LB&cM#QWo(MYJp]1?b
+#k$Qh^;e`p]&)rE"*r&/@EnfR`l`T(mJp7<s+13[s823dH-4-8cMmscb'ELE",6dTEVKJ6L!KS`
+!!)c]r;cib!<DQe!!)Hd!<;Hh!:BgerpK^brpBmhmJu\CrW)i`rW)udr;c]^!!)oa"p")Z!:Bge
+rU0XbrpBdemf!4dmJm7amK!=UqZ$Zb!<2Eb!<;Kd!;c-^!<2Bh!:BjTmem.^mem.cmJm7dmeQna
+mK!7Sr;cib!<DQe!<;Kc!<2Be!:KgdrpBgfmJs<U"*r&/@=S~>
+!quZ5nE'qFc+UKte`Ql!!!)0L!!)l`"p")Z!:K7Tq!J+^rpKddqX+=`rpKdd!U]semf*7fmK!.P
+!!*#d!!)i_rW)ob!!%T<i9g`em`"V5r9j=[s6^0Te\/?'c()/knE'hls7W85rrVoo`V\ct;M"k!
+s1&++jo`U&p8$"6!quZ5nE'h*pA]4/rrVnHc26W'!;GXS!<2*]!9X7\!9X7\s5jC`jo>D\k5>;Z
+job\H!9WGC!;kpX!<;3[!;bgX!;km_!9WDDjo>D[k5GA[joGJErW)u\!!)oY!<D9Z!!23^roX.Z
+s5s:\qW@_VroO=`joFQ+r;c]Vr;cl[!!*#\q>^QY!<2-Z!<2*]!9X7\s5s7[roO4]k5GA[joPPF
+!3>5a`W,Y-J,~>
+!i2>HnEr]7e]l(Xk4\NKp&OgdpAajdpAajdpAajdpAajdpAajdpAajdp&OgdpAajdp&Ogd!<;`m
+pAajdpAajd!!)`mpAY*mJ+ip9s7ZHms7ZKd!;6Eds7ZHmrrE)ms7ZKd!;?HdrrE)ms7ZKds7ZHm
+s7ZKdrrE)ms7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds).Q1pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAaj:p=8lepAajdpAajd
+pAajdpAb0dp?'W5c./>tk4%d@3Llloc2Rj@S2pK7!)eCJJcE7[qsFPHS>7UZrrT!d3UlG=HiO+e
+p\t8@ebeb7!;Q!^!<;Ke!<;Ke!<;Ke!<;Hl!:K7T!:BgeqsFglmd:&Tmd:)CmJm7amK`g\mJm7T
+mJm7amJm7amMGrlmJm7T!!)HT!:K7T!:K7T!:K7Tmd:)PmL90amJu\C!:K7Tmd:&TrU'dgmd:&T
+r9jRbs6fmes6fmes6fmes6]jeqsOIas6^*lmd:)CmJm7cmLfNfmJu\C!!)HT!!)HT!!)HT!;l0h
+!:K7T!:K7TrpBadWU9jKS>7Ta~>
+!m8N2nEpXKd`/l<hX9h&nc7hC!!)ld"p"5b!:o[\q==OcrUTsgqsj^erUL!inc8XZ!W_ckqsj^e
+rUKpgq!nCbr:0gfJb%dj"O?S`o$6gss6^-K`k'1<Q+GiAmK7mWb$iQp!m8N2qsFGaJcC<$\GuHo
+"+A23@F"lSb/Sl!mK7V3s)If5!Hl]bmJm7^mf*:emf*:emf*:emf*:emKWa[mJm7T!!)oa$NTV_
+!!)HT!:K7T!;l0i!:K7T!:K7T!;l0a!;l1$!:K7T!:Bgemd:)CmJm7TmJm7TmJu\C!;l0n!:K7T
+md:)CmJu\C!!)uc"9@lX!!)rbrrE)errE)errE)errE)e!!)oarrE)e#6=2[!:K7T!<)<u!:K7T
+md:&Tmd:&Tmd:&Tmd:)PmKWa[mJm7TmK!7S!!'"d"+A23@=S~>
+!rqu=nE((Bc,I'/eaDSfmJuD;!!)l`"p")Z!:K7Tq<n7_rU0[cqsFFarU'^emK!4R!W_WgqsFFa
+rU'Xcq!J+^r9aObJaVLb"NBfJm`"bb$0L[+`O*V/PdK<:jo`m%s.%=5!VXe8joA;1s+13[s81p\
+c1_1-c2Rh<c1'itF8#WTq#:EhF3XUE!!)fVrrE)]rrE)]rrE)]rrE)]#6<oK!!)-]!;kmd!9WDD
+!9WDDk2lXDqrS.ak2lXDk2lXDqrRkYqrS^qk2lXDjo>DDjoFQ+!!)0D!!)0D!9WDDqrS=fk2l[+
+joFQ+!9WDD!<)$_!9WDD!;u!Z!<;3]!<;3]!<;3]!<;0]!;kpY!<;0d!9WDDk2lXDrT4^mk2l[+
+jo>DDjo>DDjo>DDjoG;@#6<oK!!)0D!<2*\!3,)_c1_1-J,~>
+!h?&@nEp=8ec*Mkk3hs2p&P*c"7GmNpAFskmf)qY!!)`k!<2Zn!;>j[p(Zopme6>Sme-V\p@dqJ
+me6>Sme6)Jp&Y6fmf)o&mJm7\p&OOS!!)`d!;>g\p@dqJme-YSme6&Kp@dqJmf)n]mJu\Sp&aX^
+!<2Znme6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[U
+mf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[U
+mf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)n]me6)Jp&a[Umf)nc`V.:E`V/`nmf)n]me6)JpAaO^
+p?q)B`<4tT^#&8H"#6UA.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9UbVB,"*=MBF8,\8F3XUM
+!!)f^!!)uc!s%cW!<2Bd!<2Bg!:K7TrpBadqsF[hmd:)CmJm7dmJm7amK3IWmK!4R!!)oa!!)oa
+!s%cW!<2Bg!:BgerpBjgmd:)SmK3IWmK!.P$io_`!:K7Tmd:)CmK!4RrrE&d!!)rb!!)uc!s%cW
+!<2Bd!<2Bd!;l0a!<2Bj!:K7Tmd:)QmKN[ZmJu\C!<)<f!:K7TrpBadqsFOdmd:)SmK3IWmJs3R
+"#6UA.=_~>
+!liB.nEpmJd_`T4hWF+gmJu\?mcs6*mem+flL*s*r;Zi_r;]dalL"Z?lL*s*l2^,;l2^,;!!)<P
+lL*s*l2^,;lL*s*!:K.?lL*p;!:K+PlL"WPlL"Z?l2^,;lL*s*!:K.?l2^,;lL*s*lL*p;lL*s*
+l2Ug6mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*0^e5olL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*_X>;/_X?^WlL*s*lL*s*
+lL+Z:#j1!\]#)mT]&)rE"*r&/@EnfR`l`T(mJp7<s+13[s823dH-4-8cMmscb'ELE")[o7EVKJ6
+D9i%H!!)f^!!)uc!s%cW!<2Bd!<2Bg!:K7TrpBadqsF[hmd:)CmJm7dmJm7amK3IWmK!4R!!)oa
+!!)oa!s%cW!<2Bg!:BgerpBjgmd:)SmK3IWmK!.P$io_`!:K7Tmd:)CmK!4RrrE&d!!)rb!!)uc
+!s%cW!<2Bd!<2Bd!;l0a!<2Bj!:K7Tmd:)QmKN[ZmJu\C!<)<f!:K7TrpBadqsFOdmd:)SmK3IW
+mJs3R"*r&/@=S~>
+!quZ5nE'q-c+UKte_^;f!!)lXr;cfYr;Zi[r;ciZ!!)oY!!*#\"9@TH!!)lX!!)oY!!)oYrrE)]
+$395N!!)0D!9WDDqrRkYrT4([puVPVr9""ZJ`btS"MNs2k.U<I#i=+F[(X_:[+4[."3(<6Us8o@
+pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2FKi")@Q0F85b:p1hkLjo>DVjo>D[joYVGjoGDC!!*#\
+!s%KG!<2*\!;km`!9WDDk2lXDroO1\qrRt\k2l[Bjo>DYjo>DYjoYVGjoGDC!s%H`!<2*_!9WDD
+roO:_k2l[@jpV7PjoFQ+!9WDDk2l[Bk5PG\jo>DZjo>D[joYVGjoGDC!!*#\!!)oY!!*#\"p!fJ
+!9WDDr8n1`k2l[+joGAB!s%KG!<2*\!;km\!9WDDroO:_k2lZBjo`U&p8!3~>
+!i2>HnEpaDe]kePhX9h*p&Og[mf)q[!!hrc!!)`d!!)uk!:Kj[!s&&_!<)Tmme-Y[p&G*lpAP'i
+p&G*jp&XR]rUp<\p@eIc!:Kj[rW)rkrW)ojrrE)mrr<)nmelb[me-Y[p'0sYp&Og[melbYmelbY
+melbYmelbYmelbYmelbYmelbYmelbYmelbYmelbYmelbYmelbYmelbYmelbYmelbYmelbYmelbY
+melbYmelbYmelbYmelbYmelbYmelbYmelbYmelbYmelb_m`"n=p;QItp&OOY!"A;hp?qA*c+VBP
+MnS9BmK5J>UaaRg!i2>HqsFG^JcC<$\GuHo"$)mI.F.qpUmsI7mK6qus)[r7!FjUVmJm7^mJm7c
+mK3IWmK!7S!!*#d!s%cW!<2Bd!<2Eb!<;Hg!:K:P!;l0d!:K7TrU'XcqsFFaqsFOdmd:)SmK!=U
+qZ-Za!!*#d!s%cW!;l0m!:K7Tmd:)CmJu\C!<)?_!;u6b!<)<f!:K7TrpBadrpBadqsFFarpBsj
+md:)CmK!1Q"p")Z!:K7TrU'afmd:)SmJm7dmem.cmJm7dmf*7fmJs3R"$)mI.=_~>
+!m8N2nEr,id`/l<g?.\gl2^,;lL*s*!!)<P!!)<P!!)<PlL*s*lL"Z?l2^,;lL*s*!:K.?!:K.?
+rW!W"lL*s*!:K.?lL*p;lL*s*lL*s:!!DNSlL+WO!q,@ArW!8mlL*p;!:K+P!.XG%mcs6*mcs3?
+mcs6*mcjf;mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*
+mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcs6*mcln%
+lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*s*lL*rSlGDi'lL*s*lL*s8
+!"A/\mcrrg`k'1<M7VR5mK7mWb$iQp!m8N2qsFGaJcC<$\GuHo"+A23@F"lSb/Sl!mK6bks)Ii6
+!qopFqsFFaq!J+^rU'afmd:)SmJm7dmK3IWmK!7S!!*#dr;clc!W_ZVqZ-N]!s%cW!<)<c!;l0a
+!;l0d!:K7TrpBdeme["amJm7dmK3IWmK!.P$io_`!:K7Tmd:)CmK!4RqZ-Q^!!)uc!s%cW!<2Bd
+!<2Bd!;l0a!<2Bj!:K7Tmd:)QmKN[ZmJu\C!<)<f!:K7TrpBadrpK^bs6]jerpKdd!U]rdmK7mW
+b$ff~>
+!rqu=nE((1c+UKte_]0FjoG;@rrE)]rrE)]rrDlW!s%KG!;kmY!<2*\!<2-[!;tsZ!;kmY!;bjW
+!<)'Z!<2-[!<)'[!<;3]!;P[V!;kmY!.j:ljoiB[^#m$)k555Xjp9hg]sPJlK='M)jo`m%s.%=5
+!VXe8joA;1s+13[s81p\c1_1-c2Rh<c1'it>5%u;q#:E`>0Zs,!!)fV!!)u[!s%KG!<2*\!<2*_
+!9WDDroO1\roX.Zs5j@_k2uO@qrRt\k2l[Bjo>DYjo>DYjoYVGjoGDC!<D9Z!<;0]!<2*_!9WDD
+qrS:ek2l[+joFQ+!9WDDrT<tWr8mtZrT41^k2l[Cjo>D\jo>DYjo>D\jothJjoFQ+!;ts`!9WDD
+k2l[BjoYVGjoGDC!!*#\r;cl[!!*#\rr<)^!3##^c1_1-J,~>
+!h?&@nEr2ehSm1IhWF7gmJu\;mcNs"!9W_3mJu\;!9W_3mcNs"mcFN3mJu\;mcNs"!9W_3!9W_3
+mcOKK-KaaY!9W_3mcNp;mcNs"mcFKLmJm7LmJm7L!!)HLmcNp;!9W_3rW%H1!9W_3mcNs"mcFN3
+mcNs"mJu\;mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNq#k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3fqN^$`T%k3hC"k3i-I
+"n(O8mcNC*`<4YC^#&8H"#6UA.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9UbVB,"'Ya)F85b:
+mTS0<mf*:_mJm7cmK3IWmK!7S!!*#d!s%cW!<2Bg!:K7TrpC!kmd:)CmJm7]mK3IWmK!4R!!)oa
+rrE#crrE)e!!*#d!s%`h!;l0a!<2Bh!:K7T!<)?c!<;Hn!:K7Tmd:)CmK!4RrrDi^!!)uc!s%cW
+!<2Bd!<2Bd!;l0a!<2Bj!:K7Tmd:)QmKN[ZmJu\C!<)<f!:K7TrpBjgmd:)SmK3IWmK!4RrW&nb
+"#6UA.=_~>
+!liB.nEpL/d_`T4g>;hg!!)oU!!)uW!s%??!;POU!92u<qr.SUro*nXr8R\Uro*nXqr.SUqr7VU
+$/tpbio0q<iW&uVir9#Xir/oYiW/c5!!)oU!!%T0io1*LijRjTqVqDQrSe+>g;:G<dXA^`nEpC(
+b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.nEpBYpA].-rrVIccMR&0!;Z$_!<)<f!:K7T
+rpBadrpBjgmd:)SmK3IWmK!7S#6=2[!:K7T!;Gm`!:K7TrU'XcqsOIarU0[cs6]jerpBjgmJm7a
+mJm7dmK<OXmJm7cmf*:emKim]mJu\C!:K7TrU0[cq!J+^rU'afmd:)SmJm7dmJm7amJm7dmKN[Z
+mJu\C!;u6h!:K7Tmd:)RmK3IWmK!7S!s%cW!<2Bg!:K7TrU0XbW9sb5b/Rk?~>
+!quZ5nE'prc+UKte^aZU!W_*-rS@PTec+D-!8c6+rS@P)rS@VVe_U<*h?VTfh>lEheH#R)!7h&K
+s5!e,!<(aUe_U<*h@A)mh>dQ4!!(m4!!(OL!<1gZe_U9+hVQf^!!;!Webn8.e_]-_hVQf^h?!]6
+ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(
+ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8(ebn8.e_[CaXPU&Vh>u0`quH]P
+#h@25[(X_*[+4[."3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2FKi"&eReF85b:k#0J$
+k5PGWjo>D[joYVGjoGDC!!*#\!s%KG!<2*_!9WDDroOFck2l[+jo>DUjoYVGjoGAB!!)oYrrE#[
+rrE)]!!*#\!s%H`!;kmY!<2*`!9WDD!<)'[!<;0f!9WDDk2l[+joGABrrDiV!!)u[!s%KG!<2*\
+!<2*\!;kmY!<2*b!9WDDk2l[AjothJjoFQ+!<)$^!9WDDroO:_k2l[CjoYVGjoGABrW&nZ"3(<6
+Ujr~>
+!i2>HnEqBFe]kePhX9OojoFQ3k3hC"!:K";joFQ3!:K";k3hC1!(62:!9W_3mcNp;mcNp;mcNs"
+mcNp;!9W\LmcNs"mcFN3mcNs"mJu\;mJm7L!9W_3!!)HLmcNp;mcNs"mcNp;mcOKKJ*-1]mJu\;
+mcNs"!9W_3mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mPa4qk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k.Tojk.TpFk3hC"k552f
+k3h["mbZ4%c..0Sk4%d@3Llloc2Rj@S2pK7!)eCJJcE7[qsFPHS>7UZrrT!d3UlG=9)npDq#:EX
+9%Ee+rrE#c$NTV_!!)HT!!)HT!<2Bd!<2Bn!:K7Tmd:&Tmd:)SmK3IWmK!7S!!)c]#QX;\!!)HT
+!!)l`!!)uc!!*#d#6=2[!!)HT!;l0a!<2Bd!<2Bd!<)<c!<2Bn!:K7Tmd:)CmJm7cmJm7amL'$_
+mJm7TmJm7TmK!7S"9@lX!!)oa$NTV_!!)HT!:K7T!<)<q!:K7Tmd:&Tmd:&Tmd:)SmK3IWmK!7S
+!s%cW!<)?c!2o5e3LlloJ,~>
+!m8N2nEpI*d`/l<f)=S.!;kaU!<(mZ!92u<qr7PSs5F"Yqr.SUro*nXqVqMTs5F"Yqr.SUqr.SU
+ro3qX!TF+Yir9#ViW&uTiW9,>ir/rViW&uUiW&t0io8r#[c4aT[ef"]!;tg]f#G;@dWrF\nEpC,
+`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2nEpBLo)F:9rrV%JcMHu/!<)<n!:K7T!:K7T
+!:K7TrpBadrpC*nmd:)CmJm7TmK!7S!s%cW!<2Bd!;Gme!:K7T!:K7T!;c*`!<)<c!<2Bk!:K7T
+!:K7TqsFFarpBadrpBadrU'XcrpC*nmd:)CmJu\C!!)uc!!)oa$NTV_!!)HT!!)HT!<2Bh!:K7T
+!;l0l!:K7T!:K7Tmd:&TrU(-qmd:)CmJm7TmJm7TmK!7S!s%cW!<2Bg!:K7TrU0[cVsXY8`l__?~>
+!rqu=nE((!`P&Xlc/."-h>mH0!!)uS!s%37!;kXO!<:mU!;kUQ!<1gT!;bRP!<:mU!;kUQ!;kUQ
+!<1jT!!1pVrndYTr8%DRqVD8RhVS53rS@MSqq_;QJ_oDC"K^I]hQ6S1quH`Q$.[nW]sPJtF0sfn
+jo`m%s.%=5!VXe8joA;1s+13[s81p\c1_1-c2Rh<c1'it614c*q#:EG6-]8grrE#[$NT>O!!)0D
+!!)0D!<2*\!<2*f!9WDDk2lXDk2l[CjoYVGjoGDC!!)cU#QX#L!!)0D!!)lX!!)u[!!*#\#6<oK
+!!)0D!;kmY!<2*\!<2*\!<)$[!<2*f!9WDDk2l[+jo>D[jo>DYjpM1Ojo>DDjo>DDjoGDC"9@TH
+!!)oY$NT>O!!)0D!9WDD!<)$i!9WDDk2lXDk2lXDk2l[CjoYVGjoGDC!s%KG!<)'[!2nr]c1_1-
+J,~>
+!h?&@nEpHpe]#5@hYlR:!;kmY!<)$^!9WDDr8mtZroO:_k2l[@jo>D\jo>DWjob\Hjo>D[k5PGY
+jo>D[joPPF!<)$[!;tsZ!;kpY!;P[V!;kmY!.j:ljoi'R[-"ank4erUjp0b^]uAiC^#&8H"#6UA
+.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9UbVB,"@;JLpAb$`s6]sN6-]5nquH]`r;cib!!*#d
+!!*#d!W_ZVr;cibqZ$Zb!<)?a!;l3a!<;Kc!;Q!\!<)?a!<)?a!<;He!<2Bd!<)?a!<)<i!:K7T
+md:)Smem.cmem.cmJm7dmem.bmJm7cmf*7fmK!+Orr<2i!:K7TrpK^b"RZ6imK!7Sr;cib!!*#d
+!W_ZVqZ$Zb!<)?c!<2Bd!3>Mi0r1<gJ,~>
+!liB.nEpHsd_`T4f)FN2iW.upini\O!8c_liW.up!8c_lina[lina[liW.upini\O!8c_l!8c_l
+ini\OiW.up!!)$8inaY8ini\Oina[liniYpiW.upina[lini\O!8c_liniYp!.WkbhW!DOhW!Al
+hW!DOhVnOphW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DO
+hW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhW!DOhVpQP
+ini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini\Oini[tii_:Dini\OiqNNQ
+h?VWK]#)m4]&)rE"*r&/@EnfR`l`T(mJp7<s+13[s823dH-4-8cMmscb'ELE"@2,;me6YJ#P.<N
+k2P5_cM?o+!<)?a!<2Bd!<2Bd!<2Bf!:K:R!<2E`!!2KfrU0UaqsOIas6fgcq!S(\rU0UarU0Ua
+s6]jerpBadrU0UarU'jimd:)CmK!7Sr;clcr;clc!!*#dr;cib!!)ucrr<)f!;c-`!!M]imd:)S
+mem+gmJm7T!<2Eb!<2Bd!<2Bf!:K:P!!2KfrU0[crpBadX6p(8b/Rk?~>
+!quZ5nE'm`c+UKkc2H/p!7fWVrm_8Se_\j,!7fU"r7(cIrm_)Ne_U<)eH4UX!<1LK!;t@PhUU-V
+e^XX"rRLoJrRCu+eH#U!#i5R3!7fWVeH#U!!oDH-rm_50e^XX"e_^5S!oDH-rm_50e^XZMe_^5S
+!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(
+!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(!8dY(#2Z0+Ut)9trRLZCrm_7u['[Nk
+@^O\Tjo`U&p8#t5!quZ5qrRlVJcC<$\GuHg"3(<6UsAuApA`,$joe!,k2uC:jp1>:k2+tF6-]5f
+quH]Xr;ciZ!!*#\!!*#\!W_BFr;ciZqZ$ZZ!<)'Y!;kpY!<;3[!;P^T!<)'Y!<)'Y!<;0]!<2*\
+!<)'Y!<)$a!9WDDk2l[Ck5>;[k5>;[jo>D\k5>;Zjo>D[k5PD^joG8?rr<2a!9WDDroX.Z"Qf[a
+joGDCr;ciZ!!*#\!W_BFqZ$ZZ!<)'[!<2*\!3>5a`W,Y-J,~>
+!i2>HnEpHpe]kePhYlR:!;kpY!<;3]!<;3]!<)$[!<2*_!9WDDqrRkYroO:_k2l[Bk5PG\jo>D[
+jo>DXk5PG]k5PDcjo>DDjo>D[k5PGYjo>DUjo>DZk5PF4k2PM+[-"aX[/9"^!<)$bhT`aYeS;e[
+nEpB=S>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HnEp9:rT=(Hrq6H^p+b+SmJm72mJm7!
+mf*:0mJm6amK5J>Ua^f~>
+!m8N2nEpHod`/l8f)=G*!;kXQ!<:pU!<:pU!<(aS!<1gW!8cQ4qq_;Qrn[_WhVJ82hZ!TTh>dQS
+h>dQPhZ!TUhZ!Q[h>dQ4h>dQShZ!TQh>dQMh>dQRhZ!S,hW!ApWnsc4Wr(ZL!<(aZf###<dV6;L
+nEpC,`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2nEp95rn\%Bk3D6olL+**l86fCmJm72
+mJm7!mf*:0mJm6amK7mWb$ff~>
+!rqu=nE('ec+UKtc.1A$eH#KsrrE)LrrE)LrrE#J!!*#K!s$m%!;k:H!<1LN!7fU"rRLoJrm^uK
+rRClJqUPTGs4.,L#1W\Re^XX"rRLoJqpbZHpXK6Dr71fIJ^rc1"JjSDeYN)mq>^oRhUU0$]sPJl
+@^P"]jo`m%s.%=5!VXe8joA;1s+13[s81p\c1_1-c2Rh<c1'iq1&]W0k2,7Wk2u*ojtY-;jo>D*
+jo>Cnk5PG(jo>CYjo`m%s."T~>
+!h?&@nEpTlhSm1IhVRDOk5,,ZhWFb:"5`1sk5>8[hYR9_joFQ#k2,7WjoFQ#!8cl8!!M0@hWE\n
+!!q`Dk2,7Wk2,8!!!;$>hYdETk2-%:"6SJ&hYmK\hWE\WhWE\WhY[A'hWEYphWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W0AbjJk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk+q.8k+q.rk2,7Wk552_k2+tWhVS7N"5[M#hXKq8
+0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d1%=T2KCgl!>1NQ=pAjUK!!(72!!'b$r;at-
+!!&na"#6UA.=_~>
+!liB.nEpHcd_`T0f)=>"!<:dO!<(XM!!(aM!!1dRqUu)Qg=cP\gA:mJgAM$HgAM$NgAM$OgAM$M
+gAV*IgACsMg&M,(g>U`gU"Z3oU&*L@!;tOUf###8dTsH@nEpC(b/Rl7rrU3_H2I"0<It1$s1&++
+mK7aW`aR0m!liB.nEp:-oIp;KcM[,)!:B1S!6jj2!5@n"!6OX/!2f/dH-4-8J,~>
+!quZ5nE'pYc+UKkc-?7<qZ$ZAeboIMc.1(hr;ZiBqZ%,V!7f?Ec.1(h!7f<oc.2[k"O5KAe]n$m
+#h@2Mc.1(hc.2am!mT9?r;ZlKc2@VEe]lXhrW!5Ke]lXhe]lXhquD5ke]e*=e]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lVtc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hSCO.[SCPm7c.1(hqu@/Uc.1@hc*Xjkc!%L)nE'hl
+s7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5nE'au.K2%%.K2%%.K2%'.9b!ok4\lCjo>D*
+jo>Cqk5>;%jo>CYjo`U&p8!3~>
+!i2>HnEtd0e]kePhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Wh>lEphWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWEYphWE\WhWE\WhWE[Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W,3IbEhWE\WhWE\WhWE\WhWE\WhWE[jhQ5S0hWE\WhWE\W
+rW!DihWEtWk2+@rc/)X;k4%d@3Llloc2Rj@S2pK7!)eCJJcE7[qsFPHS>7UZrrT!d3UcAGhP?Bo
+P`(caP`(caPbd/emXafMmK5J>Ua^f~>
+!m8N2nEpNad`/l8db<E)hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV%t`hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?!8?;`hV-i?hV-i?hV-i?hV-i?J)8o9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g)Ai%hV-i?hV-i?hV-i?U"Z3oU"\AWhV-i?
+hYmKahV-iCg=jul]#N0$]&)rE"+A23@EnfRb/Sl,mJp7<s+13[s823dIE'E<cMmsg`dR=D!SXCD
+N<,m0JaS*WbjGR]`l__?~>
+!rqu=nE'mXc,I''c.UVI!5-h^!.i\YeHDDmSCO/*ec#RGeHa@4[)L9n[,1<7"3pQ>SBV!6p<EKs
+!)eCJJcE7[qrS"*pA^Z-rrMi<n)aZ$V"T]IUt(%YJ`b2="3pQ>S:C~>
+!h?&@nEpKYhTa$YhVNbEhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEYphWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE[Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W/EYgOhWE\WhWE\WhWE\WUunK8UupOrhWE\W
+hW=h#hWE\Ok2+t6`Qd7;^#&8H"#6UA.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9UbVB,"8;0>
+c2Q5nc2Q5qc.1A$JaS*WbO,HeUmrla~>
+!liB.nEpHVf#GG@db*7R!.ijng'!u#S_BY0g&M-Lg'?3G^;e`#]&)rE"*r&/@EnfR`l`T(mJp7<
+s+13[s823dH-4-8cMmscb'ELE&+]#>cI1"dcI1"dcI1"ll@JASm`b)$H-4-8J,~>
+!quZ5nE'pIc+UKkc-:agc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1&=c.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1'ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh/Ci"qc.1(hc.1(hc.1(hPgu#KPh"%/c.1(h
+c.)gEc.1(`e]l@P[(X^V[+4[."3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2FKi!q,4$
+p<<TfJ`_OGbN8oGs7W7=~>
+!i2>HnEtd(hUTTihWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE[Ek2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W-g':JhWE\WhWE\WhWE\WhWE\WhWE[rhPB#0hWE\WhWE\W
+hWE\WhYlRAhTa$ihGV&LnEpB=S>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'M
+S>7Ta~>
+!m8N2nEtd"f$;.Pdb`^7g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:P5hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?1Z$jBg>:Q?g>:Q?g>:Q?g>:Q?g>:PWg7d5og>:Q?g>:Q?
+g>:Q?g>:]?hU]]`cIP\#hXKq8IE'E<c2Rjf`dRaP!*+UMJcE7[qsFQ7`l_`8rrU?_I=^g;m]5aX
+IE'E<J,~>
+!rqu=nE'mHc,IB0c%4Drea_/mSCO.[SFG&6c,IB8bt>A"nE'htpA^Z,rrMi<qrRlVJcC<$\GuHg
+"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@nEpZVhUTlihVRDOk2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)ir
+k5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)ir
+k5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)ir
+k5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)ir
+k5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3=k2,8"h?)irk5O3Ik2,7WhPB;0k+pkjk2,8"h?)ir
+k5F-Ck2+t>c.1ZC^#&8H"#6UA.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9UbRGgJaTT,"#6UA
+.=_~>
+!liB.nEpNLf$_RTdb<Q/g4@uLg'",'U"Z42g'QWif#l"\ejR++nEpC(b/Rl7rrU3_H2I"0<It1$
+s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5nE'p@c,IB0c-:agc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1'ge]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh/Ci"qc.1(hc.1(hc.1(hSCNkSSCPm7c.1(h
+c.1(hc.1(`e]l@P`Pp(f[+4[."3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2BQOJ`a#q
+"3(<6Ujr~>
+!i2>HnEpH`c/.!qec+\4hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%
+hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%
+hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%
+hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%
+hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuXIhWE\Wk,dF@hQ5l%hWE\ojoXE%
+hYZF?hUU05bu27;nEpB=S>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2nEpN]b1=_Xdb<E)hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?J)8o9g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g)o2*hV-i?hV-i?hV-i?V:qd"V:se[hV-i?
+hV-i?hV.tc#iaR`cIU-3]&)rE"+A23@EnfRb/Sl,mJp7<s+13[s823dIE'E<cMmsg`dNF+JaTT,
+"+A23@=S~>
+!rqu=nE'dM^"*,$J^o>%n^Rc<eYL`kn^Rp%e]#MX`CdMonE'htpA^Z,rrMi<qrRlVJcC<$\GuHg
+"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@nEpO&XPVgae_]0\joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9:joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9:joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;
+joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;jp9i+k+pk0k+pl5joF9;joF9;joF9;
+joOo4rn[aY@_LpnmK52>S12__!h?&@qsFG^JcC<$\GuHo"#6UA.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.nEpO$WnPnHcIU_KhI,'og>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:[og>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?hIbKug>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:PWg7d5og>:Q?g>:Q?
+g>:Q?g>:iKk2+\;g9+_mhXKq8H-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3b/Rl8rrU3_H%GC7m]5aX
+H-4-8J,~>
+!quZ5nE'ssUt*`/`QcYYeUc9BeHDDmSCO/$ec+D1e]l@hUft.^nE'hls7W85rrVoo`V\ct;M"k!
+s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HnEp@k;U,3t!nH/aJ`_OGo]?:Xk,d^Ho&^8Hp?q)*eP_=EhXKq83Llloc2Rj@S2pK7!)eCJ
+JcE7[qsFPHS>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2nEpRn9Zkr;daH_#J_kt7o\K_IhPK)*o%j]4mcNB_c:ir+hXKq8IE'E<c2Rjf`dRaP!*+UM
+JcE7[qsFQ7`l_`8rrU?_I=^g;m]5aXIE'E<J,~>
+!rqu=nE'eZ9#^eS!l`F/J^o>%o[O)?eYL`ko$n''k2+Y=`CbcreaV]'c1_1-bl7_;c26W';M"k!
+s1&++jo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@nEpMSMb:)$hWFgo@HQG/hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEs.hWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Wk$$X(hWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhYuXBmcNB58nt`Xn*U94UmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'E
+Umrla~>
+!liB.nEpPPNC9Vgf%S]+g4@u9g&U"/iWdu:885BPk4%d@H-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3
+b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5nE+NSMb9eac.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1?Pc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(heQU5Jc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc2Q8nh?D0"8n+m@n)a_ks7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N'
+s7W7=~>
+!i2>Hn*UDR]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=F$!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=F$!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=F$
+s"OXSK=&>Kn*U9<S>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2n*Xr][Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-n&IS-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbpAh5>]-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-n$Vp/2U@\ZG,&XnEpC,`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<
+`l__?~>
+!rqu=n)a`?Zskb@.=ir$.0VG(K<2c:n)a_spA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0N
+J`a#q"3pQ>S:C~>
+!h?&@nF$;L"7G<r`IY^R^"L(%`QdQ5p@.JP0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d
+0nJbDm]5aX0r1<gJ,~>
+!liB.nEpMOmdfZ"b//_@J\'OG"N&=<lLOH4"*r&/@EnfR`l`T(mJp7<s+13[s823dH-4-8cMmsc
+b'AR+JaTT,"*r&/@=S~>
+!quZ5nE0`<B]e0j]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]tIg\]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJdB!f7Y]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]tLed[(Wi[`STbFnE'hls7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N'
+s7W7=~>
+!i2>Hn*Xrame6):hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVMZ&hWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\OA`hk3hWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhVRDOk2,7WmdBf;mK5J>UaaRg!i2>HqsFG^JcC<$\GuHo"$)mI.F.qpUmsGrmXaf,mK5J>
+Ua^f~>
+!m8N2n*U>LmdBB&J_kt7fA6PjlL+'BIE'E<c2Rjf`dRaP!*+UMJcE7[qsFQ7`l_`8rrU?_I=^g;
+m]5aXIE'E<J,~>
+!rqu=n)eBQk3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e^\'ae_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,A_ttoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e^`O,hUUK5k2u+#jo`m%s.%=5!VXe8joA;1s+13[s81p\c1_1-c2Rh<c%5#.k,[VHc1_1-
+J,~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HnF$;U!;?El!;?El!;?El!;;!3JaUbM"$)mI.F%koUmsIBmJp.9s+13[s823d3LllocMmsA
+S2l/gJaTT,"$)mI.=_~>
+!m8N2nEpe[o(MYJo(MYJo(MYJo(IY&JaU_L"+A23@EnfRb/Sl,mJp7<s+13[s823dIE'E<cMmsg
+`dNF+JaTT,"+A23@=S~>
+!rqu=nE0];!;?E[!;?E[!;?E[J`_OGbiT#PpA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0N
+J`a#q"3pQ>S:C~>
+!h?&@nEp;5o`"sKp4;X_m`b)$0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX
+0r1<gJ,~>
+!liB.nEp;1o`"sGnq$4[m`b)$H-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3b/Rl8rrU3_H%GC7m]5aX
+H-4-8J,~>
+!quZ5nE'`$o`"s:mXaMOk02ri`W,Y-c2Rk=s2Flt!)eCJJcE7[qrS""s7W86rrVoo`I[0&k,[VH
+`W,Y-J,~>
+!i2>HnEpe:s8U?oc.1(hc.1)=s4)\gJaU_L"$)mI.F%koUmsIBmJp.9s+13[s823d3LllocMmsA
+S2l/gJaTT,"$)mI.=_~>
+!m8N2nEph0s8U*]`lc<D`lc=$s2sVXmXafMmK7mWb$iQp!m8N2qsFGaJcC<$\GuHo"+A23@F"lS
+b/Sj\mXaf,mK7mWb$ff~>
+!rqu=nE(5"pA_hF]u@\(]u@\bs2BQOJ`b/<"3pQ>SBV!6p<EKs!)eCJJcE7[qrS"*pA^Z-rrMi<
+J`_OGX6'N/pA^Y5~>
+!h?&@nEph#s8Q8+@Tm5E@Tm7@s1R:cmed(OmJm7^mJm7RmJm7"mJm7VmJm7amJm6<md9EE0r1<g
+c2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.nEpCes8Q6t?2sp*[bCTGquH*O!!)f^!!)BR!!'\"!!)NV!!)oa!!%T<mHt(%b/Rl7rrU3_
+H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5nE(7_s8Q8+@Tm5E@Tm7@s/acIk555Gjo>DVjo>DJjo>Cojo>DNjo>DYjo>C4k3_:5`W,Y-
+c2Rk=s2Flt!)eCJJcE7[qrS""s7W86rrVoo`I[0&k,[VH`W,Y-J,~>
+!i2>HnEpggs8QO6!:K";jo>D]s/aKBmJm7MmJm7^mJm7RmJm7"mJm7VmJm6<mcNp>3Llloc2Rj@
+S2pK7!)eCJJcE7[qsFPHS>7UZrrT!d3J$ULm]5aX3LlloJ,~>
+!m8N2nEpg`s8QL1!9W;'iWK8]s/"$<mJm7MmJm7^mJm7RmJm7"mJm7VmJm6<mcNp>IE'E<c2Rjf
+`dRaP!*+UMJcE7[qsFQ7`l_`8rrU?_I=^g;m]5aXIE'E<J,~>
+!rqu=nE(7Ws8QO6!9W/#h>dQUs.mp:jo>DEjo>DVjo>DJjo>Cojo>DNjo>C4k2te.c1_1-bl7_;
+c26W';M"k!s1&++jo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@nEpCCs8R0>!<<)u!<<'"Ph#[!!!)3M!!)oa!s%cW!:9+R!;Ps^!8HoA!:B1S!:]CV!9<JI
+!/9hC0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.nEpC@s8R*<!<<)u!<<'"Oj<jl!!)3M!!)oa!s%cW!:9+R!;Ps^!8HoA!:B1S!:]CV!9<JI
+!/9hCH-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5nE'h2s8R0>!<<)u!<<'"Mp;.]!!)3E!!)oY!s%KG!:8hJ!;P[V!8HW9!:AnK!:]+N!9<2A
+!/9P;`W,Y-c2Rk=s2Flt!)eCJJcE7[qrS""s7W86rrVoo`I[0&k,[VH`W,Y-J,~>
+!i2>HnEpL=s8R0?!!rQ(!!rT(!K5M*mf*:_mf!4cmK!=UrW)rcr;cc`rW!#f!:KgdrpKacq<n1]
+s6fgcs6fjd!:KdcqX4:^rpK^bqX4:^s6fjd!:KdcrpBdemf!4cmem.cmem.bmK<OX!:K:R!;l0e
+!:K7Tmf!4dmK3IW!!*#d!!*#d!<DQe!/BnD3Llloc2Rj@S2pK7!)eCJJcE7[qsFPHS>7UZrrT!d
+3J$ULm]5aX3LlloJ,~>
+!m8N2nEpX;s8R*=!!E9)!!N<$!JShrmf*:_mf!4cmK!=UrW)rcr;cc`rW!#f!:KgdrpKacq<n1]
+s6fgcs6fjd!:KdcqX4:^rpK^bqX4:^s6fjd!:KdcrpBdemf!4cmem.cmem.bmK<OX!:K:R!;l0e
+!:K7Tmf!4dmK3IW!!*#d!!*#d!<DQe!/BnDIE'E<c2Rjf`dRaP!*+UMJcE7[qsFQ7`l_`8rrU?_
+I=^g;m]5aXIE'E<J,~>
+!rqu=nE'q-pA]46!!rQ("UP/.p4LWek5PGWk5GA[joGJErW)r[r;ccXrW!#^!9X7\roX1[q<%VU
+s5s7[s5s:\!9X4[qW@_VroX.ZqW@_Vs5s:\!9X4[roO4]k5GA[k5>;[k5>;Zjob\H!9WGB!;km]
+!9WDDk5GA\joYVG!!*#\!!*#\!<D9]!/BV<c1_1-bl7_;c26W';M"k!s1&++jo`m%s.%@6!VXch
+k(2Zqjo`m%s."T~>
+!h?&@nEpI,s8R0?s8;rrrrIJsqX4=_r9b0tmd:&Tmd:&Tmd:)CmJm7TmK!.P%KPqb!!)HT!:K7T
+md:&TqsOIas6]jeqsFOdmd:)PmJm7]mK3IWmK!"L!!)oa!!)oa%KPqb!!)HT!:K7T!:K7TqsFgl
+md:&Tmd:&Tmd:)PmL]HemJm7TmJu\C!!)Ee!:K7TrpBjgmd:(/mK52>S12__!h?&@qsFG^JcC<$
+\GuHo"#6UA.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.nEpI&s8R*=s8;rrrrI8fqX4=_r9b0tmd:&Tmd:&Tmd:)CmJm7TmK!.P%KPqb!!)HT!:K7T
+md:&TqsOIas6]jeqsFOdmd:)PmJm7]mK3IWmK!"L!!)oa!!)oa%KPqb!!)HT!:K7T!:K7TqsFgl
+md:&Tmd:&Tmd:)PmL]HemJm7TmJu\C!!)Ee!:K7TrpBjgmd:(/mK7aW`aR-l!liB.qsFGaJcC<$
+\GuHo"*r&/@F"lS`l`RXmXaf,mK7aW`aOA~>
+!quZ5nE'mqpA]46s8;rsrrVn8c2-T%!;tsl!9WDD!9WDD!9WDDk2lXDk2l[@jphCRjo>DDjoFQ+
+!9WDD!;kpY!<;0]!;km\!9WDDqrRkYpZ;PXk2l[<jo>DYjo>DYjphCRjo>DDjoFQ+!!)0D!;kmd
+!9WDD!9WDD!9WDDqrSIjk2lXDk2l[+jo>DD!!)0D!<2*_!9WDDL#rKVs7W85rrVoo`V\ct;M"k!
+s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HnEpU(s8R0?rr<$)!<)ouF3XLJrW)udrrE&d!s%cW!<2Bg!:K7TrpBadqsFOdmd:)SmK3IW
+!!*#d!!)oa!!*#d!!)oa!s%cW!;l0a!;Gma!:K7T!;Q!^!;u6b!;l0d!:K7TrpBjgmd:)SmJm7a
+mK3IWmK!7S!!*#d!!)oa!s%cW!<2Bg!:K7TrpBjgmd:)SmK3IWmJqt/"$)mI.F%koUmsIBmJp.9
+s+13[s823d3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2nEpU"qYtR8rr`<)!<)ouD9hqErW)udrrE&d!s%cW!<2Bg!:K7TrpBadqsFOdmd:)SmK3IW
+!!*#d!!)oa!!*#d!!)oa!s%cW!;l0a!;Gma!:K7T!;Q!^!;u6b!;l0d!:K7TrpBjgmd:)SmJm7a
+mK3IWmK!7S!!*#d!!)oa!s%cW!<2Bg!:K7TrpBjgmd:)SmK3IWmJqt/"+A23@EnfRb/Sl,mJp7<
+s+13[s823dIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=nE($lpA]46rr<$)!<3!"p1hkIk5GA\k5PG\joYVGjoGDC!s%KG!<2*\!;km\!9WDDroO:_
+jo>D\jo>DYjo>D\jo>DYjoYVGjoG;@!!)cU"9@TH!!)fVrrDuZ!!)oY!s%KG!<2*_!9WDDroO1\
+qrRt\k2l[Cjo>D\jo>DYjoYVGjoGDC!s%KG!<2*_!9WDDroO:_k2lYtjo`m%s.%=5!VXe8joA;1
+s+13[s81p\c1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@nEpEgs8R0?qZ-Wq!FjUQmf*7eme["amJm7dmK3IWmK!7S!!)oa!s%cW!<2Be!:K^aqsFFa
+rpBadrpK^bs6]jerpK^bqX4:^rpKacq<n4^rpBadrpK^bs6]jerpBjgmd:)SmJm7dmem.cmJm7d
+mJm7dmJm7amK3IWmK!7S!s%cW!<2Bg!:K7TrpBjgmd:(/mK52>S12__!h?&@qsFG^JcC<$\GuHo
+"#6UA.F.qpS>7ljmXaf,mK52>S1/s~>
+!liB.nEpEbqYtR8qZ-Zr!qopFp?qq\!:K^as6]jerpBjgmd:)SmJm7amK3IWmK!7S!<DQb!;l0a
+!<2Bd!<2Eb!<;He!<2Eb!;c-^!<2Ec!;Z'^!<2Bd!<2Eb!<;He!<2Bg!:K7TrpBadrpK^bs6]je
+rpBadrpBadqsFOdmd:)SmK3IWmK!7S!s%cW!<2Bg!:K7TL$f%gb/Rl7rrU3_H2I"0<It1$s1&++
+mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5nE'jWpA]46qZ-Zr!q'7:p?)AT!9X.Ys5j:]roO:_k2l[Cjo>DYjoYVGjoGDC!<D9Z!;kmY
+!<2*\!<2-Z!<;0]!<2-Z!;bjV!<2-[!;YdV!<2*\!<2-Z!<;0]!<2*_!9WDDroO1\roX.Zs5j:]
+roO1\roO1\qrRt\k2l[CjoYVGjoGDC!s%KG!<2*_!9WDDL#rKVs7W85rrVoo`V\ct;M"k!s1&++
+jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HnEpfjs8R-?!!rW)!!iT)mTS06mK3IW!!)oa!!*#d!s%cW!<2Bd!;l0d!:K7TrpBjgmJm7]
+mJm7dmK3IWmK!7S"p")Z!:K7TrpBadqsFFarpBadr9jRbq!S.^s6]shmd:)SmK3IWmK!7S!s%cW
+!<2Bg!:K7TrpBjgmd:)SmJm7dmJm7amK3IWmK!7S!s%cW!<2Bg!:K7TrpBjgmd:(/mK5J>UaaRg
+!i2>HqsFG^JcC<$\GuHo"$)mI.F.qpUmsGrmXaf,mK5J>Ua^f~>
+!m8N2nEpfepA]+8!!N?%!!E<%l;c.&mK3IW!!)oa!!*#d!s%cW!<2Bd!;l0d!:K7TrpBjgmJm7]
+mJm7dmK3IWmK!7S"p")Z!:K7TrpBadqsFFarpBadr9jRbq!S.^s6]shmd:)SmK3IWmK!7S!s%cW
+!<2Bg!:K7TrpBjgmd:)SmJm7dmJm7amK3IWmK!7S!s%cW!<2Bg!:K7TrpBjgmd:(/mK7mWb$iQp
+!m8N2qsFGaJcC<$\GuHo"+A23@F"lSb/Sj\mXaf,mK7mWb$ff~>
+!rqu=nE(6Zmf.>.!!rW)!!iT)k#0IsjoYVG!!)oY!!*#\!s%KG!<2*\!;km\!9WDDroO:_jo>DU
+jo>D\joYVGjoGDC"p!fJ!9WDDroO1\qrRkYroO1\r9""Zpu_SVs5jC`k2l[CjoYVGjoGDC!s%KG
+!<2*_!9WDDroO:_k2l[Cjo>D\jo>DYjoYVGjoGDC!s%KG!<2*_!9WDDroO:_k2lYtjo`m%s.%=5
+!VXe8joA;1s+13[s81p\c1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@nEpHPs8R]O!<)rt!!E8`9%Eh,!!)ucrrE)e!!)oa!!*#d#6=2[!:K7T!;l0d!:K7TrpBjg
+md:)LmKWa[mJm7TmK!7S"p")Z!:K7TrpBadqsFFarpBadqsFFap[/4cmd:)CmK!7S!s%cW!<2Bn
+!:K7Tmd:&Tmd:)SmK3IWmK!7S"9@lX!!)oa!s%cW!<2Bu!:K7Tmd:&Tmd:)CmJm7TmJqt/"#6UA
+.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9UbRGgJaV%Us7ZKTr9aRIr9aRIrpKgK!oEYEnEpB5
+Umrla~>
+!liB.nEpHNo)F7@!<)rt!!E8X8C%,#!!)ucrrE)e!!)oa!!*#d#6=2[!:K7T!;l0d!:K7TrpBjg
+md:)LmKWa[mJm7TmK!7S"p")Z!:K7TrpBadqsFFarpBadqsFFap[/4cmd:)CmK!7S!s%cW!<2Bn
+!:K7Tmd:&Tmd:)SmK3IWmK!7S"9@lX!!)oa!s%cW!<2Bu!:K7Tmd:&Tmd:)CmJm7TmJqt/"*r&/
+@EnfR`l`T(mJp7<s+13[s823dH-4-8cMmscb'AR+JaV%U(@pnMio]7_io]7_io]7_io]7_io8\_
+n*U:'b/Rk?~>
+!quZ5nE'm?mf.n>!<)rt!!E8O6-];h!!)u[rrE)]!!)oY!!*#\#6<oK!9WDD!;km\!9WDDroO:_
+k2l[<jp(nKjo>DDjoGDC"p!fJ!9WDDroO1\qrRkYroO1\qrRkYpZ;Y[k2l[+joGDC!s%KG!<2*f
+!9WDDk2lXDk2l[CjoYVGjoGDC"9@TH!!)oY!s%KG!<2*m!9WDDk2lXDk2l[+jo>DDjoC+t"3(<6
+Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2BQOJ`bJEs6fpD'B\06hWE\WhWE\WhWE\WhVQfN
+mdT?@`W,Y-J,~>
+!i2>HnEpEFme6ASqtC'X!p2enqsO=]rU0Uas6]jerpBadrpKdd!U]sbmf*7fmK!7S!!*#dr;c]^
+rr</h!:K:P!!DWh!:K^ar9jF^!:KdcqX4:^rpKdd!:K^a!U]semJm7dmf*7hmJu\CqZ$Zb!<)?c
+!!2KfqsFOdmd:)SmK*CVmem.bmf!1imJu\C!!%cA"$)mI.F%koUmsIBmJp.9s+13[s823d3Lllo
+cMmsAS2me@JPrUJ!9X.Gs5s=K$f:%&k2,7Wk2,7Wk5O3=k2,h$mK5J>Ua^f~>
+!m8N2nEpEEk3h[2rpC$^mdB5shE]B`me["_mem.cmJm7dmJm7dmf*7fmK!.Prr<)f!<2Bd!<2Eb
+!;c-`!!DWhmdBrP"7?-hme["^meZtamem.^mem.bmf*7emeZtbmK!7S!!*#drr</h!:K:P!!2Kf
+rU0[c!U]sbmK3IWmK!7S!W_ZVr;cibrW!,i!:K7T!/BnDIE'E<c2Rjf`dRaP!*+UMJcE7[qsFQ7
+`l_`8rrU?_IBW'i<NT7$k5+KHhW"Osp"BT#g=kQ?o'l&LIE'E<J,~>
+!rqu=nE'j>hWEtoroOIRk2tOWeNqIWk5,/Wk5>;[jo>D\jo>D\k5PD^joG;@rr<)^!<2*\!<2-Z
+!;bjX!!D?`k2uO@"6KR`k5,/Vk5,,Yk5>;Vk5>;Zk5PD]k5,,ZjoGDC!!*#\rr</`!9WG@!!23^
+rT=+[!TjCZjoYVGjoGDC!W_BFr;ciZrW!,a!9WDD!/BV<c1_1-bl7_;c26W';M"k!s1&++jo`m%
+s.%@6!VXdAk(-F4;YfJRh>l^/eH4UXmdT?@c1_1-J,~>
+!h?&@nEp9:rT=(Hrq6H^p+b*Kmapk,!.jS4mK52>S12__!h?&@qsFG^JcC<$\GuHo"#6UA.F.qp
+S>7mCmJp.9m]PsXk54THhZ)a;mL\OKk3hC"k3hC"k2tO_hWE\amK52>S1/s~>
+!liB.nEp95rn\%Bk3D6olL+**l86e;mapk,!.jS4mK7aW`aR-l!liB.qsFGaJcC<$\GuHo"*r&/
+@F"lS`l`S1mJp7<m]PsXk54THgAg"Ck3D*gk2PO_k2PO_k2P7Og=G-3nEpC(b/Rk?~>
+!quZ5nE'^*rRD8;hWE\Wk3hBo1!P:3fB*&5J`c^h"3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-
+cMmt>s2D2(!)eC1Vrn$0s5*b;$Jsq%k2,7Wk2,7Wqpk2u"3(<6Ujr~>
+!i2>HnEp:/oJ$AMeUd/Jmf!4^mJm6<me?,O3Llloc2Rj@S2pK7!)eCJJcE7[qsFPHS>7UZrrT!d
+3NqiN;M"8=mJuDHmf2,Ek2,^t!9X7:!7gT,"$)mI.=_~>
+!m8N2nEp:-oIp;Kc@PECmf!4^mJm6<me?,OIE'E<c2Rjf`dRaP!*+UMJcE7[qsFQ7`l_`8rrU?_
+IBW&=<IsS@mJuDHmf1l<g@OG1hU^E3g=#KY"+A23@=S~>
+!rqu=nE'au.K2%%.K2%%.K2%'.9auIk2PP&!;YaW!.j;,jo`m%s.%=5!VXe8joA;1s+13[s81p\
+c1_1-c2Rh<c*-70;M!u.k5Ej.joF99joaK&k2-'e!6t#q"3pQ>S:C~>
+!h?&@n*U\BUm-e%Mj0-aMj0-aUu$[jJaUbM"#6UA.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9
+UbT(@!)eC9Y3l;PqsFI/rn[Y;rpBdKr9aRIrpKgK"4c8beaVu/0r1<gJ,~>
+!liB.n*U51V=olLV:pLgJaUbM"*r&/@EnfR`l`T(mJp7<s+13[s823dH-4-8cMmscb'C2Y!*+U<
+Y3l;PqsFU0f%/R7o]?>:g="R'b4+g$H-4-8J,~>
+!quZ5n)aZ$V"T]IUt(%YJ`b2="3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2D2(!)eC1
+Vref7e]lY$k2,7Wk2,7Wk2,7Wk2+Y-e]l)&jo`U&p8!3~>
+!i2>HnEpDPmbZ4feH!kneH=(He_YlFJaU_L"$)mI.F%koUmsIBmJp.9s+13[s823d3LllocMmsA
+S2me@!)eC9Y3l;PqsFI/rnd\;qX+C/`Vo3-k2+YF`UN9t3LlloJ,~>
+!m8N2nEphXlIsP3cI1"dcI1"dcJ%Q7mXafMmK7mWb$iQp!m8N2qsFGaJcC<$\GuHo"+A23@F"lS
+b/Sk5mJp7<m]PsXk54QL_Ud/diq_^<b.?U3jojPhdb;S-mK7mWb$ff~>
+!rqu=nE'f?k101M!7cY_J`b/<"3pQ>SBV!6p<EKs!)eCJJcE7[qrS"*pA^Z-rrMi<YN>g_J``lm
+#JJ[4c/.=>hYuXGhWDejk2tO_e]l@h^$t.dc1_1-J,~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@YO2BgJaT]/!9X1H(VS\M
+e`Q;^mcNs"k/HKNc0"HVk1/#=^$tFl0r1<gJ,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.YO2BjJaT]/!9X1H(Uho?
+dba-Gk2PO_g;`"3`o?.?hTjEt](#+iH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5YN>g_J``lm(Tc0+c.1\-
+k2,7WhSn@6`STb6hSmaa[.*2[`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HYO2BgJaT]/!9X1H$aed@
+e\05P`P(Eaec+tBc/.mVk1.`5[.*Jc3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2YO2BjJaT]/!9X1H"Kp1q
+cF3_l&%:KCcKai_b1>S3hTj9pY41i]IE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<Bf'!)eC1Vre,`c,IZ/rl"uH
+hTa=EmKge^hWEA5`RUdRjo`m%s."T~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@YO2BgJaT]/!9X1H&>[jq
+e[4JqhT`arp@dqBk.UcVs31SpV"!dS0r1<gJ,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.YO2BjJaT]/!9X1H(S0!o
+cE?0\f#G;Xo'YZ&ik!k#hTEj`U%%IPH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5YN>g_J``lm%%PSU`N7qQ
+e]#5YmdC):#JJ[Ee]#MPSFGYC`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HYO2BgJaT]/!9X1H$(TPj
+c+WQ-e]mO]pAaOdhSmIre^_ppPjn)C3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2YO2BjJaT]/!9X1H(R<Fg
+b-L0dcH>SGmcs*"g:k;Xf#l"\Omqc@IE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<Bf'!)eC1Vre8Lc,IZ'mbZ4-
+rU0^J#i<8.e]l(Hc&;)R"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@YO2BgJaT]/!9X1H#E.-O
+c*ZohhY[!M`N6bS[&!]G!/p@7"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.YO2BjJaT]/!9X1H(Q$SW
+b-L0Pf'`+so'YqWWj\q1S]8[pM=Bp8H-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5YN>g_J``lm#D::7`N84H
+ebeb<]r\T:XIT:/!/'e'"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HYO2BgJaT]/!9X1H#E.-W
+c*Zo`^&?1``O)_[[(W9*c,J4cnEpB=S>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2YO2BjJaT]/!9X1H$%^CA
+`ieIH]#r%l_@!TF]!Ac8Q--tlJai(0IE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<Bf'!)eC1Vre8;c,IZ'k0:9X
+rP\f=V#I_)Um/j3c$SsB"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@YO2BgJaT]/!9X1H$[^FC
+c*ZoG^"(ZXc2PZf[&g'UXNe`7HgpG*0r1<gJ,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.YO2BjJaT]/!9X1H(Nn$?
+b-'m4[a*=D`kK$uY,\%HWlDp$H1:5(H-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5YN>g_J``lm#BS/'`N84/
+[/S;M`W!RNX9P2AXM)<dF7A;o`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HYO2BgJaT]/!9X1H%s-:G
+c)g'/k2u*gc+UK[SGnEL`QcBPF7AT"3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2YO2BjJaT]/!9X1H%ron3
+`iA$pio9+S`k&=HQ2ZUC]#qn<D=HrqIE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<Bf'!)eC1Vrdtorl"r?hPC/5
+"kCT!XJD*[K*8R#^!1<]jo`m%s."T~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@YO2BgJaT]/!9X1H(Lkq6
+c)f1'ma]k,[&fd^Mh?qPe]#e`C@LWn0r1<gJ,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.YO2BjJaT]/!9X1H(Lbb/
+`i@1ilI*hlZDEtKKn5)Cb/V<DAao*iH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5YN>g_J``lm(LkY&`N7%c
+k1._i[%rqEK6r68`P&t(@drL^`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HYO2BgJaT]/!9X1H(Lkq>
+c)e;&k0:TQ[%rq=K8YA`hTa$i@drdf3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2YO2BjJaT]/!9X1H(L>>+
+`i?>ig<."<Y+^i3Kn4rKf#kkX?1@7aIE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<Bf'!)eC1Vree!c,IAt[*@IP
+]sOl2P_4U8K:L3*^!0aMjo`m%s."T~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@YO2BgJaT]/!9X1H(K/f&
+c(q`'k2+A-`O)G:S=GMEhTa<q>4Cq^0r1<gJ,~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.YO2BjJaT]/!9X1H(KJo'
+b+5ihhU]uh^94<+SX#&7f#G_T<UfDYH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5YN>g_J``lm(K/Mk`LO$[
+hUTli]r\$"S<Sr5e\/rH;XifN`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HYO2BgJaT]/!9X1H$W>O*
+c'5p0me6)2k5O3Ce]jW/hUTm-9(;6N3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2YO2BjJaT]/!9X1H(JN9"
+b)s:'lL*fshV-Q/cH;Qlf#l.d9^qHPIE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<Bf'!)eC1Vre.Tc,IY[^&@@.
+k2+tFe]l@/^!4g@eOo>n"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@YO2BgJaT]/!9X1H"[V"i
+eVhuUmf2DRhUTlqPht9reGr52mK52>S1/s~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.YO2BjJaT]/!9X1H"[pqe
+b)+RGl437IinDi+b/TRtg<S!l7.BUHH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5YN>g_J``lm(I?<b`IlFt
+mcNs"k2+Y5c,Gpte]#eX61F"=`W,Y-J,~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HYO2BgJaT]/!9X1H"]EV%
+eVg7&XT,*pSH"fXUupOje^[:]mK5J>Ua^f~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2YO2BjJaT]/!9X1H#>E.g
+cAA6kV>d.sSXGb*Obodgg="El7.BUHIE'E<J,~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<Bf'!)eC1Vre+S`QcASr1s@_
+rfmG@#+XQ#c-=3nnE'htpA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@YO2BgJaT]/!9X1H!FiG8
+ebe2'k5='?k2,7WhQ0WEmK52>S1/s~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.YO2BjJaT]/!9X1H!F`#-
+df7l!g=H8W!nQ)Vrn7P4g=FiT;"3lTH-4-8J,~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5YN>g_J``lm!Eu;ublcM@
+e]n*D!mT9?r7(noeYH+4jo`U&p8!3~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HYO6u(XQKEJ!fK\$rn\7L
+hWE\WhWE\WhWE\_k2t2l@drdf3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2YO6u(XQKEJ!ej=jrmpbr
+"leCmc:h[9mK7mWb$ff~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`bJE"bTFdc.1)3ec4J.
+e]guqnE'htpA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*We*[<Z6*/?1h>l+(
+h>l+*h?E&uX@cCanEpB5Umrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*We*[<X5c)Kmecjp]
+Y!c+WnEpC(b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGe)h0^6);KMc.1(h
+c.1(hc.1)<eH;U5;XX&:"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WeF*A1!fKZ*r[@h%
+r$_V#r[Ik%"$pDip@.JP3LlloJ,~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WeF"+CmY+1c-nHbt
+-nHbt-nHbt-nI&;@IimT"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`bJEs6]r@8hood">N2G
+mdBT,"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HnF$;U!;?El!;?El!;?El!;;!3JaUbM"$)mI.F%koUmsIBmJp.9s+13[s823d3LllocMmsA
+S2l/gJaTT,"$)mI.=_~>
+!m8N2nEpe[o(MYJo(MYJo(MYJo(IY&JaU_L"+A23@EnfRb/Sl,mJp7<s+13[s823dIE'E<cMmsg
+`dNF+JaTT,"+A23@=S~>
+!rqu=nE0];!;?E[!;?E[!;?E[J`_OGbiT#PpA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0N
+J`a#q"3pQ>S:C~>
+!h?&@nEp;5o`"sKp4;X_m`b)$0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX
+0r1<gJ,~>
+!liB.nEp;1o`"sGnq$4[m`b)$H-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3b/Rl8rrU3_H%GC7m]5aX
+H-4-8J,~>
+!quZ5nE'`$o`"s:mXaMOk02ri`W,Y-c2Rk=s2Flt!)eCJJcE7[qrS""s7W86rrVoo`I[0&k,[VH
+`W,Y-J,~>
+!i2>HnEpe:s8U?oc.1(hc.1)=s4)\gJaU_L"$)mI.F%koUmsIBmJp.9s+13[s823d3LllocMmsA
+S2l/gJaTT,"$)mI.=_~>
+!m8N2nEph0s8U*]`lc<D`lc=$s2sVXmXafMmK7mWb$iQp!m8N2qsFGaJcC<$\GuHo"+A23@F"lS
+b/Sj\mXaf,mK7mWb$ff~>
+!rqu=nE(5"pA_hF]u@\(]u@\bs2BQOJ`b/<"3pQ>SBV!6p<EKs!)eCJJcE7[qrS"*pA^Z-rrMi<
+J`_OGX6'N/pA^Y5~>
+!h?&@nEph#s8Q8+@Tm5E@Tm7@s1R:dmJm7bmJm7SmJm7QmJm7?mJm7EmJm7TmK*CVmf!4EmK3IW
+mK!.P!!&>Q"#6UA.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.nEpCes8Q6t?2sp*[bCWH!!)rb!!)ES!!)?Q!!(^?!!(pE!!)HT!W_ZVrW(mE!s%cW!;l0a
+!1*$TH-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5nE(7_s8Q8+@Tm5E@Tm7@s/acJjo>DZjo>DKjo>DIjo>D7jo>D=jo>DLjoPPFk5GA=joYVG
+joG;@!!&>I"3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HnEpggs8QO6!:K";jo>D]s/aKBmJm7bmJm7SmJm7QmJm7?mJm7.mJm7AmJm7amJm6QmK5J>
+UaaRg!i2>HqsFG^JcC<$\GuHo"$)mI.F.qpUmsGrmXaf,mK5J>Ua^f~>
+!m8N2nEpg`s8QL1!9W;'iWK8]s/"$<mJm7bmJm7SmJm7QmJm7?mJm7.mJm7AmJm7amJm6QmK7mW
+b$iQp!m8N2qsFGaJcC<$\GuHo"+A23@F"lSb/Sj\mXaf,mK7mWb$ff~>
+!rqu=nE(7Ws8QO6!9W/#h>dQUs.mp:jo>DZjo>DKjo>DIjo>D7jo>D&jo>D9jo>DYjo>CIjo`m%
+s.%=5!VXe8joA;1s+13[s81p\c1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@nEpCCs8R0>!<<)u!<<'"Ph#[!!!)rb!!)ES!!)rb!s%cW!;,[Z!86c?!6FR.!8HoA!;l0a
+!1*$T0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.nEpC@s8R*<!<<)u!<<'"Oj<jl!!)rb!!)ES!!)rb!s%cW!;,[Z!86c?!6FR.!8HoA!;l0a
+!1*$TH-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5nE'h2s8R0>!<<)u!<<'"Mp;.]!!)rZ!!)EK!!)rZ!s%KG!;,CR!86K7!6F:&!8HW9!;kmY
+!1)aL`W,Y-c2Rk=s2Flt!)eCJJcE7[qrS""s7W86rrVoo`I[0&k,[VH`W,Y-J,~>
+!i2>HnEpL=s8R0?!!rQ(!!rT(!K5M*mJm7bmK*CVmem.amf!4_mK<OXmJu\P!!)Hc!<)?a!;l3_
+!<2Bg!:BgerU0XbrU0XbrU0Ua!q$'VrW)i`r;cfarW)rc!<DQe!<2Bf!:Bjdmem.cmf!4_mK!=U
+rW)la!s%`h!<)?a!<2Eb!<2Eb!<2Bj!:K7TmJm7dmJm7dmf!3VmK5J>UaaRg!i2>HqsFG^JcC<$
+\GuHo"$)mI.F.qpUmsGrmXaf,mK5J>Ua^f~>
+!m8N2nEpX;s8R*=!!E9)!!N<$!JShrmJm7bmK*CVmem.amf!4_mK<OXmJu\P!!)Hc!<)?a!;l3_
+!<2Bg!:BgerU0XbrU0XbrU0Ua!q$'VrW)i`r;cfarW)rc!<DQe!<2Bf!:Bjdmem.cmf!4_mK!=U
+rW)la!s%`h!<)?a!<2Eb!<2Eb!<2Bj!:K7TmJm7dmJm7dmf!3VmK7mWb$iQp!m8N2qsFGaJcC<$
+\GuHo"+A23@F"lSb/Sj\mXaf,mK7mWb$ff~>
+!rqu=nE'q-pA]46!!rQ("UP/.p4LWejo>DZjoPPFk5>;Yk5GAWjob\HjoFQ@!!)0[!<)'Y!;kpW
+!<2*_!9O7]rT=(ZrT=(ZrT=%Y!p0LFrW)iXr;cfYrW)r[!<D9]!<2*^!9O:\k5>;[k5GAWjoGJE
+rW)lY!s%H`!<)'Y!<2-Z!<2-Z!<2*b!9WDDjo>D\jo>D\k5G@Njo`m%s.%=5!VXe8joA;1s+13[
+s81p\c1_1-c2Rh<c%5#.k,[VHc1_1-J,~>
+!h?&@nEpI,s8R0?s8;rrrrIJsqsFFar9aXemd:)PmK<OXmJm7amL0*`!!)HT!:K7Tmd:)Pmf*:e
+mJm7amJm7amf*8$mJm7TmJu\C!!)HT!:K7T!:K7T!<)?c!<;He!;l0a!;l0l!:K7T!:K7T!:K7T
+rpBsjmJu\C!!)uc"9@lX!!)oa!s%cW!;l3a!"J>r!:K7T!:K7T!:K7TqsFFaqsG$rmd:&TmJm7T
+mJu\C!:K7T!1iN[0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.nEpI&s8R*=s8;rrrrI8fqsFFar9aXemd:)PmK<OXmJm7amL0*`!!)HT!:K7Tmd:)Pmf*:e
+mJm7amJm7amf*8$mJm7TmJu\C!!)HT!:K7T!:K7T!<)?c!<;He!;l0a!;l0l!:K7T!:K7T!:K7T
+rpBsjmJu\C!!)uc"9@lX!!)oa!s%cW!;l3a!"J>r!:K7T!:K7T!:K7TqsFFaqsG$rmd:&TmJm7T
+mJu\C!:K7T!1iN[H-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5nE'mqpA]46s8;rsrrVn8c26W'!;ts]!9WDDqrS"]k2lXDqrS:ejo>DDjoFQ+!9WDDqr[nY
+s5j:]qrRkYqr[nY']oAqk2l[+jo>DDjoFQ+!!)0D!!)u[rrE)]!!)oY!!)oY$NT>O!!)0D!!)0D
+!<2*b!9O:Djo>D[job\Hjo>DYjoYVGjoG;@rr<Mj!!)0D!!)0D!!)0D!;kmY!;kmj!9WDD!9O7]
+k2l[+joFQ+!!&SP"3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HnEpU(s8R0?rr<$)!<)ouF3XUM!!)rb"9@lX!!)ucrrE&d!!)oa!W_WgrpC!kmd:)CmJm7b
+mJm7dmJm7amf*:bmJm7dmK3IW!!*#d!s%`h!<2Bg!:K7Tr9aObrpBadqsOIarU0[crpBjgmd:)S
+mKim]mJu\C!:K7TrU0[crpBadqsFOdmd:)PmJm7dmK3IWmK!4R"9@lX!!)rbrrDub!s%cW!<2Bj
+!:K7TmJm7dmJm6XmK5J>UaaRg!i2>HqsFG^JcC<$\GuHo"$)mI.F.qpUmsGrmXaf,mK5J>Ua^f~>
+!m8N2nEpU"qYtR8rr`<)!<)ouD9i%H!!)rb"9@lX!!)ucrrE&d!!)oa!W_WgrpC!kmd:)CmJm7b
+mJm7dmJm7amf*:bmJm7dmK3IW!!*#d!s%`h!<2Bg!:K7Tr9aObrpBadqsOIarU0[crpBjgmd:)S
+mKim]mJu\C!:K7TrU0[crpBadqsFOdmd:)PmJm7dmK3IWmK!4R"9@lX!!)rbrrDub!s%cW!<2Bj
+!:K7TmJm7dmJm6XmK7mWb$iQp!m8N2qsFGaJcC<$\GuHo"+A23@F"lSb/Sj\mXaf,mK7mWb$ff~>
+!rqu=nE($lpA]46rr<$)!<3!"p1hkLjo>DZjob\Hjo>D[k5PG\jo>DYjoPPF!<2*c!9WDDk2lXD
+r8mtZroO1\qr[nYr8mtZroO:_jo>D\joYVG!!*#\!s%KG!;tsZ!<2*\!;kpY!<)'[!<2*_!9WDD
+roOLek2l[+joFQ+!<)'[!<2*\!;km\!9WDDqrRkYroO:_k2l[Bjob\Hjo>DZk5PGZjoYVGjoGDC
+"p!fJ!9O7]roO1\S`U%!pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@nEpEgs8R0?qZ-Wq!FjUVmJm7bmJm7dmf!4dme["]mf*:cmK3IWmK!7SrW)rc!!*#d!!)l`
+rW)rc!!*#d!<DQb!!)Ha!<;He!;u6b!<2Bd!;c-_!<;Ka!<;He!<2Ed!!holmd:)CmK!4RqZ-N]
+!s%cW!;l0a!<2Bg!:K7TrU'XcrpKacrU0XbrpBjgmd:)SmK<OXmJu\P!1iN[0r1<gc2Rj8UbVc7
+!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.nEpEbqYtR8qZ-Zr!qopFqsFFar9aObrpKacs6faaqsOIarU'afmd:)Smf!4cmJm7dmJm7`
+mf!4cmJm7dmK!=UqZ$WaqZ-Za!!)rb!!*#d!!)l`rW)udqZ-Za!!*#drr<;l!:K7Tmd:)Rme["]
+mK3IWmK!.P!!*#d!s%cW!<)<c!<2Ec!<)?b!<2Bg!:K7TrpBmhmd:)CqZ*2T"*r&/@EnfR`l`T(
+mJp7<s+13[s823dH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5nE'jWpA]46qZ-Zr!q'7:qrRkYr8mtZroX1[s5s1Yqr[nYrT41^k2l[Ck5GA[jo>D\jo>DX
+k5GA[jo>D\joGJEqZ$WYqZ-ZY!!)rZ!!*#\!!)lXrW)u\qZ-ZY!!*#\rr<;d!9WDDk2l[Bk5,/U
+joYVGjoG;@!!*#\!s%KG!<)$[!<2-[!<)'Z!<2*_!9WDDroO=`k2l[+qZ*2L"3(<6Us8o@pA`,/
+joA;1s+13[s81p\`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HnEpfjs8R-?!!rW)!!iT)mTS0<mJm7bmJm7bmf*7gmJm7]mK*CV!<2Bg!:K7Tr9jRbs6]je
+rpBadq!S.^s6]jerpBjgmJm7bmf*:amJm7bmJm7dmJm7^mf*7gmJm7amJm7cmK`g\!:K7Tmd:)R
+mf*:]mK3IWmK!.P!!*#d!s%cW!<)<c!;u9b!;u9b!<;Hh!:K7TrpBsjmd:)C!!&GT"$)mI.F%ko
+UmsIBmJp.9s+13[s823d3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2nEpfepA]+8!!N?%!!E<%l;c.,mJm7bmJm7bmf*7gmJm7]mK*CV!<2Bg!:K7Tr9jRbs6]je
+rpBadq!S.^s6]jerpBjgmJm7bmf*:amJm7bmJm7dmJm7^mf*7gmJm7amJm7cmK`g\!:K7Tmd:)R
+mf*:]mK3IWmK!.P!!*#d!s%cW!<)<c!;u9b!;u9b!<;Hh!:K7TrpBsjmd:)C!!&GT"+A23@EnfR
+b/Sl,mJp7<s+13[s823dIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=nE(6Zmf.>.!!rW)!!iT)k#0J$jo>DZjo>DZk5PD_jo>DUjoPPF!<2*_!9WDDr9""Zs5j:]
+roO1\pu_SVs5j:]roO:_jo>DZk5PGYjo>DZjo>D\jo>DVk5PD_jo>DYjo>D[jp1tL!9WDDk2l[B
+k5PGUjoYVGjoG;@!!*#\!s%KG!<)$[!;u!Z!;u!Z!<;0`!9WDDroOCbk2l[+!!&GL"3pQ>SBV!6
+p<EKs!)eCJJcE7[qrS"*pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@nEpHPs8R]O!<)rt!!E8`9%Eh,rrE&drrDra!s%cW!;Gmf!:K7Tmd:)CmK!.P#6=2[!:K7T
+!;Gmg!:K7Tmd:&Tmd:)PmJm7amf*:cmJm7dmJm7]mK3IWmK!.P!!)ucrrE&d"9@lX!!)uc!!)c]
+!s%cW!;l0m!:K7T!:K7T!:K7T!;l0a!;l0q!:K7Tmd:)CmJm7TmJu\C!1E6W0r1<gc2Rj8UbVc7
+!)eCJJcE7[qsFP@UmrmZrrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.nEpHNo)F7@!<)rt!!E8X8C%,#rrE&drrDra!s%cW!;Gmf!:K7Tmd:)CmK!.P#6=2[!:K7T
+!;Gmg!:K7Tmd:&Tmd:)PmJm7amf*:cmJm7dmJm7]mK3IWmK!.P!!)ucrrE&d"9@lX!!)uc!!)c]
+!s%cW!;l0m!:K7T!:K7T!:K7T!;l0a!;l0q!:K7Tmd:)CmJm7TmJu\C!1E6WH-4-8c2Rjbb'EmP
+!*+UMJcE7[qsFQ3b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5nE'm?mf.n>!<)rt!!E8O6-];hrrE&\rrDrY!s%KG!;GU^!9WDDk2l[+joG;@#6<oK!9WDD
+!;GU_!9WDDk2lXDk2l[@jo>DYk5PG[jo>D\jo>DUjoYVGjoG;@!!)u[rrE&\"9@TH!!)u[!!)cU
+!s%KG!;kme!9WDD!9WDD!9WDD!;kmY!;kmi!9WDDk2l[+jo>DDjoFQ+!1DsO`W,Y-c2Rk=s2Flt
+!)eCJJcE7[qrS""s7W86rrVoo`I[0&k,[VH`W,Y-J,~>
+!i2>HnEpEFme6ASqtC'X!p2enqX47]rpK^brU0UaqsFglmd:&TmJm7T!!)Hc!<)?c!!2KfqsOC_
+rpK^brU0UarpK^brpK^b!U]semJm7amem.amem.cmJm7cmf*:dmJm7dmem.cmem._mK3IWmK!.P
+r;cfar;cibr;cibr;cib!W_ZVr;cib!!*#dr;`DV"$)mI.F%koUmsIBmJp.9s+13[s823d3Lllo
+cMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2nEpEEk3h[2rpC$^mdB5shE]B_med(amem.amem._mL'$_mJm7T!!)Ee!:KdcrU0[c!U]sb
+mem.bmem.amem.bmem.bmem+dmK!7S!!)oar;cfar;clc!!)ucrrE&d!!*#dr;clcr;c`_!s%cW
+!;l3_!<)?a!<2Eb!<2Eb!<2Bf!:K:R!<2Bd!<2Eb!1iN[IE'E<c2Rjf`dRaP!*+UMJcE7[qsFQ7
+`l_`8rrU?_I=^g;m]5aXIE'E<J,~>
+!rqu=nE'j>hWEtoroOIRk2tOWeNqIVk555Yk5>;Yk5>;WjpM1Ojo>DD!!)-]!9X4[rT=+[!TjCZ
+k5>;Zk5>;Yk5>;Zk5>;Zk5>8\joGDC!!)oYr;cfYr;cl[!!)u[rrE&\!!*#\r;cl[r;c`W!s%KG
+!;kpW!<)'Y!<2-Z!<2-Z!<2*^!9WGB!<2*\!<2-Z!1i6Sc1_1-bl7_;c26W';M"k!s1&++jo`m%
+s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@nEp9:rT=(Hrq6H^p+b+0mJm6amJm6<mdKQG0r1<gc2Rj8UbVc7!)eCJJcE7[qsFP@UmrmZ
+rrS^d0nJbDm]5aX0r1<gJ,~>
+!liB.nEp95rn\%Bk3D6olL+**l86eumJm6amJm6<mdKQGH-4-8c2Rjbb'EmP!*+UMJcE7[qsFQ3
+b/Rl8rrU3_H%GC7m]5aXH-4-8J,~>
+!quZ5nE'^*rRD8;hWE\Wk3hBo1!R>m!!&nY!!%T4n)a_ks7W85rrVoo`V\ct;M"k!s1&++jo`U&
+p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HnEp:/oJ$AMebnk1!6OX/!2f/a!.jS,mK5J>UaaRg!i2>HqsFG^JcC<$\GuHo"$)mI.F.qp
+UmsGrmXaf,mK5J>Ua^f~>
+!m8N2nEp:-oIp;KcM[,*!6OX/!2f/a!.jS,mK7mWb$iQp!m8N2qsFGaJcC<$\GuHo"+A23@F"lS
+b/Sj\mXaf,mK7mWb$ff~>
+!rqu=nE'au.K2%%.K2%%.K2%'.9b!ok4equjo>CYjo>C4k3qF7c1_1-bl7_;c26W';M"k!s1&++
+jo`m%s.%@6!VXchk(2Zqjo`m%s."T~>
+!h?&@n*U\BUm-e%Mj0-aMj0-aUu$[jJaUbM"#6UA.F%koS>7n:mJp.9s+13[s823d0r1<gcMms9
+UbRGgJaTT,"#6UA.=_~>
+!liB.n*U51V=olLV:pLgJaUbM"*r&/@EnfR`l`T(mJp7<s+13[s823dH-4-8cMmscb'AR+JaTT,
+"*r&/@=S~>
+!quZ5n)aZ$V"T]IUt(%YJ`b2="3(<6Us8o@pA`,/joA;1s+13[s81p\`W,Y-cMmt>s2BQOJ`a#q
+"3(<6Ujr~>
+!i2>HnEpDPmbZ4feH!kneH=(He_YlFJaU_L"$)mI.F%koUmsIBmJp.9s+13[s823d3LllocMmsA
+S2l/gJaTT,"$)mI.=_~>
+!m8N2nEphXlIsP3cI1"dcI1"dcJ%Q7mXafMmK7mWb$iQp!m8N2qsFGaJcC<$\GuHo"+A23@F"lS
+b/Sj\mXaf,mK7mWb$ff~>
+!rqu=nE'f?k101M!7cY_J`b/<"3pQ>SBV!6p<EKs!)eCJJcE7[qrS"*pA^Z-rrMi<J`_OGX6'N/
+pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LA=;M"k!s1&++mK52>S12b`!h?&@JaS*WX6p'EUmrla~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I"0<It1$s1&++mK7aW`aR0m!liB.JaS*WX6p(8b/Rk?~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\ct;M"k!s1&++jo`U&p8$"6!quZ5J`_OGX6'N's7W7=~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3W&4E;M"k!s1&++mK5J>UaaUh!i2>HJaS*WX6p'MS>7Ta~>
+!m8N2JaS*WX6p(<`l_`7rrU?_IJ`F4<It1$s1&++mK7mWb$iTq!m8N2JaS*WX6p(<`l__?~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<qrRlVJcC<$\GuHg"3pQ>SB_'7p<A0NJ`a#q"3pQ>S:C~>
+!h?&@JaS*WX6p'EUmrmYrrS^d1&LBis+13Zs823d0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H2I#\s+13Zs823dH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`V\eKs+13Zs81p\`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@qsK#5JPrsTqsFP@UmrmYrrS^d1&LBi;Lq`T;Z#ka0r1<gcMms9UbVc7JPq%s[o3+k"#6UA
+.=_~>
+!liB.qsK#8JQ90ZqsFQ3b/Rl7rrU3_H2I#\<In/Z<Vu1dH-4-8cMmscb'EmPJQ78$[oN=n"*r&/
+@=S~>
+!quZ5qrWH-JPrsTqrS""s7W85rrVoo`V\eK;Lq`T;Z#SY`W,Y-cMmt>s2FltJPq%s[o3+c"3(<6
+Ujr~>
+!i2>HqsK%8JcE4ZqsFPHS>7UYrrT!d3W&5qs+13Zs823d3LllocMmsAS2pK7JcC<$\,Z?n"$)mI
+.=_~>
+!m8N2qsK%8JcE4ZqsFQ7`l_`7rrU?_IJ`G`s+13Zs823dIE'E<cMmsg`dRaPJcC<$\,Z?n"+A23
+@=S~>
+!rqu=qrWJ0JcE4ZqrS"*pA^Z,rrMi<qrWJ0JcE4ZqrS"*pA^Z-rrMi<qrWJ0JcE4ZqrS"*pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HqsM;oqsLibp$VeP"4a2o;Z8s=3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3W;;H;M1dqrV#^JZhF:a"$)mI.F%koUmsIBm_SVom^2]\meuh]eYIOi
+r]rA$5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4kr]pWa
+K;@&rp@%FUpA=7[3LllocMmsAS2pK7rUp?DUjH#=5q"`Z3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,\(5m(#;Ut,G;q!PN_p$TBan*[OUqsFPHS>7Ta~>
+!m8N2qsH]>mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+o'Z):o'Z):o'Z)GmS*3>o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)AmK`=No'Xr&I8IpG#>fiFddH\oo'c!@o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z)>mdff:mdff:mdg8C"+A23@EnfRb/Sl,mQ^:1o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)>mdff:mdff:mdg8C9_.WBmdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdg&=#P.<R
+ma@q[:rYU&:jo1gmdff:n*Wp@mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdfr:o'Z):o'Z):o)%hWIE'E<cMmsg`dRaP#P.<Rma@q[
+:shB1:jo1gmdff:q!LiHmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:p$P?@mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:o'Z):o'Z):o'Z);mS39?o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o()5>
+mdff:mdff:qsFQ7`l__?~>
+!rqu=qrY`_qrY9Rp#c5@"O3`h8jUT[#!k708pdAYrU0.:ZgR_Q"3pQ>SBV!6p<EKs_=%3_[-mVL
+rU'g5UjG^"auKYl3B9]YUs8l+n)gtEqrS"*pA^Z-rrMi<qr[kF"O3`h8jUuf#!k708pdAYrU0IC
+[-mVL\aJqKZgR_Q"3pQ>S:C~>
+!h?&@qX-N?me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6):
+p?qYBp?qYBpA+,Kp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYGmR['>UcC_$5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4kV!dsDmS!9Ap?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBme6)Bme6)B
+me6MF"#6UA.F%koS>7n9mQL:3p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qABme6)Bme6)Bq<glKme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme68?8G;JI3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,[$me6&99D7fI
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6):p?qYBp?qYBpA41Z0r1<gcMms9UbV`64ne<>3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3B9Ac5rh4kV!dsMmRm3@p?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp@I]@p?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBme6)Bme6)B
+me6&99D7fIme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6):p?qYBp?qYBpA41Z0r1<gJ,~>
+!liB.qX-N;mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff6
+o'Z):o'Z):o(h]Go'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z)?mK2tISbkN+3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_
+3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3'9/_3;GZ<SaQ(9mS!-=o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):mdff:mdff:mdg5B"*r&/
+@EnfR`l`T'mQL./o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):
+o'Yr:mdff:mdff:q<glGmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdfu;!qPcMq`H\p4?,G_4?,G_4?,G_4?,G_4?,G_
+4?,G_4?,G_4?,G_4?,G_4?,G_4?,G_4?,G_4?,G_q)e_Lmdfc59ChNAmdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff6o'Z):o'Z):o(qbV
+H-4-8cMmscb'EjO!qPcMq`H>f4?,G_4?,G_4?,G_4?,G_4?,G_4?,G_4?,G_4?,G_4?,G_4?,G_
+4?31"!hJcMp?kQDmdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdfu;7Iom;mdff:mdff:mdff:mdff:mdff:mdff:mdff:
+mdff:mdff:mdff:mdff:mdff:mdff:mdff:mdBZ6o'Z):o'Z)9mS!-=o'Z):o'Z):o'Z):o'Z):
+o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):o'Z):mdff:mdff:mdg5B
+"*r&/@=S~>
+!quZ5qW9s/k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBo
+mcNs"mcNs"meQ!;mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs/joXu5SA$ubSEB8,k"G.)mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"k3hC"k3hC"k3i*.
+"3(<6Us8o@pA`,.jur.pmcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcN["k3hC"k3hC"q;t<;k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hj'!q,3@^,Z7bk3hX!9CCs1k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBomcNs"
+mcNs"meZ&J`W,Y-cMmt>s2Fis!q,3@aZ0Emk3hs*9((j0k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"oB&L0k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hBomcNs"mcNs"
+md9.0mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcN["k3hC"k3hC"qW7n!s7W7=~>
+!i2>HqsOLXa8c,3qsOIWs6]mLrpBjMmcON:!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K!9X:K
+!9X:K!9X:K!9X:K!9X:K!9X:K!9X7Jr:]gOs7QPA5s[O15r^kj3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk
+3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,\)5m9876$r>!n*^5L\c;X%qsFPHS>7UY
+rrT!d3W&7Ep;d43pA=:Xp:C;&p@[kRp&fY-5rnp13&s8b5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k
+5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rh4k5rnp1"Z\k7HhR1%mf3!ks8DZgmK5J>UaaUh!i2>H
+qsOLX"+*="3W;;r3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk3C,Yk5rnp1
+"Z\k7HhR1.mf3!ls8DZamf3!qs8DZ[mf3!ks8DZgmK5J>Ua^f~>
+!m8N2qsFRWme6M#rrr8mmdff:qsI/KmdB6"io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]Ckmdff:p$MnPmWH0)!d3r%n*U;Kme6Lj
+rrr8mmdff:qsFQ7`l_`7rrU?_IJ`F7o'Z5JbPqbBp?qM>o)%hWo'Z5J^AeB5p?qM>o(DDPo'UY5
+49BZno'buKo'Z5J^&J94p?qM>o)%hWIE'E<cMmsg`dRaP!qPc%a#jEGmdg/@"7kmRqS)t5qY'@J
+mdg&="7kmRqSW=:qY'@Jmdfi7"7kmRqRun4qY'@Jmdg8C"+A23@=S~>
+!rqu=qr[qHrUquGpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0d
+s8DZimec/Gmf2E9hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWEtume,`BmJq>-3<2@b3<2AE3<VW.F7/Jbk5XlJp-8TNs7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmpAb*brU0RF
+"3pQ>SBV!6p<EKss6fjZ1&ptIpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajds7ZKkpAOFVk5XlJp-/NMs7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds8DZime,`BmJq>-3<2@b3<2AE3<VW.F7/Jbk5XlJp-8TNs7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKmpAb*b
+rU0RF"3pQ>SB_'7p<EKss6]l.r]'sEd5_1mr](*I3HOWVpu_VErUrGTpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb*brU0@@s6fjZ3WJgQ
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7ZKkpAOFJ
+k5XlJp-8TNs7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKmpAb*brU0RF"3pQ>S:C~>
+!h?&@qX4CWr;Zfb.H^'\mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs7jok,G
+p?qYLmQ]k%k3hBohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWFams5s@L!;?$P#+R\>3GPq``r?8*Zt_Te3LoL)s7ZBjs6_i.mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs7jok,Gp?qYNmK52>S12__
+!h?&@qX4CWr;Zfb.H^'\mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs7jok,G
+p?qYMmf3"Ys8VLGk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"r8n.Mp@dqJoBlgQ3C,Z?[-#C.#3N:-3C,ZqmI(#Jr;Zfb2s0PjmcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mec,Lme6ABpA41Z0r1<gcMms9
+UbV`6#+R\>3GPq`dJjF5Zt_Te3Log2s7ZBjs6_i.mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs8jok,Gp?qYGmf3"Ys8VLAk3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3i-/"Rc!Wme6&9s7ZBjs6_i.mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs7jok,Gp?qYNmK52>
+S1/s~>
+!liB.qX4CSs7SJQqXWq6io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7W
+hW!DOk3hg.o(h\RlMfcGlJgg[hT+=Tf%S^/hWjP"oBlUDr]EG[ZJ,0TqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqV&5hr]C1GmI(#Fs7St_qXWq6
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_iniPO
+hW!\co'Z)FmK7aW`aR-l!liB.qX4CSs7SJQqXWq6io]7_io]7_io]7_io]7_io]7_io]7_io]7_
+io]7_io]7_io]7_io]7WhW!DOk3hg.o(h_Ro)JDQs8)<Ok2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2+tShW!\co'Z)?mJrOO4@!VdgA:jGs8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clg9PGl491Z6
+mf2kXp.,/Zo'5Ask2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_hVR8Kio]\"mdg5B"*r&/@F"lS`l`T'mJrOO4>giYgA:jGs8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)TlqV&5hr]C1Gp?qtOs7Sq^qXWq6io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_hVR8Kio]\"mdfu;s763`
+63$fPlK7*gio]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_io]7_iniPO
+hW!\co'Z)9mf2kXp.,/Zo'5Ask2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_hVR8Kio]\"mdg5B"*r&/@=S~>
+!quZ5qW@hG#PRTcp?peoec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D,e_]0\
+eHFakmcNs4k5O3=k2+t1ec4b3mdoQ@Pl<ZEC95t*p&`dGCAp3nPjRW5mK`IRs7Ym;hUVV^!7h)*
+!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*qpbi+k3hC"qW7n!
+s7W85rrVoo`VS`smK`IRs7Ym;hUVV^!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*
+!nH/ar7(r,k3hC"q<%_F#PRTcp?peoec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*ec+D*
+ec+D*ec+D*ec+D*ec+D*ec+G'eHFakmcNs/joCYF3<Erse].:aeZ<Nb3<5<2k5XiSp?qtSmbZgN
+rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rndP&"Q&;/
+k3i*."3(<6UsAuApA`,.joCYF3<Erse^='leZ<Nb3<5<;k5XiSp?qtSmbZgNrn[Y*rn[Y*rn[Y*
+rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rn[Y*rndS'"Q&;/k3hj's6^-cmf3"K
+hVQf^h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h>l+*h?)6ahYbn,hWF7g
+md90:mK`IRs7Ym;hUVV^!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*!7h)*
+!7h)*!7h)*qpbi+k3hC"qW7n!s7W7=~>
+!i2>HqsFU\mdB62d/O18k2-(!rq?6W7eY^$hWEtgk3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k2+tWrn[_Ep@e1I"k>n)3McBIs8MEdk5OcK
+k5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OfJjp(8IUcC_,c0t''
+p?qA2p;6h2mcNC)k5P)OmK5J>UaaRg!i2>HqsFU\mdB62d/O18k2-(!rq?6W"SV9Ok4Z^m!q,4-
+rT=+Qp$N"65s[N,pAP$jmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDKmJuDK
+mJuDKmJuDKmf)>Qme3G:5s`camKE7OmcO5[rrVWNhYlU9pA=7[3LllocMmsAS2pK7"k>n)3McBI
+s8MEdk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5OcKk5F`Ijp(8IUcC_,c1p]0p?qA2
+p;?n3mcNC)k5P)ImKE7OmcO5arrVWNhYlU9p@%DPp?qA2p;6h2mcNC)k5P)OmK5J>Ua^f~>
+!m8N2qX+RIk2P\&s8W)p2"pe>qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+k2+\Gg>:iWmdg5B9A87VhW!h[k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PCWg=G!/g=ki[o(DDNcMfpeRI^4Js8(m;k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PP$iWA91RJo;Kb3n[%io]7cqZ$TpqEjoP
+pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LFhU^Q;
+hW!tko)%hWIE'E<c2Rjf`dR^O#3+e)lMCP\rq\JFqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'(.f&#-;ipQ7*qX+RIk2P\&s8W)p62(0KqY'dZqY'dZqY'dZqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZp?(5_hV-iGmdBZ=mJtQ34?Ao$qY'sck2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k5=3?k3eZ:493Ol
+mKV\5ip-C?s8Mj]pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZp?(5_hV-iGmdBZCmK7mWb$iTq!m8N2qsFI0r]Dm&o(r([qW?f"io]7_io]7_io]7_
+io]7_io]7_io]7_io]7_io]7_io]7_io]7_rSdn@m[=&:!6Y'(#3+e)lMCP\rq\qSqY'dZqY'dZ
+qY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'dZqY'XFhU^Q;hW!tko(;>S
+io]7cqZ$TpqE4KJpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+p?(5_hV-iGmdBZ6mKV\5ip-C?s8Mj]pA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZpA4LZ
+pA4LZpA4LZpA4LZpA4LZpA4LZp?(5_hV-iGmdBZCmK7mWb$ff~>
+!rqu=qrRnHrn[_=pAb$`!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj["7G$r
+c2H2lmec,Hmf(c:hEU/Zk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Ne]n'C!p8q=p#Z8!r](.Hme6)Kp;Yqmk*.kl3Q:IL!:KjC!p94Vqt:$X
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6N`p?pefc2H2l
+mec,Kc1_1-bl7_;c26W'mf)&Ek4\iPp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&ja>e]n'CrpK[G!:KjC!p94Vqt:$Xrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq?B[!oDJPrRLo8p#Z8!r](.Hme6)Kp;Yqmk*.kl3Q:IL!:KjC!p94V
+qt:$Xrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6N`p?pef
+c2H2lmec,Kc1_1-c2Rh<c26W'c2K^,Pj\85s7Xjs"m2%05rlpZjoFiKh?)j5s82Kimf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)q[mK27qc2H2lme,]Bmf)&E
+k4\iPp&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&ja>e]n'C
+rpK7;!:KjC!p94Vqt:$Xrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6N`p?pefc2H2lmec,Kc1_1-J,~>
+!h?&@qsOLHrnc!$!p8@irSIA<r8'a-k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"
+k3hC"k3hC"k3hC"k3hC"k3hC"k3hC"k3h*_ec"@rmRj!86$)2V)"mt0!<3'!!<3'!!<3'!!<3'!
+!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!<3Vm+Qag/k&WgSSF>nGk5O5RrrV?>
+ec"A#mK52>S12__!h?&@qsOLHrnc!$!p8@irSIA<s5s=;_Z']"hUVS]oBo5@5s]SSmMPWtrrE'!
+rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'!rrE'1jrie/k2p_N
+6(IE3s5s=;_>aT!hUVS]q<e>>UmrmZrrS^d1&LB'S3]G^k3a)[!<3'!!<3'!!<3'!!<3'!!<3'!
+!<3'!!<3'!!<3'!!<3'!!<3'!!<3'!!:C]\(uFE;F$W*^q!S1ErnbNl!p8@irSI/6s5s=;a8Z5'
+hUVS]mI(#:rnbKk!p8@irSIA<"#6UA.=_~>
+!liB.qsFI@rRq8FrVnPIs8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)Tc
+k17uZg&UF7mJu,BecXpok2OJEs5F+6da%gB!:'4E8sqq,D;s[tl3RCqq?Zp'q?Zp'q?Zp'q?Zp'
+q?Zp'q?Zp'q?Zp'q?Zp'q?Zp'q?Zp'q?Zp'q?Zp'q?Zp'qA@p7hB^t7EBHLSn*U24rRq8FrVo%W
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clqY'(&
+df%l"lMBoNH-4-8c2Rjbb'EmP!8d\.!;?Bk0Db_Fs8)cls8)cls8)cls8)cls8)cls8)cls8)cl
+s8)cls8)cls8)clqY'(&df%l"lMBoKhYl..pAP"RqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqY'(&df%l"lLaL:R6WlOioV6G#lb2,#l4i'#l4i'
+#l4i'#l4i'#l4i'#l4i'#l4i'#l4i'#l4i'#l4i'#l4i'#l4i'#l4i'(tpCp,i7Bt4@#>'mJu,B
+g&UjFs#p5YqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$Egp?'rSrRq8:qX+H2b/Rl8rrU3_H2I"oR6WlOioV6G#lb2,#l4i'#l4i'#l4i'#l4i'#l4i'
+#l4i'#l4i'#l4i'#l4i'#l4i'#j*D`+PP]/EBHLSq!J.=rRq8FrVo"Vs8)cls8)cls8)cls8)cl
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)clp?'rSrRq8:o^2_9rRq8FrVnhQ
+s8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)cls8)Tck17uZg&UF+
+mJu,Bg&UjFs#p5YqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$ElqZ$El
+qZ$ElqZ$Egp?'rSrRq8:qX+H2b/Rk?~>
+!quZ5qr[h,"Rc!`pA`\:#O^Hnc.1(hebSA-eO[s8c/.=>hWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\Oe]l@hc.1A9k":k(3GRF-.HV3A&G?\/
+&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G@6s1"@`'eS7*1
+Pjdc4eHG=6s7ZK5p':$Bc-=e`e^aKX"3(<6Us8o@pA`,/k5<a4me6\Ss4-fJmbZ45e]lXpq<%V*
+"Rc!`pA`5-#O^Hnc.1(heaqoqPX.<EhVK^D&H<=8&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/
+&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/+Or3s.Fls`3C/nuk5<a4me6\Ss2Xg<mbZ45e]lXpq;qdu
+s7W86rrVoo`V\dWPX.<EhVK^D&H<=8&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/&G?\/
+&G?\/&Dek\.K7j"C,nSEpu_M)"Rc!`pA`5-#O^Hnc.1(heaqr$eHG=6s7ZK;p':$Bc-=e`e^a'L
+r7(r<pAajda7]c+hTa<qc.1A?jo`U&p8!3~>
+!i2>HqsFXEk2t4Np<WaCk1/#EhUUKZmKM.thUUKF_X7Wbe^`O5e_]rd#CB'8[-$KfhT5]umbZLn
+jo_t_8pg$p"lAD(e_^#9rs%W9e`P`=hYQXB3Llloc2Rj@S2pK7"lAD(e_^#Grs%W9e`P`=hYQXD
+hWEtNhY+hd#3OIdk2+YFo^2s28kQJQjqusrrrVWFec+\5Zq<r;n*UA9k2t4Np;-b5k1/#EhUUKZ
+mK5J>UaaUh!i2>HqsF]98kQJQjqut(rsA,MeJRH2Zq<r;q!J=Bk2t4Np;6h6k1/#EhUUKTmKMJ0
+k1/>^a8ZA+e^`g=e_]`^"lAD(e_^#9rs%W9e`P`=hYQXB3LlloJ,~>
+!m8N2qsFX9g=k!+o$ICAp>46GhV-9/qX.#)f%SR#io]Cgk3D*ok3D*ok3D*ok3D*ok3D*ok3D*o
+k3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*ok3D*gg<S!tf$<"AmR)+b8?U\',hhtlqY'dZ
+qY'd^pA4LZpA4XZqY'dZqYKp^pA4LZqY'dZqY'd^pA4LZpA4XZqY'dZqYKp^pA4XJg=#uS"0P0_
+Fmn`%db<F'f(-]X#PR$&db`^'gA:4>IE'E<c2Rjf`dRaP"k),Ydan!9rs/8SdaI"+cJ&-_"k),Y
+dan!,rs/8SdaI"+cJ%pY6ZkdfY1h_Xg@kRCpA4LZpA4XZqY'dZqYKp^pA4LZqY'dZqY'd^pA4LZ
+pA4XZqY'dZqYKp^pA4LZqY'dZqYK@.df.r&Y"1s'n*UA-g=k!+o"tD3p>46GhV-9/qX+H6`l_`8
+rrU?_IJ`FfF[Sd'g>4+/pAb!_qY'dZqYKp^pA4LZqY'dZqY'd^pA4LZpA4XZqY'dZqYKp^pA4L^
+q?c<<dNmQ#Y"1s'q!J=6g=k!+o#(J4p>46GhV-9/o^2n2g=k!+o#Uh9p>46GhV-9/md:8,g=k!+
+o"tD3p>46GhV-9/qX+H6`l__?~>
+!rqu=qrS(,e^_phmeZq`pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAP!tp?pJUc.1@heaE=s"jPTJ
+c->+_jp9hoc-=e`c.27Tjp?)p8u1"f.Fn.lrq6?[qt:$Xqt:$Xqt:$Xqt:$Xqt:$Xqt:$Xqt:3]
+p@d@nc2Q5qX@bd"n)aeue^_phmeZq`pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpA=jr
+p?pJUc.1@heaE=s"3pQ>SBV!6p<EKs"jPTJc->\QrrDcjrrDcjrrDcjrrDcjrrDcjrrDcjrrDck
+rsADee]l@he]lY4qrS(,e^_phmeZq`pAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFpjpAFps
+p?pJUc.1@heaE+m$$/C)Ut+!Eeb9%Bp&OOXp&OOXp&OOXp&OOXp&OOXp&OOXp&OOXp''mXp>4?E
+rm_+P8jROejos#[e]lA,qYpQhr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjqu6urma]S,
+e^_ppmec,Kc1_1-c2Rh<c26W0F$WEoe^Z,!pAb-c!:KaX!:KaX!:KaX!:KaX!:KaX!:KdY$/X4W
+.FltM8jROnjos#[e]lA,qYpQhr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;R)sma]S,
+e^_ppme,]Gc.1@hc0kH.!;??j!;??j!;??j!;??j!;??j!;??j!;??j!;?<i$23f;c-=ehc.27N
+jos#[e]lA,qYpQhr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjr;Qcjqu6urma]S,e^_ppmec,K
+c1_1-J,~>
+!h?&@qsFL0k5Nm2p<Wa=mf(`=hTa=-qsI.shUTm$k2u*omcNs"mcNs"mcNs"mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"mcNs"k0;0$hSmb%p$ViX#"m.shUUKVaSuP&
+eLBY;bt:l3n*U5$k5Nm2p;-b/mf(`=hTa=-qsFP@UmrmYrrS^d1&LA>c0##U!;=b=!:Kj:"5_;I
+k54QIc0##U!;=;0!:Kj:"5_;Ik4S0B;?fb<hVQf>p;m7>hUO(;hT\Yj;Xa#Sc0##U!;=8/!:Kj:
+"5_;Ik54QK0r1<gcMms9UbVc7s&'%nc/.=-hY,Fu#i=+^k2+?T;H!;X!R9d+eH#<[rrDKdeH=[Q
+c0"]e!R9d+eH#<`rrDKdeH=[Qc0"K_!R9d+eH#<ZrrDKdeH=[Qc0"ok"#6UA.=_~>
+!liB.qsF[.g="9pmeY?2#kmE+cI1Fdb2W<d9Z#B/b0K#+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_
+k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2PO_k2P+;b0nkXb2W*^8l/2Pb1bRtf(/k;
+s8)cls8)TlqZ$ElqYL6gs8)clqZ$ElqZ$Egs8)cls8)TlqZ$ElqYL6gs8)clqZ$ElqZ$9Gc7mu+
+b",3&n*UD"g="9pmeXj$#kmE+cI1Fdb2W<d"*r&/@EnfR`l`T(mKU\bda$;/qU,<Kp?'ZGdb;^`
+iqr-J`nJkdddHtMrs8>\cHakl`ld<6mRg;L8BTZ?dan!hqZ$ElqZ$Egs8)cls8)TlqZ$ElqYL6g
+s8)clqZ$ElqZ$Egs8)cls8)TlqZ$ElqYL6gs8)chhTdh/g<)r[;"*fV`nJkdddHtLrs8>\cHakl
+`ld<<mK7aW`aR0m!liB.qsH[F9M!=[g="RCs8)cls8)clqZ$ElqZ$Egs8)cls8)TlqZ$ElqYL6g
+s8)clqZ$ElqZ$Egs7Y<pcJ%!p85)kTmKU\bda$;/qS`C>p?'ZGdb;^`iq;^D`nJkdddHtRrs8>\
+cHakl`ld<0mKU\bda$;/qSW==p?'ZGdb;^`iqr-GH-4-8J,~>
+!quZ5qrRpmec*Mlk3hs:s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'(Ki
+pAaR;rl"ui]uAk*joN0Grl+oo53C_ahWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\Frl"ui]uAk$k5S$X6,h+!`Qdhmp'0s8`AuJn`VrKujoN0G
+rl#*(me6ASpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c
+#QOMtp@eOShYtIre\/rYqrS""s7W85rrVoo`V\cu^"*,$#3P@IpAajdrq6EnpAb-c!rquorq6En
+pAb-c!rquorq6EnpAb-c!rquorq6Nqp@eOShYtIre\/rYqrRpmec*Mlk3hs:s7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp'1Qjs7ZK\hYtIre\/rYp#c9H
+#!p5Qe]#f$an>r,e\sQ!c,KZSn)aYaec*Mlk3hs:s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp':Wks7Z0dmb[r^"4b*(hYZF;`W,Y-cMmt>s2Flts%3J]
+`QcrPc0j*T#4C$\`RW5Pr^utJ!PR%_`<PJmp@eO[s8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]n
+s7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]rs7ZKds6ebC`<4Z(`SU:M!PR%_`<PJmp@eO[s8M]ns7ZKl
+p&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp&b9fs8M]ns7ZKlp':Wks7Z0dmb[r^"4b*(hXBS-^"*,$
+#3P@IpAajdrq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6EnpAb-c!rquorq6Ts
+pAaj[s6ebC`<4Z(`SULS"3(<6Ujr~>
+!i2>HqsFX,hUTm$ma(n<ma]S4k/G$rqsFX,hUTm$k/?Zok3h*V`RWha^#o"U#[1,0c0!P*eb7)a
+!:Kj:"Qms4;HiPW"i]?Kc.26urs.uBc.1sq^#o4["$)mI.F%koUmsIBmKLSde]lY4ci47<e]lY,
+`P(F2mKLSde]lY4_Z'l/e]lY,`P(F,mKcuo>0Z3[.Fn.5rrDKdeHG$Z>#JPmmKLSde]lY4_>ac.
+e]lY,`P(F2mK5J>UaaUh!i2>HqsF_n;Hh?-eLB&Be,K^AeLB&2c!""Kq!J=)hUTm$m_\u/ma]S4
+k/G$rp$N"&hUTm$m`5>4ma]S4k/G$rn*U@uhUTm$m_So.ma]S4k/G$rqsFPHS>7Ta~>
+!m8N2qsF^'g="!hlLt)'rsAPqim,Qlg:k;\qsFX!f$;:\hSSC[g<.F\f"/TTp$N,d:fYBddPTD?
+qTAgEp?'ZCdb;Q<:fZuP#JSp?`mX/GqSiI@qY&po`mWST^>f%X"+A23@EnfRb/Sl,mK^J[d`0`#
+pA38<$2XATcGn;d^:rV(mK^J[d`0`#pA2f/$2XATcGn;d^:rV"mKlli<PmJ<1t(ggb5VeAk0D,t
+g;6id<U]>\^=q#Tdd$Q&`W$8@p>XB;db;FLiqr-GIE'E<cMmsg`dRaP#usf%_V3EpddHt^rsAD]
+c8<u'_GsE4q!JC$g="!hlLt(orsAPqim,Qlg:k;\p$N(!g="!hlLt(trsAPqim,Qlg:k;\n*UFp
+g="!hlLt(nrsAPqim,Qlg:k;\qsFQ7`l__?~>
+!rqu=qrS'he]kePk5G!'s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKl
+p'9Hn^!5*7^#&YK$ae1'^!5*ihWE\WhYuX=hWE\ojoXE%hYuX=hWE\ojoXE%hYuX=hWE\ojoXE%
+hYuX=hWE\ojoXE%hYuXHhWE\WhWEA-^!5*7^#&GEr_btoe\sPnk4\iKs7ZKds8VfmpAajds7ZKd
+s7ZKmpAajdpAb0ds7ZKds8VfmpAajds7ZKds7ZKmpAajds6ebC`<"N&r_i4I"glh)^!5^<p,N*G
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKlp'9Hn
+^!5*7^#&YK"3pQ>SBV!6p<EKs"glh)^!5^<p+$+9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds8M]shSm1Qe[3$HqrS'he]kePk5G!3s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKkp'9Hn^!5*7^#&GEr_btoe\sPnk4\iKs7ZKd
+s8VfmpAajds7ZKds7ZKmpAajdpAb0ds7ZKds8VfmpAajds7ZKds7ZKmpAajds6ebC`<"N&r_i4I
+"glh)^!5^<p,N*Gs7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKlp'9Hn^!5*7^#&YK"3pQ>SB_'7p<EKsr_bD_e\sPnk4\iKs7ZKds8VfmpAajds7ZKd
+s7ZKmpAajdpAb0ds7ZKds8VfmpAajcrs%oJ`Atof^&Cq)jor-Bc+VBarUr/LpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb*b#N!G5c.027hY$"7[+3F7
+c0"uu1B7(JpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdrq6TR
+`P'OH[(Y>bjor-Bc+VBarUr5NpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdrq6TR`P'OH[(Y>njo`m%s."T~>
+!h?&@qsFKlhYtb#me6;Q!!)rs!!)fo!!)Kf!VYs\blch0^#&YS+10nL`QdQ-mcNs"mcNs"mcNs"
+mcNs"mcNs"mcNs"mek$OmcNs"mcNs"mcNs"mcNs"`THUNmcNs"mcNs"mcNs"k0:lihR'uQp$Vf_
+"hidCc.27Us8N)trr<&QrrqQ83S!!"r`\dY!OU__blR8+o)JRejSo2[pAY0emf(H5hR'uQqsFP@
+UmrmYrrS^d1&LA>[,1f,!Uf[Rrr<&srr<&orr<&frrMi]rlkQ%[(Y>nmK']OrlkK3p?;PS!:g'h
+!;$3kp?qq)"5^DuhY$=9=p;Ure]lY4pAb-mrVlitgA_?=eN)1:^&D4(mK']OrlkK3p@A7\!9F.[
+!;?Enp?qq)"5^DuhYZ^C0r1<gcMms9UbVc7r`TK=hUTm$me6Y\!;uis!;QQo!:Tpkk1.H$hS&nl
+q!J0ihYtb#me5lEquH9e!!)Wj!VYs\blch0^#&GM!OU__blR8+o`+dg!WN/prr<&orr<&irrMi]
+rlkQ%[(Y>bmK']OrlkK3p@A7\!9F.[!;?Enp?qq)"5^DuhYZ^C0r1<gJ,~>
+!liB.qsF]pf#kkPk486=q>^Nnq>^Njq>^Nbq?cldk/tQ`f!;mDqsFWjd`0/DhYuLMk2PO_k2PO_
+k2PO_k2PO_k2PO_k2PP$`Z4.#k2PO_k2PO_k2PO_k2OD?k2PO_k2PO_k2PP&iWn2W_T($,]&*,J
+$!CP:]%50DcKb,ts8N)trr<&Ss8VcuilXC/f",!i=mtb`ZI[18b3&9goD8=ajSAiVp\G3io&e*3
+b1<l0hYZ^CH-4-8c2Rjbb'EmP#I;q'_TM$3p@\7^!;uZn!;QBj!:]gkp@@@g_TLH8]&*>P#I;q'
+_TM$3p?DGO!:fmc!;-*op@@@g_TLH8]&*,J$!CP:]%50DcKb,ts8N)trr<&Ss8VcuilXC/f",!i
+=mtb`ZI[18b3&9goD8=ajSAiVp\G3io&e*3b1<l0hYZ^CH-4-8cMmscb'EmP$!CP:]%50DcKb,t
+rr<&srr<&orr<&hs8Vcuil]-`f",!i=nqCiZI[18b3&9gl2(;XnbN4co_Jmfo&e*3b1<l0hY$:A
+ZI[18b3&9gp%nOc!Vufkq>^Njq>^Neq?cldk/tQ`f!;mDn*UFdf#kkPk486;qYL9Rq>^Niq?cld
+k/tQ`f!;mDqsFQ3b/Rk?~>
+!quZ5qrS'Xc,IB0hYupDp?qqR!q,dMrq6Bnp?qqR!W_r^rq6Wcp?qVSp?qYBrq6E]p?qqR!Uf[[
+mK_U^]uA6l[+5'9"f0D^]tMtqhA581k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk5;n4k2,7Wk2,7Wk2,7W
+k2,7W^#%o.k2,7Wk2,7Wk5O3Be\/Z8c(q_sp#ZQY>#M`P`P'7Imf)n[s82Ni!<)Tl!<;ri!<;ri
+!<;ri!<;ri!<;ri%0-%hmbYoK`Qbbf>#OhO"f0D^]tN;%mK*%Lrq6E]p?qqR!Uf[Y!!)Hdp&a[U
+mf)n]me6)Jp&a[Umf)n]me6)Jp&aX^mf)n_me6)BpAXIbhS$VAc(q_sqrS""s7W85rrVoo`V\d$
+Us6ll^#&bV!VYs\p&a[Umf)n]!;>j[p&Y6fmf)ncme6)B!;>jSmf)n]me6)Jp&XUTrU'pI]tMD0
+UpS\LjoqR*`P&tArpBg\mf)n]me6)Jp&a[Umf)n]me6)JpA=mmp?qYBrq6E]p?qqR#k%ES!;?-S
+p?qqR"7GmNpAXIbhS$VAc(q_sp#ZQY>#M`P`P'7Imf)n[s82Ni!<)Tl!<;ri!<;ri!<;ri!<;ri
+!<;ri%0-%hmbYoK`Qbbf>#OhO"f0D^]tN;%mK*%Lrq6E]p?qqR!Uf[Y!!)Hdp&a[Umf)n]me6)J
+p&a[Umf)n]me6)Jp&aX^mf)n_me6)BpAXIbhS$VAc(q_sqrS""s7W86rrVoo`V\d(;Hcu*c,IB8
+hX:C:!<;ri!!)rj!<E/sp&b9f!<)Tks82Kis8DZkmKh[g]uA7';HcunjoqR*`P&tArpBg\mf)n]
+me6)Jp&a[Umf)n]me6)JpA=mmp?qYBrq6E]p?qqR#k%ES!;?-Sp?qqR"7GmNpAXIbhS$VAc(q_s
+p#ZFRc,IB0hYupDp?qqR!q,dMrq?3h!q$'Vrq6Wcp?qYJ!:KRKrq6Wcp?hqSp?qYBrq6K_p?qYJ
+rpC$J]tMD0UpS\@joqR*`P&tArpBg\mf)n]me6)Jp&XUTqZ$Warq6E]p?qqR!q,dMrq6E]p?qqR
+!q,dMrq6E]!:Kj["Rc!Op@eLR#N!/-`Qb3cebeJ2`W,Y-J,~>
+!i2>HqsF]jhTa$ik4\NHrrDcjrrMfnrVlol!<)otpAP!l!;??j!;??j!;?Bks7Q][e]#eiXM*cn
+mNAU]c+VBYk2u*omcNs"mcNs"mcNs"mcNs"mcNs"mcMLfs8U%bmcNs"mcNs"mcNs"mcNrVs5rb3
+mcNs"mcNs"mcNZgc,IrXXM*chmKmW;C96::1!T.[p](6nrVlitg]%<Jmf(H6hQ1I$C@CQqXPV4@
+e`QT!r;Qcjr;R&rrr<'!s7ZHmrr2ulr;Qcjr;Qcjr;Qcjr;QilrrE&u!;?<is7Q][e]#eiXM*cn
+mK5J>UaaRg!i2>HqsF]jhTa$ik4\NHrrDcjrrMfnrVlol!<)otpAP!l!;??j!;??j!;?Bks7Q][
+e]#eiXM*cnmK]iMc,J5qp@eFa!;??j!;??j!;??j!VQNms8N)srrDcjrrDclrrN3#pAFpjpAFsj
+p'9a1`Qd8@^#o"U$#3paXPV2Vc0k<"s8N)trr<&RrrMi]rlkT&XD23Zn*UF^hTa$ik4\NHrrDcj
+rs8>u!!*'!pAY-lrrDcjrrDcjrrDcjrrDcjrrVoo!<2uupA=mip'9a1`Qd8@^#o4["$)mI.F.qp
+UmsIBmKmW;C96::1!T.[p\t3nr;Q`sq#:<onG`ggm`dK2hQ1I$CA@3%XPV4@e`QT!r;Qcjr;Qcj
+r;Qcjr;Qfk!<3#u!;uispAFpjpAY'n!<;cjrrDcjs8Vctk1.GqhQ4EQp$N'dhTa$ik4\NHrrDcj
+rrMfnrVllkr;Qcjr;Qcjr;Qcjrr3$"s7ZBj!;?<is7Q][e]#eiXM*cbmK]iMc,J5qp@eFa!;??j
+#kn8u!<<)mrrE&u!;??j!;??j!;??j!;??j!quWorr2ulqu?]i#NjRUc/,P8k54QK3LlloJ,~>
+!m8N2qsH\Fd`T;HhX^72o(MYJo(MYJo(MVSo(MYJnc87So(MYJo(MVSo(MYJo(MYJo(MYJo(MYJ
+p@@e2b.c$HV7PO\mNA@S`kKIHio9+[k2PO_k2PO_k2PO_k2PO_k2PO_k2OD[s8U(ck2PO_k2PO_
+k2PO_k2POCs5N2#k2PO_k2PO_k2PCS`kKI@V7POVmRh&!AZF>(4NcgWs8)cls8)cqqYpNqqZ$Tl
+!;c`ls8VrqqZ$Els8)cls8)cqqZ$ElqZ$Tls8)cls8VrqqZ$9[il]-\euE:iAaf%]V:*N#b22^[
+p@@qJp@@qJp@@qJp&G*`p@@nWp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp@@qJp&OgWp@@qJp@@qN
+o((Y[^<4m#]&*>P"+A23@EnfRb/Sl,mQ[Prb.c$To()MFp@@qJp@@qJp@84Sp@@qJ!:ojSp@@qJ
+p@84Sp@@qJp@@qJp@@qJp@@qNo((Y[^<4m#]&*>P9Vp1[^<5='o(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJnc87Snc/[`o(MYJo(MYJo(MYJo(E(Wo(MYJo(MYJo(MYJo((Y[^<4m#]&*,J8nDFBWn,<T
+b3&9pqZ$ElqZ$Tlrr<&qs8VoqqZ$Els8)cls8)cqqZ$ElqZ$Tls8)cls8VrqqZ$Els8)cls7Z$C
+b/2<PWb#UMn*WoHd`T;HhX^72o(MYJo(MYJo(MYJ!!)T`o(E(Wo(MYJo(MYJo(MYJo(MYJo(MYJ
+o(MYJo(MYJ!;?!Wo(MYJo(MeJo%qO'b0m,thYZ^CIE'E<cMmsg`dRaP5@n87Wn,<Tb3&9pqZ$El
+qZ$TlrrE)qs8VoqqZ$Els8)clrrE*!qZ$ElqZ$Tls8)cls8Vf`ilXC+euE:iAbb[eV:*N#b22^[
+p@@qJp@@qJp@@qJp@@qJp@@qJp@@qJ!:ojS!!)``p@@qJp@@qJp@@qJp&OgWp@@qJp@@qJp@@qJ
+o%qO'b0m,thY$;,V:*N#b22^[p@@qJp@@qJp@@qJ!:ojSp@@qJp@@qJp@@qJp@@qJp@@qJp@@nW
+p@@qJp@@qJp@@qJp@e(JhTERTd\XP3n*WoHd`T;HhX^72o(MYJo(MYJo(MYJ!!)T`o(E(Wo(MYJ
+o(MYJo(MYJo(MYJo(MYJo(MYJo(MYJ!;?!Wo(MYJo(MeJo%qO'b0m,thYZ^CIE'E<J,~>
+!rqu=qrS6]c,I'/eaDSnme6YJ!qu'UrpBgfme6YJ!W_Z^rpC'cme6&Kme6)BrpBj]me6YJ%JK5`
+p?qA!`O*V/UpT"UjrgJE`O*V7hVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2*fNs8TbZk2,7Wk2,7W
+k2,7Wk2,76s5)npk2,7Wk2,7Wk2+tF`O*V/UpT"Ok5JfpUs6kE^#&2Wrq6s(p@eO[p&G*dpAagd
+pAaj[s8M]os7Z0drq6Hop@eOcp&k?gpAb-c"98)gs8M]ts6f=3]tMD0V#FiljpIp/`O*V7mcO62
+pAXI]p?qYRmK3(^!<2Bfp&OgcmK3+MpAXI]p?qYRmK3+MpAXI]p?qYRmK3(^pAXIjp?qYBme6):
+e]"o7c(q`'qrS"*pA^Z,rrMi<qrS6]c,I'/eaDSnme6YJ!qu'UrpBgfme6YJ!W_Z^rpC'cme6&K
+me6)BrpBj]me6YJ%JK5`p?qA!`O*V/UpT"UjpIp/`O*V7mcO62pAXI]p?qYRmK3+MpAXI]p?qYR
+mK`g\p?hn\p?qYRmK3+MpAXIcp?qVSmdBf:pAXIip?qYBp?qA!`O*V/UpT"Ok5JfpUs6kE^#&2W
+rq6s(p@eO[p&G*dpAagdpAaj[s8M]os7Z0drq6Hop@eOcp&k?gpAb-c"98)gs8M]ts6f=3]tMD0
+V#FiljpIp/`O*V7mcO62pAXI]p?qYRmK3(^!<2Bfp&OgcmK3+MpAXI]p?qYRmK3+MpAXI]p?qYR
+mK3(^pAXIjp?qYBme6):e]"o7c(q`'qrS"*pA^Z-rrMi<qr[le#GfV`6+u.Cs8M^(s7Z0dp@\Ld
+p@eO[!;?HdpAb-c"9/Aps8M]os7Z0drq6a"p@eOSmbYWC`Qb4X@ef'mUs6lc`RXD=p?qYRmK3+M
+pAXI]p?qYRmK3+MpAXIc!:KRK!!)`\pAXI]p?qYRmKiOSp&OOKp?qYRmLJsYp?qYBma]:``Qb3c
+hY$"<Us6lc`RXD=p?qYRmK3+MpAXI]!:KR[mK3+MpAXI]p?qYRmK3+MpAXIcp?qVSmdBf:pAXIj
+p?qYBme6):e]"o7c(q`'n)atQc,I'/eaDSnme6YJ!qu'UrpBj]!!*#d!qlWfrpBj]me6YJ!qu'U
+rpBj]me6YJ!qu'UrpBj]!;?E[&,,GbmdBf:ma]:``Qb3chYZF;c1_1-J,~>
+!h?&@qsH81hSmIYk3hs:s7ZKds7ZKds7ZHms7ZKdrrE)ms7ZKds7ZHms7ZKds7ZKds7ZKds7ZKl
+p'C*Kc,IZYSA!eVmKK-2`P'7IkN2fas8M-]`W,Pl!QG*1jp0b^]uANl^#&GM$u0iuUt*`'c0"a"
+s7ZHl"8;cppAP$opAb-mrr3)os8VflrsJK"s7ZHms7ZKmpAY'opAb0drr3Q's8Vfms7Z0CbsBV)
+UhXscn*WK3hSmIYk3hs:s7ZKds7ZKds7ZHm!;?Hds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKd!;?Hds7ZKds8M]tmcMd5`SR,uhYZ^C0r1<gc2Rj8UbVc71S!=@`QdQ5p@eO[s7ZKds7ZKd
+rrE)ms7ZHms7ZKds7ZKdrrE)ms7ZKds7ZKds7ZKds8M]tmcMd5`SR,uhYZ_7SDM6(c0"HfpAajd
+pAajdpAajdpAajdpAajdpAajd!<;cmp&OgdpAajdpAajdpAajdp&OgdpAajdpAajdpAaj[mcMd5
+`SR,uhY$:FC3+-ce]kePk4\iTpAY'opAb0drW!&os8N)urr_ups7ZHl$MON"pAY-mpAb0drr3)o
+s8Vflrt+o(s7ZKmp@d@f6-[rUC3+.YmQmB"`Pp*ame6ASpAajdpAajdpAY*mpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAagdpAajdpAajdrq6Wck0:lahOM:9qsFP@UmrmZrrS^d1&LAI
+C3+-ce]kePk4\iTpAY(!pAb0d!<<)ms8N)ursJK"s7ZKm!;?HmpAY'opAb0drr3E#s7Z0Cc+VBP
+UhXscq!LhGhSmIYk3hs:s7ZKds7ZKds7ZKds7ZKds7ZKds7ZHms7ZKd!;?Hds7ZKds7ZKds7ZKd
+!;?Hds7ZKds7ZKds7Z0Sk0:lahOM:9p$Oo3hSmIYk3hs:s7ZKds7ZKds7ZHms7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7QHds7ZKds7ZKds7ZKlp'C*Kc,IZYSA!eJmQmB"`Pp*ame6ASpAajdpAajd
+pAY*mpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAagdpAajdpAajdrq6Wck0:lahOM:9
+qsFP@Umrla~>
+!liB.qsFZRd_``<hX:%,!!)rf!!)fb!!)KY#k$Qh^;A<`]&*>P#*mWR]#*1Xki)W_s8M!Y`rGYi
+!QP03iX"Dp_RdV4Q+GiFmKmTEBq<\l]#NUpp\+Rdrq6<lo(E%`m.UJI#i<Qh`mUDlD/&J,#*mWR
+^;f$to^`"^hXUXHp@8LWhT!:HdZqE#qsFQ3b/Rl7rrU3_H2I"6Q.!O``np.Unc/[fnc/[bnc/[Y
+nd+[?`kK=<Q+GiLmKSs)_S4%Hmca3A!<)Hg!:o[\!;#aembYst_U=^\hY$:CBl.RTd`/l<hX:.3
+rW)rk!!)T`!!)BZs6^0L`^IhpSS;qTn*UCFd_``<hX:%,rrCpH!!)``#k$Qh^;A<`]&*>P"*r&/
+@F"lS`l`T(mKmTEBq<\l]#NUpp\"Rer:U*jq"=[fnb3"N#i<S4`mUDlD/&e5#*mWR^;f$tkje]R
+rUKpgo'ub\oC<1ThT!:HdZqE#p$N$Ld_``<hX:%,!!)3Q!!)T\#k$Qh^;A<`]&)oD#*mWR^;f$t
+o^`"^hXUXHp@8LWhT!:HdZqE#qsFQ3b/Rk?~>
+!quZ5qrS*Ic+UKte`QMl!!)rb!!)f^!!)KU#j0[N[(X_K[+5'9#*dBG[(Y#?khZ?Rs8LjU^&R]\
+!PSO*hZ)+1]sPJtPdK!6jpPX5@[t]V[(Y#Xme6YJ"SV9Op?qn[s6^-c!:K:KmdBfJmL&[Ume6):
+!;>jKpAXI^p?qABrpBm^mdBfJmL&+Ee\+Sg`LLCP@diF`Pg-nK^")9;mf*:DmJm7\mKht*]sPJt
+PdK!<jo`U&p8#t5!quZ5qrS*Ic+UKte`QMl!!)rb!!)f^!!)KU#j0[N[(X_K[+5'9#*dBG[(Y#P
+kjAENrU'Xco'QJXoBlnHe\/?'c'5Tcp#ZWkC1<^X]sPK'mdBfJmKE7Ome6)J!<;Hlp&OOKp?qAB
+rpC-emdBf:mJutKme6YJ"8;0NpAXI^p?qABrpC-Uma]!C]u?LNC1?Yo#*dBG[(Y#Po^;_ZhX1@D
+p?i4Ke\/?'c'5TcqrS""s7W86rrVoo`V\d*@VTABc+UKteaDl!rpCBlmdBf:!:KRKme-YKme6):
+pAXI^!:K:KrpBm^mdBfJmLAmXmcNrf]sPJlS765BpuVdFc+UKte`Q)`!!)uc!!)TX!!)WY#j0[N
+[(X_K[+4j3#*dBG[(Y#Po^2\ZkO&<Mo'QeGe\/?'c'5Tcn)ah=c+UKte`QMlrrCpD!!)`\#j0[N
+[(X_K[+5'9"3(<6Ujr~>
+!i2>HqsFWPe]kePhXgF@!;uNj!<2]k!<2Zr!;?*dp&G*bp'9a)^!5)l^#o4["dIQ^^!5F2joFiI
+joFiIjoOnhrT4FSk/IA_k3g4gk5E9tk5E7%k/IA_`W#!"mePuMhT`aYeWdc0p$Vg+)O0+'3R-^S
+s7ZKds7ZKmpAY-m!<<)m!;?HdrW!0&pAY-ms7ZBks8Nu1s7QHds8VfmpAajds7ZKds7YmCc,Ira
+Pl?$umKJj*c+VBYoC`.aq"FXdrq6?mpAP'kpAG!kpAP'kp&G*cp'9a)^!5)l^#o4["$)mI.F%ko
+UmsIBmKJj*c+VBYoC`.ar:U*jrq?<krq6Nrp@\L[!!)Zb#Nj:Ec./&lk54QMPh"$lc/.m^!!)oi
+!!)uk!W_rfr;cfir;Zuo!;?*dp%AXQc+VBPPeH5Pmf%POPhsYFc0"HopAajdpAb0drrE'!s8Vcm
+pAajc!!`JsrrE*!pAG!kru(P1p&Ogds7ZKds7ZKmpAajdp?q(f`Qd8(rd4,%"dIQ^^!5F*p&G*f
+pAG!jp&P0erW)rkr;clkrW)rk!!)]c#Nj:Ec./&lk54QK3LllocMmsAS2pK7rd,QJhT\(*k3i9C
+s7ZKds8Vfm!<;cms7QHds7ZEl)uoX3!<<'!rr<&ms8VfmpAajds7YmCbrO&*Pl?%)mKJj*c+VBY
+me-V\qt:!irUp9mp@eFbrV$0i"SMihp&OdZ#Nj:Ec./&lk4S-GPh"$lc//'c!!)oi"9A/h!;?Bl
+s7QKop@eFbrq6?mpAP'bp'9a)^!5)l^#neO"dIQ^^!5F*p&G*fpAG!jp&P0erW)rkr;clkrW)rk
+!!)]c#Nj:Ec./&lk54QK3LlloJ,~>
+!m8N2qsF]Od`/l<g?RtrmJm7bmJm7dmf!4cmKN[ZmJuYT!;>j\l3H%_]#N0\]&*>P-]QEg]#*1X
+hW!DOhW!DOhW!DOhW!DOhVuQ7hW!DOhT#TThVuQThYkFrini\OrPf]6`rFo8hW!DOhW!DOhW!DK
+g;:G<cAfElp$NiGFa9+t_Ec,tlLsfBo(MYJp@@nWp&Og[nc87So)8Unp@@nWp@e(U!<;a4o(MVS
+o(MeJp@@qJp@e(No(MM:hT!:HdZJftH11/+Oj_7\`nK_Cp$Me[q!S(\rpBdemf!4cmem.cmf!4c
+mJm7]mf2PWg;^_DdZM,tqsFQ7`l_`7rrU?_IJ`F;Oj_7\`nK_Cp$Me[r9aObrpKacrpBsjmd:)C
+!!)`\s69jC`k'1<Oh0EHmK\m&`k'1DlK[m,!!)oa!!)uc!W_ZVr;cfar;Zug!:K7Tp[8(H#MR2/
+`mU!\hY$:WH$+Cpd_\8hhWjh*p@@qJp@e(N!;6Edp@84Sp@A1_#57W]!;?-Wr;clk*:igo!:ojW
+o(MYJo(MeJp@@qFlJBOp_U=QlFa<HD#EdHS]#NIhlLjQF!;Q!\!<2Be!:KgdrpK^bs6fjdrpBad
+p[8(H#MR2/`mU!\hYZ^CIE'E<cMmsg`dRaP*I2dQOj_*3`np"So(MYJo(MeJp&OgWp@e%Wo(MYR
+!$:k)p&Og[!;6Bmo(MeJp@@qJp@dq>hSqgtdZJftH2-e4Oj_7\`nK_CnEp8VqsFFarU'^emdC#R
+rU0Ua"RZ9XmK!"Ls69jC`k'1<Oh0EBmK\m&`k'1DlK\'1!!)oa"9@lX!:Kgds6]pgmdC#RrpBde
+mf!4\mf2PWg;^_DdZM,tn*UFCd`/l<g?RtrmJm7^mem.bmK!=UrW)rcr;clcrW)rc!!)c]s69jC
+`k'1<Oh0EHmK7mWb$ff~>
+!rqu=qrSoW`P&Xle`Q#^k3hC"k3hC"k3h@3k3hC"joFQ3k5G?%k3h@3k3`6;!!)0Lk3hC"k3hC"
+mcNZ^]sPJtMmV@<jop[^]sPK'mbRrWqq_@es8LjV^&Qsf^&?gd]`d3*s5(H^h?VTE[(X_B[,1K<
+rc8:%c+Q`_e`QVo!W_WgrpBadrpKacrpBadrpK^br9aOboBuY@"kC;n^!2K7F7863MoEB:^")9-
+mcNs"mcNs"mcNs"!9W_3mcNs"mcOHJ"RbF?!:Kgd!q,4=r;Zl\mf!2&mcNp;mcNs"mcNs"mdB6"
+e\/?'c&8scqrS"*pA^Z,rrMi<qrSoW`P&Xle`Q#^k3hC"k3hC"k3h@3k3hC"joFQ3k5G?%k3h@3
+k3`6;!!)0Lk3hC"k3hC"mcNZ^]sPJtMmV@<jsQ)+]sPK'k2u*omcNs"mcNs"mcNs"mcNp;mcNs"
+mcFN3mcNp;mcOHJ"7G=>k5>8smJu\;!9W_3mcNs"mcNs"k1./P^!2JBhY$%1Es@QI]h5ugk4e9F
+!:BjdmJm7dmf!4cmJm7dmem.`mJm7Ymf2DQe\/?'c&;RBn)bXK`P&Xle`Q#^k3hC"k3hC"k3h@3
+k3hC"k3hC"k5>8_mcNp;mf!1fmcNs9!!26MrW!c&k3`6;k3hC"k3hC"mcNZ^]sPJtMmV@<jo`m%
+s.%@6!VXe8k5KE+Mp8q-^")9>mJm7bmJm7dmf!4cmKN[ZmJuYT!;Gp]jos;K9"iK-rc@ks-]>sW
+[(Y#Pk3hC"k3hC"k3hC"k3hC"k3`6;k3hC"joFQ3k3`6;k5>8^mcNs"r;[]&!:JtLk3hC"k3hC"
+k3hBoe\/?'c&8scp#[?S`P&Xle`Q#^k3hC"k3hC"k3h@3k3hC"k3`6;joFQC!!MHP!:K"J!!M`P
+mJu\S!#+e_mcNs"mcNs*k2t4-[(X_B[,196*K.nM[(Y#Pk3hC"k3hC"k3hC"joFQ3k3hC"k3hC1
+!!M`PmJu\S!!;TNmem+dk3i3K([gGR!:K";k3hC"k3h["k1./P^!2JBhYZF;c1_1-J,~>
+!h?&@qsFK;ec*MfhYupmp?qYBp?qYBp?qVSp?qYBp&OgS!:KO\!:KO\p?hn\p&G*\p?qYBp?qYQ
+mK_mn]uAi\^#&YS$A6mJ]uAjbk2,7WroO:=k2-+"#i=_#`Pq!>k2-+"#fZi#k/HK_k2-+;"NBN[
+`PqfU"i^M\`W+fojpp81hWE\WhVQ5b`RTUShY$:CH\6s/e]kePhX:.3('+%.!;?*dp@\L[p&G*d
+p&G*d!;?*dqY'php%JFR#i<flc..`!K7iX\!JAr%`;ncomPsq.p?qYBp?qYBp&OgSp?qYBp?qYB
+p?qVSp?hn\p?hqKp&G*\p?qVSp?hn\p?hqKp?qYBp?qYQmK_mn]uAi\^#&YS"#6UA.F%koS>7n:
+mK%sjrl"lorpD90me6)Bme6)Bme-YSme6)B!;>g\me-V\me-YSmJm7\!!)H\me6)Bme6VI#Nj"=
+`SQ6\hYZ^AK@Tt?!8d_C3;2e6me6)Bme6)Bme6&K!;>jSme6)B!;>jS!;>jSme6)B!;>g\!;>jS
+mJuYT!;>jSme6)Bme6YJ#Nj"=`SQ6\hY$:CH\6s/e]kePhX:.3('+%.!;?*dp@\L[p&G*dp&G*d
+!;?*dqY'php%JFR#i<flc..`!K7iX\!JAr%`;ncomPsq.p?qYBp?qYBp&OgSp?qYBp?qYBp?qVS
+p?hn\p?hqKp&G*\p?qVSp?hn\p?hqKp?qYBp?qYQmK_mn]uAi\^#&YS"#6UA.F.qpS>7n:mKn5m
+K8\:)^!5F%p\"Rer:U^&p@\L[p&G*dp&Og[!!)]m!;Q9fmKh[o^!5)cH\6tGmK%sjrl"lorpDc>
+me6)Bme6)Bme6)BmJm7\me6)Bme-YSme-YSme6)Bme-YSmJm7\me6&KmJm7\me6)Bme6)BrpC$R
+`P'7IK>$.7mK%sjrl"lorpDQ8me6)Bme6)Bme-YSme6)BmJu\K!!)H\!;>g\me-YSme6)BmJm7\
+mJu\Kme6)Bme6VI#Nj"=`SQ6\hXBk5K@Tt?!8d_C3;2e6me6)Bme6)B!;>jSme6)Bme6)Bme-YS
+mJm7\mJu\K!!)H\me-YSmJm7\mJu\Kme6)Bme6VI#Nj"=`SQ6\hYZ^C0r1<gJ,~>
+!liB.qsFZBd_`T4g?/%m!!)r^&HM+]!:&hL!:&hLlKS?Ll2UhXl3QP+_RdV4Kt?.<mKS6f^:M&0
+g@=&"`W=rrr8%_!s5)VPhZ)Hhrr3,@hVQ8lrVm#?s2N(YpYH20f"S`0c@NR`p$Vg-#)UXF]#NId
+p[/dsmJm7TmJu\C!:K7T!:K7T!:BjTmK!+OrrD`[s5jL=`^IhlM>hqlmKSBn_RdV<k4Ip=!;,Oa
+!:&hL!:&hLlKS?LrTXUflKS?LlKSBCl3QP+_RdV4Kt?.<mK7aW`aR-l!liB.qsFZBd_`T4g?/%m
+!!)r^&HM+]!:&hL!:&hLlKS?Ll2UhXl3QP+_RdV4Kt?.<mKSBn_RdV<k4.a:!;bs\!<26`!;bs`
+!:&hL!<)0b!9sOap?DqGg;:G<dY59hp$Vg-#)UXF]#NIdp[/dsmJm7TmJu\C!:K7T!:K7T!:BjT
+mK!+OrrD`[s5jL=`^IhlM>hqlmKSBn_RdV<k4Ip=!;,Oa!:&hL!:&hLlKS?LrTXUflKS?LlKSBC
+l3QP+_RdV4Kt?.<mK7aW`aR0m!liB.qsOH3#)UXF]#NIdp[/"]r9b-smd:)CmJm7TmJu\C!!)Ee
+!;Q!^josJY]#N$PrdFS0#)1LB]#*1`n`p,SqW\%\rosI`qW\1`lKS?LrTXIbl2UhXl3QP+_RdV4
+Kt?.6mKSBn_RdV<k4Ip=!;l$j!:&hL!:&hLlKSB7l2^_HrrE)a!!)`X#j0jX]#)mL]&)oD#)1LB
+]#*1`o]cDVo]cealKS?LlKSB7l2Uh_l3@=Sl2UhLl2^PC#j0jX]#)mL]&*>P"*r&/@=S~>
+!quZ5qrS64c+UKte_]HFk2-+"!oE(rroO7^k2-+"'EI:P!9WDD!8ci<k2$(<jo>D<k2-+"%Gp7(
+hWE\F]sPJtHaM?#jsYT$]sPK'e_\j5e_\j5e_\j5e_\j5e\/ZQs5);_e_\">e_\!rs5)<*rrg$l
+e\/ZprtiBK]tOHrhUUK5hUUK5hUU/i[(X_2[+4j3$$1H?K>kO2^!5F5joFiHjq[sZ!!)0D!:JtL
+k2lXDmcFKLjoFQ3!;ts]mcFKLroO4KqrS=Tk2+t>]i)P_K6)Bdn)at(c+UKte_]HFk2-+"!oE(r
+roO7^k2-+"!oE(rroO^IjoFQ+!!)0<!9WDD!8d_;#QX#D!!)0<!8d_;&)QI*k2tO_hUT<H^!1o2
+ebeJ2`W,Y-c2Rk=s2Flt$@C%2[(Y#Hk2,7WroO:=k2-+"!W_B>roOmpk2$+#jo>D<joFQ#!!)-]
+!8ckproO[Hk2+tWhUT<H^!1o2ebeJ9Hd072^")!%hWE\ojoXE%hYuXChWEYp!9W/#hYuXC!9W/#
+!9W/#hYuXI!9W,<!9W/#h>l[<!9W/;jpp81hWE\WhUT<H^!1o2eb/&2F*i7d`P&Xlc//H^!:KaH
+('*Is!9WDDmcFN3jo>DLjo>DD!9W\Lr8n+Ljo>D\joFiHjp^\?hVQMj;SC&%F*i9&jpHI[]sPK'
+hWE\WhYuX=hWE\ojoPPFhYuX=hWE\ojpp81!9WDD!9W,<k2lXDhYuXC!9W,<!9W,<hYuXJhWE\W
+k2,7We\/?'c$QhJqrS""s7W86rrVoo`V\d(F*i7d`P&Xlc//H^!:KaH!!)rZ&HM7]!9WDD!:JtL
+k2lXDmJm7cjoFiJk5X9Dc+U3l`Ii5YHhc_1Hd072^")!%hWE\ojoXE%hYuXChWEYp!9W/#hYuXC
+!9W/#!9W/#hYuXI!9W,<!9W/#h>l[<!9W/;jpp81hWE\WhUT<H^!1o2eb/&3Hd072^")!%hWE\o
+joXE%hYuX=!9W/;jpp5JhW=e<hW=h#joF9#!<2*dhWEYp!9W,<hYuXJhWE\Wk2,7We\/?'c$QhJ
+n)at(c+UKte_]HFk2-+"!oE(rroO7^k2-+"!oE(rroO^IjoFQ+!!)0<!9WDD!8d_;#QX#D!!)0<
+!8d_;&)QI*k2tO_hUT<H^!1o2ebeJ2`W,Y-J,~>
+!i2>HqsF]Ae]kePhX9P(mJuDImJuDG!"A8q!:K";!:K7Tk3`6KmJm7bmJuDJmKr%DhT`aYeUtQt
+qsF]Ae]kePhWE\mjoF99joO?$rl+p;r8n"9rP\g"s8;!`hSoNW`W,u;joi['`W,u;joF97jp0bf
+^!5)[^#o"U$'^@4KAOj5`TH=^p&OOXp'C`mp&Og[!:Bgerq6Eome6AR!!;l^!;uNjmf)q[!!2f]
+qt:Hdp?q)"`Pp*YK9V:Yn*UF5e]kePhX9P(mJuDImK)GMrU'[Jr9adOmd:)CmK!7S!s%cO!<)?c
+!<2Bg!9W\LrpBdKqsFdQmbZ4%c..H[k54QK3Llloc2Rj@S2pK7#D:RO^!5F%k5=WIk5=WIk5#&d
+mJm7Tk3`6;mJuD;!<2Bd!;u6bk5F]Sk3h*N^!5)[^#o4[#D:RO^!5F%k5=WIk5=WJk3i3K!Uf+J
+mJuDJ!!2NMr9adO!:K7TmcON:!W_Wgr9aRIr9amRmbZ4%c..H[k4S-KP`(cYhT\("k2u[:!:KaX
+#ls\m!;?*dmJm7dp&b<_p@eIc!qu$^r:U-Yrq??l!VYsYp'gB_mcNBF`Qd7lP`(dpmK\Bpc+VBY
+mcOH8!9X4I!TjC\mJuDImKVhAmJu\C!<2Bg!:JtLrU0[crpBjgk3`6KmJuDHmKr%DhT`aYeUtQt
+qsFPHS>7UZrrT!d3W&4NP`(cYhT\("k2u[:!:KaXq>^Tb!!*#l$39Mf!;?*dp?qVSrUp6ZrUpTd
+k2+';c/+);Mj4#)#D:RO^!5F%k5=WIk5=WJk3i3K!Uf+JmJuDJ!!2NMr9adO!:K7TmcON:!W_Wg
+r9aRIr9amRmbZ4%c..H[k4S-IK@S5[c/.mNr9aRIr9aRIqu@AlmJu\C!9W_;!:K7Tmd:&TmcON:
+"9@lPmK!7S!9X1H$0L[4c+VBPK>$F9mK\Bpc+VBYmcOH8!9X4I!TjC\mJuDImKVhAmJu\C!<2Bg
+!:JtLrU0[crpBjgk3`6KmJuDHmKr%DhT`aYeUtQtqsFPHS>7Ta~>
+!m8N2qsG,Kd`/l<f&G]Oio]7_io]7_io]7s!$pP(!9W;'!9W8@ioU7'ioU7'io]7_io]7_k2PCO
+`k'1<J\'_8mK\0c_R@>4hV.VYrl5!<qqh:k!T*kRh?Cq!hT#Tqrn[dts2P*=ptc>2hU]QP_TmS@
+hY$=9M'7;q_F28pipQ+"lL*s*mcs3?mcjf?l2^)L!:K:?!:'";rW"&.l2^,;mcs6*mcs3?!:K.?
+lL+**mcs6"inD8\_U<l3M=9k,J^VQL`n'//k2PO_k2PO_k2PO_!93/#k2PO_k2PO_k2HC#joFQ'
+joFQ'!93/#jo>D@k2HC#joFQ'k2PO_k2POcio8P/]#N0L]&*>P"+A23@EnfRb/Sl,mLt0"`k'1@
+io9+[k2PO_k2PO_k2Q4;,iSe(k2PM'k2HC#joFQ'joFQ'k2PO_k2POcio8P/]#N0L]&*>P'S4]P
+]#N=\io]7_io]7_io]7_io^4?#Nk%.io]7_ir&j*k2PO_k2PO_!93,@k2PO_joFNDk2PO_k2PO_
+k2PO_imu,\`mTFLhY$=9M'7;q_F28pipQ+"lL*s*mcs3?mcjf?l2^)L!:K:?!:'";rW"&.l2^,;
+mcs6*mcs3?!:K.?lL+**mcs6"inD8\_U<l3M=9k,J^VQL`n'//k2PO_k2PO_k2PO_!93/#k2PO_
+k2PO_k2HC#joFQ'joFQ'!93/#jo>D@k2HC#joFQ'k2PO_k2POcio8P/]#N0L]&*>P"+A23@F"lS
+b/Sl,mf&%SIF>u#_V4#;lL*s*lL+**meQo,l2UhPmcjf;mJu\C!:K.?!:K:?mcs6*mdB)og;67p
+dXD+Oq!JiId`/l<f&G]Oio]7_io]7_io]7_rW!2cio]7_io]8!!%@!hk2PO_k2HC#joFQ'k2PM'
+joFQ'k2PO_k2PO_k2PCO`k'1<J\'_2mLt0"`k'1@io9+[k2PO_k2PO_k2Q:=0&l!nk2HC#k2HC#
+joFQ'!!)0@k2PM'k2PM'k2PO_k2PO_k2t[_f#G;@dXf!dn*Wo$d`/l<f&G]Oio]7_io]7_io]5#
+io]7_io]7_io]7_iW/!#!9W;'!9W8@io]7_!!)$@iW/!#!9W;'io]7_io]C_imu,\`mTFLhYZ^C
+IE'E<J,~>
+!rqu=qrS-1c+UKtc/."DhYI3Rh>dQTh?Eu:h>lEh!<1gT!;51Rc+UKt`I"uKqrST>c+UKtc.1A$
+e_\j5e_\j5e_\j5rk8@3"l@ede_\jT]dVb;hUUK5hUT=>hS&shhUUJrs1SI4hUUK5hUUK5hUU0$
+]sPJlHaMZ&jp?ruK6tkV9"id*pZ;b^k2l[+joFND!<2*\!<2-[!<;0]!;P^V!;GU_hUU/i[(X_2
+Mh?ZNjp-7X]sPJthUV;U!!)ZJ!s%37!<1gW!8cQ4rSIPSrn[_WhVJ8*h?V<=[(XG*[,1]B"3pQ>
+SBV!6p<EKs#CF_/[(X`@eb.eq!!;!W!<1gZ!8cQ4hVJ83h>dQKh?V<=[(XG*[,1]B#CF_/[(X`@
+eb%_t!;YLM!;YIR!8cQ4r8%JTh>m3)#L0rh]u>?*hY$";Mh?Y/c+Q`_e^aEV#ls,M!9WDDjo>D\
+jo>D\k5GA\jo>DVk5PGUjpKtqe\/?'c$PA$KC@q-Hd072^!5Eap"fZKo\KZMhVJ83h?*c7h>mN2
+rrE&T!s%37!;51Rc+UKt`I"uKqrS"*pA^Z-rrMi<qrS3CK7eNq]h5ugebA5&!!;9_!<2*b!9WDD
+k2l[Cjo>DVjpKtqe\+Sgc$PA$KD=R6Hd072^!5Eao\TQIq;2&Mq;)2RhVJ81h?!]6!;,+Qc+UKt
+`I"uKp#ZL+c+UKtc/."DhY[BRh?*c7h>mQ3#6<W;!8cQ4!;t[R!<1gT!;51Rc+UKt`I"uKn)ak%
+c+UKtc/."Dh>dQJh?*c7h>mQ3!s%37!<(dS!<1gW!8cQ4p"fqu]sPJlHaMZ,jo`m%s."T~>
+!h?&@qsFW/hSm1IhYuXMmcNs"mcNs"mcNp;mcNs"mJu\P!#F_b!:JtLk3h@3k3hC"k3hC"k2u*o
+hYtIreT8F\qsG2?e]#5@hVRDOk2,7Wk2,7Wk2,7>`W#lBk2,7Wk2,7>rr<#;!oE(rrP]lYhSoNW
+hWE\6`TI3_hWE\WhWE\WhWE\O`P'7@F1pH'mMhC\P^Cs*^!5Erk3hC"k3hBomcFN3mcFN;!:K^a
+*:DtW!!)HLmJu\;k3hC"k3hBo!!)HLmcN["k3i62#i<flc..0*S<WL1"`rP>]uAk-jq[=HmcNs"
+mcNs"mJu\;mcNs"mcNs"r;[;pjoFQ3joFQ3!:K";k5,,hmcFN3mcNs"mcNs"k3hBgrl"uiF1pH-
+mK52>S12__!h?&@qsFW/hSm1IhYuXMmcNs"mcNs"mcNp;mcNs"mJu\P!#F_b!:JtLk3h@3k3hC"
+k3hC"k2u*ohYtIreT8F\qsFW/hSm1IhYuXZmcNs"mcNs"mcNp;!9W_3mcNs"mcNp;mcNp;!9W_3
+r;[]&joFQ3k3h@3!:K";k3hC"k3hC"k3hBgrl"uiF1pH'mMhC\P^Cs*^!5Erk3hC"k3hBomcFN3
+mcFN;!:K^a*:DtW!!)HLmJu\;k3hC"k3hBo!!)HLmcN["k3i62#i<flc..0*S<WL1"`rP>]uAk-
+jq[=HmcNs"mcNs"mJu\;mcNs"mcNs"r;[;pjoFQ3joFQ3!:K";k5,,hmcFN3mcNs"mcNs"k3hBg
+rl"uiF1pH-mK52>S12b`!h?&@qsGDfS<SBNc+VBYk2u*omcNs"k3h@3k3hBomJu\P!"eS\!9WDD
+k3h@3k2u*omcNs9jp9hg^!5)SPan!5mKI[g`P'7IroP<jk3hC"k3hC"k3`3Lk3hC"k3hC"k3`6;
+k3`3Lk3hC1!#Y.d!9W_3mcFKLmcNs"mcNs"mcNs"mcNC*`<4Y3^#&GM"`rP>]uAk-jra$RmcNs"
+mcNs"mJu\;mcNs"!9W\LmcNp;mcFN3mcOKK'^"iG!9W_3!9W_3mcNs"mcN["k2-*V"4_J+hXBk9
+F5FmL`SUUV(%15Pk3hC"k3hC"!:K";k3hC"k3hC1!"JAY!9W_3!9W\LmcNs"qZ%/pjoFQ3k3hC"
+k3hBomcNC*`<4Y3^#&YS"#6UA.=_~>
+!liB.qsFZ2d_`T4f&$&Y!!)rV!<D-V!<;$\!92u<ro*nXp>QA7f###8dWN.XqsFW-cG$a$f)FA3
+hV-i?hV-i?hV-i+`r>uChV-i?hV-i+rr<#<!nuMbrPfQOg;a0Lg>:Q'`npaPg>:Q?g>:Q?rn7V.
+^:(c$EOt$"mf&=PFj@k4_UeG?!!*#X!s%<\iqi`Tir9#XiW&uQir9#RiWn?"f"stpc?9,Kn*UC&
+d_`T4f&$&Y!!)cQr;clW!!*#X!s%??!<(pS!<;$Y!;>CXhU]QT_U<S<hYZ^CH-4-8c2Rjbb'EmP
+#'JA2]#*%To\oiNr8I_Wiqi`UiWB2?iW/u;!!)`P#i=.L]#)m<]&*>P#'JA2]#*%To]#lNpYl/Q
+ro3qXro3kVs5F"Yr8R_Vo\p/5f###8dWN.Xp$VgA"a/,-[_gVhiW&uXiWB2?!93kUro3qXro*nX
+pYu2Qpu2P8imtt;_Tm<'Omh]BFje.<_UdT9iW&uQir&lWiW&uXiWB2?iW/r:qZ-ZU!!)`P#i=.L
+]#)m<]&*>P"*r&/@F"lS`l`T(mf&=PFj@k4_UeG?!!)rV!<D-V!<;$\!92u<ro*nXpu2P8imtuT
+_Tm<'One>KFje.<_UdT9ir9#QiW&uXir9#Xir&lWiW&uVir9#NiX"Dl_RdV4Fh6H&mKRg^_RdV8
+hXoe-!;kaX!92u<ro+"[io0t;ir/rWiW&uXiW&uPiX"Dl_RdV4Fh6GumKRg^_RdV8hXoe-!;GLO
+!<;$Y!<1s[!92u<rSm\Ss5F"Yp>QA7f###8dWN.XqsFQ3b/Rk?~>
+!quZ5qrSi4c*Xjkc.1\$hUUK5hUUK5hUUH_hUUK5h>lF0!$0VH!8c6+e_\gVe_\j5e_\j5e^`O,
+c+UKkc"aW9qrS&sc*Xjkc1BKc^&J'.eH!;^s8Te3ec!/`s4+g_rRLq]!S.5CeHa@4['\(m[+4j3
+regr$`P&@dc2QQ"ec+D5e_]05!8cS_!8[_4qZ-WPrr<>]e_U;_e_]05rn[b-h>dQTh@8#lhUUK>
+e_\Qa;SC%jrep7-*brs,[(X`7hUUK5hUUK5hUUK5h>lE_hUUK5hUUK5r;[;`eH".VeH".V!8c8_
+eb]=^hUMVVhUUK5hUUK5e_\j$]sP/kC:)Ogjo`U&p8#t5!quZ5qrSi4c*Xjkc.1\$hUUK5hUUK5
+hUUH_hUUK5h>lF0!$0VH!8c6+e_\gVe_\j5e_\j5e^`O,c+UKkc"aW9qrT;Ac*Xjkc.1\$hUUK5
+hUUK5hUUH_!7frVhUUK5hUUH_hUUH_!7frVr;[qreH".Ve_\gV!8c8_e_\j5e_\j5e_\j$]sP/k
+C:)Oak5L8BF2bho^!6Q5!7h)*$e=+jeH"I_eH"G+hYR<PhZ!Q]hUUH_hUUK>ec+D-e_U9+rn\+7
+hVQf>hUUK-]i)P_F8h*djrS9^['[Nke_\j5e_\j5e_\j5e_U;_e_\j5e_\j5eboIWhUMVVhUMVV
+h>lE_hUVK'(>dRAe_\j5e_\j5e^`O,c+UKkc"aW9qrS""s7W86rrVoo`V\fsMZn1@]r\olrn[Y*
+rn\%5hVQc_hVQf>h>lF0!<:m`!7fp+e_]-_e_]05rn[t3hUUK-]r\odF8h*mjsXuh['[Nke_\j5
+e_\j5e_\j5e_U9+e_\j5e_\j5e_U;_e_U9+e_\jT!$C(J!7frVhUMT+hUUK5hUUK5hUUK5hUTla
+['\(m[+4j3-u.#6[(X`7hUUK5hUUK5hUUK5h>lE_hUUK5!7fp+hUUH_hUMVVhUVT*)qEfq!7frV
+!7frVhUUK5hUU05e]ke7[*<?meaMWAC<a,m^!5*ae_\j5e_\j5e_\j5!8c8_e_\j5e_\jT!"If8
+!7frV!7fp+hUUK5qZ%DgeH".Ve_\j5e_\j,hUTla['\(m[+5'9"3(<6Ujr~>
+!i2>HqsFW/e]kePhXfk0!;ts]!9O7]qrRt\k2l[Cjo>DSjp0bf^!5)K^#o4[9QSb/]uAOahWE\W
+hWE\WhWE\WhWFjW`TH%>hWE\WhSoNWhWDfWhSn@Os2G$#`W+fWhWDfW`TH%>hWE\WhWE\WhWEA-
+^!5)K^#o"UrhL6ChShLohWF7gmcNs"mdB6*!:K";rW!8e!!)HTk3hC"k5G?!mcFN3mdB6*k3h@3
+!9W_3mcNs*k3hC"k2tP"`<"h1rhT#N"`r5=^!5F*k5PGWjo>D\joYVGjoGDC!s%KG!<)'[!;kmY
+!;5IZhT`aYeT8FdqsFPHS>7UYrrT!d3W&4JF4JOKc//'S!!)rZ!s%H`!;km\!9WDDroO1\p#ZM9
+c+VBPF1p`5mKI[^c+VBYn`KiOq;qYWrT41^k2l[CjoYVGjoG>A!W_?_o]?D8c+VBPF1p`/mf'!r
+C>Qoi`STbFk3hC"k3h["mJu\;mf!1mjo>DLmcNs"mcOKK)Xc_fk3h["mcNs"!!)0Lk3hC"mcNs"
+mcNZgrl"opCAt$tmKI[^c+VBYoB-&Qq;qYWroO:_k2l[CjoYVGjoGABrrDrY!!)]S#N!_=c.-mK
+k54QK3LllocMmsAS2pK7rhMPhhShLohWF7gmcNs"mdB6*!:K";mcFN3!!)HTk3hC"!:K7TmcNp;
+mdB6*k3hC"mcNZg`AtooCAt%(mKI[^c+VBYn`KiOq;qYWrT41^k2l[CjoYVGjoG>A!W_?_o]?D8
+c+VBPF1p`/mKI[^c+VBYoB$#QqrRt\k2l[CjoYVGjoG>ArrE)]!!*#\!!)]S#N!_=c.-mKk3q^A
+F4JOKc//'SrrDlW!!*#\!s%KG!<2*_!9WDDrT=+[qrRkYp#ZM9c+VBPF1p`5mK5J>Ua^f~>
+!m8N2qsH[cd`/l8f&#9ChW!DOhW!DOhW!AlhW!DOh>lC4!92kphW!AlhVnOphVnOphW!DOhW!DO
+iniPC_Rdb8D7\U$mS%KC_R@>0g=kE;hV-i?hV-i?hV-id`l?lhhV-i?hV-!LhV-i+s4YKHs8U+=
+hT#TLhV-i+s2NpLhV-i?hV-i?hV-]3_R@>,D7\Tsmf&a]C!sjd_UdT<iW&uXir/oZiW&uTir/rX
+iW&uSir9#Pir@j=f###8dV8]On*Wned`/l8f&#9ChW!DOhW!DOhW!Al!92kphW!DOh>lElh>lEl
+!92kp!92i8hW!DO!!(m8hW!DO!92kphW!DOhW!POhU]QT`mS_8hYZ^CIE'E<c2Rjf`dRaP5Aeig
+]#*%ThW!DOhW!DOhW!DOh>lElhW!Alh>dQ8hW!DOh>lEl!92kp!92kphW!DOhW!POhU]QT`mS_8
+hYZ_7D:6G8_UdT#ini\Oini\Oini\OinaY8ini\Oini\O!8c_liW.up!8c_l!8c]8ini\OiW.s<
+ini\Oini\Oini\OhU]QT`mS_8hY$=9SH`fV_F28lhY6"0!<2!W!!;-[!;b^S!<;$Y!;YXS!;>FP
+h?DKI]#)m0rgiNG9l8=u]#*%ThW!DOhW!DOhW!DOh>dQ8hW!DOhW!AlhW!AlhVnOphVnOph>lEl
+hVnM8hW!DOhVnOphW!DOhW!DOiniPC_Rdb8D7\U$mK7mWb$iTq!m8N2qsOHS#&2N&7)IO3pYl/Q
+r8IeYiW&uUiWB2?iW/u;!!)fRs5!q1_F28hC&X[umS%KG`k'%<hVR8Kini\Oini\Oini\O!!)$8
+ini\Oina[liniYpina[lina[liW.upiniYpiW.upini\Oini\OiniPC_Rdb8D7\TsmRM-B`k'%<
+hVR8Kini\Oini\Oina[lini\OiW.up!8c_l!8c]8ini\OiW&u8iW.upiW.upini\Oini\ShVQi#
+]#N08]&)oD9l8=u]#*%ThW!DOhW!DOhW!DOh>dQ8hW!DOhW!AlhW!AlhVnOphVnOph>lElhVnM8
+hW!DOhVnOphW!DOhW!DOiniPC_Rdb8D7\U$mK7mWb$ff~>
+!rqu=qrU+X`P&Xlc/."-e_\j5e_\j5e_\gVe_\j5eH","!8c8_e_\gVe_U;_e_U;_e_\j5e_\j5
+hUUK-]r\olC:)jpjooM=]sPJtqpb]'r7)#.e^a]5^#&\;'&M0Ps4,ZV^&QWrec5Z_s4+g_rRCt_
+s1SB]!8dP%#L0r`^!1<!hY$"=S<TOQc+Q`_c.1\$rn[q2hVQf>!8c8_rW!,Y!!(m4ec+D*ec#RK
+h?3i/hVQf^h?2:.!7h)*"4c8bec+G)eH`dp^!1#VPaq4)9kqY\[(X`@e_\j5e_\j5e_\j5eGoU+
+e_\j5e_\gVe_\gVe_U;_e_U;_eH".Ve_U9+e_\j5e_U;_e_\j5e_\j5hUUK-]r\olC:)jpjo`m%
+s.%=5!VXe8k!*V"]sPJthUUK5hUUK5hUUK5hUMVVhUUK5!7_&LhUUK5hUMVVh>lE_h>lE_hUUK5
+hUUK>e_\QaXM)kn[,1]B9PVP[[(X`@e_\j5e_\j5e_\j5e_\gV!8c8_e_\j5eH".Ve_U;_eH".V
+eH".V!8c8_e_U;_!8c8_e_\j5e_\j5e_\QaXM)kn[,1K<$_3HO@a2SY^!5*aec+D2e_]05h>lE_
+hYmKYh>dQ4hUVV^!7h&Ks5!kYe_]05rn[b-!!(RKh?2<bhUVV^rm_7e[(X^nS<TQ4k"TU0]sPJt
+hUUK5hUUK5hUUK5hUMT+hUUK5hUUK5!7frV!7fp+hUUH_hUMVVhUUH_!7frVhUUH_hUUK5hUUK5
+hVQf>c+U3lc"aWBqrS"*pA^Z-rrMi<qrS9VPal4-]h5u_e_\jUh@\;phUUH_hUUK>eH"G+!8cS_
+rn[_WhVJ83h?*c7hUVV^!nH/arm_7e9"iJYS<TQ=k"KO/]sPJthUUK5hUUK5hUUK5hUUK5!!(m+
+hUUK5hUMVVhUUH_hUMVVhUMVVh>lE_hUUH_h>lE_hUUK5hUUK5hUUK-]r\olC:)jjk!s1*]sPJt
+hUUK5hUUK5hUUK5hUMVVhUUK5h>lE_!7frV!7fp+hUUK5h>dQ+h>lE_h>lE_hUUK5hUUK>e_\Qa
+XM)kn[,1969kqY\[(X`@e_\j5e_\j5e_\j5eGoU+e_\j5e_\gVe_\gVe_U;_e_U;_eH".Ve_U9+
+e_\j5e_U;_e_\j5e_\j5hUUK-]r\olC:)jpjo`m%s."T~>
+!h?&@qsFJoec*PfhDjZSk2,7Wk2,7Wk2,5#k2,7WjoFQ#!8ckpk2,5#k2$*pjo>D<k2,7Wk2,7W
+hWE\O`P'7I@_LXqmKI(M`P&t8nD46H`Pq`2!QG*<h@%=&hSoNOhSoNO`Pqf4"3(;s`Ur$e]`c=)
+@_LXkmL$&&XCB`)]uAOahYuXLhWEtWk2l[#k2tM#!9W,<k2-+"$JkdFh>l^#!9WG#roX4\!Tr8<
+joaK&k2-+"s5"(EhShe*eRGVeXRGQX@b(Iss5$6-hWE\WhWE\WhWE\Wh>dQ<hWEYphW=h#hW=h#
+h>lEph>lEp!!(m<hW=h#hWE\Wh>lEphWE\WhWE\Ok2+t6]uAi;^#&YS"#6UA.F%koS>7n:mK$eI
+rl+oo39K)[hWE\WhWE\WhW=h#hWE\W!9W,<hWE\WhW=h#h>lEp!!(m<hWE\WhWE\Ok2+t6]uAi;
+^#&YS!FjUY`W+d`k2,7Wk2,7Wk2,7Wk2,7Wjo>D<k2,7WjoFQ#k2$*pjoFQ#joFQ#!!)0<k2$*p
+joFQ#k2,7Wk2,7Wk2+t6]uAi;^#&GM$EUV9@b&`:`RX,-roOgLk2tO_joF9#k2$(<k2$+#hYuXE
+h>l]p!9WDDk2tP"k5PD^k2-+""5`2&hYu[;h?i?$`Bhc!@]Zr<n*U3cec*PfhF?Yak2,7Wk2,7W
+k2,7W!!)0<k2$*pjoFQ#joFQ#!8ckp!8ci<!8ckpjoFQ#k2,7W!8ckpk2,7Wk2+tWhVQ5b`SP(;
+hYZ^C0r1<gcMms9UbVc7$EUV9@b&`:`RX,-roOgLk2tO_joF9#k2,5#k2$+#hYuXEh>l]p!9WDD
+!9W/;jpp81k2+tWhSm1QeRGVeXSD2a@b(Iss5$3,hWE\WhWE\WhWE\WhWE\W!!(m<hWE\W!9W/#
+h>lEp!9W/#!9W,<!9W/#h>lEp!9W/#hWE\WhWE\WhVQ5b`SP(;hY$:;@b(Iss5$$'hWE\WhWE\W
+hWE\W!9W/#hWEYphW=h#hW=h#h>lEphWE\W!9W,<hWEYphWE\WhWE\WhVRDOhSm1IhI=1Tn*U3c
+ec*PfhF?Yak2,7Wk2,7Wk2,7W!!)0<k2$*pjoFQ#joFQ#!8ckp!8ci<!8ckpjoFQ#k2,7W!8ckp
+k2,7Wk2+tWhVQ5b`SP(;hYZ^C0r1<gJ,~>
+!liB.qsFYsd_`T0f%U,[2;6p@hV-i?hV-fdhV-i?h>lEd!8?;`hV-fdhV%t`h>dQ0hV-i?hV-i?
+hVQu;^:M20@Ck=mmKR+F^:(c(f)FA]f%S^/f%S^/f%S^/f)Nb0f%S^/f%S.Df%S]ps4YKmf%S.D
+f#G_`f%S]ps4YKHf%S^/f%S^Sg'H9X^:(c$@Ck=gmf'3j@Eu`u_U@04h>dQShZ!TUh>dQQh?Eu:
+h>lEh!;kXQ!;,.Jg',pA8A`Y\ri5GT#%>rs]"ZbLrn^#rhV-i?hV-i?hV%r0hV-i?!8?90hV-fd
+hV%t`hV%t`h>dQ0hV-fdhV-i?hV%t`hV-i?hV-i?hVQu;^:M20@Ck=mmK7aW`aR-l!liB.qsFYs
+d_`T0f%U,[2;6p@hV-i?hV-fdhV-i?h>lEd!8?;`hV-fdhV%t`h>dQ0hV-i?hV-i?hVQu;^:M20
+@Ck=mmKR+J_RdJ4gA]qeg>:Q?g>:Q?g>:Q?g>2f0g>:Q?g>2hdg>:N`g>2hdg>2hdg&M-0g>:N`
+g>2hdg>:Q?g>:Q_h?_id^:M20@Ck=gmf'3j@Eu`u_U@04h>dQShZ!TUh>dQQh?Eu:h>lEh!;kXQ
+!;,.Jg',pA8A`Y\ri5GT#%>rs]"ZbLrn^#rhV-i?hV-i?hV%r0hV-i?!8?90hV-fdhV%t`hV%t`
+h>dQ0hV-fdhV-i?hV%t`hV-i?hV-i?hVQu;^:M20@Ck=mmK7aW`aR0m!liB.qsOH`#%>fo[_gJH
+pYGlMr8%MUhVJ80h?O&;h>lEh!!)fNs4RY)_R@>,@K*;%mKR+J_RdJ4gA]qeg>:Q?g>:Q?g>:Q?
+g>2f0g>:Q?g>2hdg>:N`g>2hdg>2hdg&M-0g>:N`g>2hdg>:Q?g>:Q_h?_id^:M20@Ck=gmKR+J
+_RdJ4gA]qlg>:Q?g>:Q?g>2hdg>:Q?g&Tj`!8cGd!8cE0g>:Q?g>2hdg&Tj`g&Tj`g>:Q?g>:Q?
+hV-Pp]#)m(]&)oD#%>rs]"ZbLrn^#rhV-i?hV-i?hV%r0hV-i?!8?90hV-fdhV%t`hV%t`h>dQ0
+hV-fdhV-i?hV%t`hV-i?hV-i?hVQu;^:M20@Ck=mmK7aW`aOA~>
+!quZ5qrS)dc+UKkc-?7<29j[re]lXhe]lVEe]lXheH".E!6s'=e]lVEe]e*=eGoToe]lXhe]lXh
+e^_ph['[Nk>-uiWjp##6]sP/kc2Q6Oc.1(hc.1(hc.1(hc2YJjc.1(hc.0N-c.1(Ps4+g_c.0N-
+c+Ug@c.1(Ps4+g5c.1(hc.1)<ec3noZin(e>-uiQk5M.[@`?$^^!69$!!)uJrrE)L!!)oH"p!3(
+!7fU"qpk]Ho[O2ke]kd*]u=I[V!mFM>0Xaf[*?kpeO.U3c.1(hc.1(hbl@aoc.1&=c.)gEc.)gE
+blH#=blH#=!!(9oc.)gEc.1(hblH#=c.1(hc.1(he]l@G[(X^f[+5'9"3(<6Us8o@pA`,/jp##6
+]sP/kc2Q6Nc.1(hc.1(hc.)gEc.1(h!7f<oc.1(hc.)gEblH#=!!(9oc.1(hc.1(he]l@G[(X^f
+[+5'9#$T9b['\*&rm`pOe]lXhe]lXhe]lXheGoToe]lXheH".Ee]e*=eH".EeH".E!!(Qoe]e*=
+eH".Ee]lXhe]n*Ds3:SN"MN&`[+4j3rhK^,`P&@dc1]Zf!<(IJ!<:RL!;k:N!7fU"e^XZsec,XA
+eHa@Lc+R#g`FAhBn)agXc+UKkc-?7<6d=0+e]lXhe]lXh!!(Qoe]e*=eH".EeH".E!6s'=!6s$o
+!6s'=eH".Ee]lXh!6s'=e]lXhe]lXpc-<W&^!0`febeJ2`W,Y-cMmt>s2FltrhK^,`P&@dc1]Zf
+!;t@L!7fU"qpboOe^XZMeGoUEeHa@Lc+U3l`FAhBpuVcac+UKkc-?7<2U0dse]lXhe]lXhe]lVE
+!6s'=e]lVEe]lXh!6s$oe]lVEe]e'oe]lXh!6s$oe]lXhe]lXhrmh%ns0MpBc!%L)p#ZH^c+UKk
+c-?7<4jDO%e]lXhe]lVEe]lXhe]e*=eH".EeH".E!6s'=e]lVEe]e*=e]e*=e]lXhe]lXhe^_ph
+['[Nk>-uiKjp##6]sP/kc2Q6\c.1(hc.1(hc.1&=!7f?EblH#=!7f?E!7f<oc.1&=c.)doc.1(h
+!7f?Ec.1&=c.1(hc.1(hc.1@hc*Xjkc!%L)qrS""s7W7=~>
+!i2>HqsGJ6e]kePhWE\WhWE\WhWE\WhWEYphWE\Wh>lEphYdEWk2$*pk5>8ohWE\WhWE\WhWEtW
+k2+@rc.-::k54QR@b&`:`RWi%k2,8"h?)irk5O3Ck2,7WhZ*W4k5O68`<+orhYY7mk2-'U#3No)
+hSmIrrn\.IhWE\WhVQf%^!5):^#o"U$,sTs>2ILa`STJNjoF98jo>D[k5PD_hWEu!!"%K^!9WDD
+!8[\UrT4+:qrRn8qrS=Dk2tOW`Pp*Y>/e1on*Up"e]kePhWE\WhWE\WhWE\WhWE\WhY[?ThWE\l
+!!q]ek2,5#k2,8!!!1s=r;[VijoFQ#k2,7Wk2,7_hWE\>^!5):^#o4["$)mI.F%koUmsIBmN#ce
+c+VBYk2,7Wk2,7Wk2,7Wk2$*pk2,7W!8ckpr;Zu_h>lEpr;[Pgk2,7Wk2,7Wk2tO_hT`aYeRH5S
+qsGP8e]kePhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\m!!;$>hYR9Rk2-%:)!1h\h>dQ<hWE\W
+hWE\WhWE\>^!5):^#o"U$,sTs>2ILa`STJNjoF98jo>D[k5PD_hWEu!!"%K^!9WDD!8[\UrT4+:
+qrRn8qrS=Dk2tOW`Pp*Y>/e1on*Up"e]kePhWE\WhWE\WhWE\WhWE\WhY[?ThWE\l!!q]ek2,5#
+k2,8!!!1s=r;[VijoFQ#k2,7Wk2,7_hWE\>^!5):^#o4["$)mI.F.qpUmsIBmKpkG`EM-C3Q9k3
+roO4;qrRkYr8n(]hWEu!!!M0@!9WGB!;tsZhYcO9h?V"[c/)XC]uBd7+(EdF^!5ErhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhY[?ThWE\l!!26=r;[\s!9W,<!9W/#hWE\WhWE\WhT`aYeRH5Sp$O2:
+e]kePhWE\WhWE\WhWE\WhWEYphWE\WhW=h#h>lEph>lEp!9W/:!#t(WjoFQ#joFQ#k2,7Wk2,7_
+hWE\>^!5):^#neO'k5_<^!5ErhWE\WhWE\WhWE\WhWE\m!!;$>hYR9YjoFQ#joFQ#k5>8\hWFb:
+(>e0Rk2,7Wk2,7Wk2tO_hT`aYeRH5SqsFPHS>7Ta~>
+!m8N2qsGJ1d`/l8db<F3g>:Q?g>:Q?g>:N`g>:Q?g&Tj`gAM!ShV%t`hYdEgg>:Q?g>:Q?g>:]?
+g=!jL`mS/(hYZ^_?-^<q^=(`dg=G!/g=G!/g=G!/g=G!/gAh3(g=G!/r5Jfhs47(e!SZ-'`YdFL
+s4530g=G!/g=G!/g=G!+_R@>,?+Sncmf'd9=k:SX_UdGtg>:Q?g>:]?h>lEdhVJ54g>:Q^!%$>!
+!8cQ4!87DQhVQuCg>:Q?hV-i?hV-iCg>:Q?hV-Pt^;e`,rjqRd'j]8-]#)nLg>:Q?g>:Q?g>:Q?
+g>:Q]!!:m2gA:jUh>lEdh>lEdhYdETg>;c.(>@UFhV-i?hV-i?hVQu?d_`T8dTsH@qsFQ7`l_`7
+rrU?_IJ`FQ?.-a(_U@/lhV-i?hV-i?hV-i?!8?;`hV%t`hV.o."Q%i4g>;c.'\_EthV-i?hV-iC
+g=jul]#N0(]&*>P+'m=7]#)nLg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?gACpPg>:Q\!!1s1r;[\k
+!8cE0!8cGdg>:Q?g>:Q;d_`T8dTsH@p$Vgj)HkY25f2++hV-i?hV-iCg>2hdg>:Zd!8?;`r;\.t
+!!(m4!!(^Q!8cSdhV-i?hVQuCg>:Q?hV-i?hVQu;_S4%@=oQ#$mM0$U`k'%8g=kE;hV-i?hV-i?
+hV-i?qu?fPhV.i,#i5R<g>2hdg>;c.!SZE/!#F;F!8cGdg>:Q?g>:]?g=!jL`mS/(hYZ^CIE'E<
+cMmsg`dRaPrjj"Nf#Btlf%T!7hV-i?hVQuC!8cGdhV%t`hV.o."PV]4hVS22#MS%kg>:Q?gA]q5
+g=F,+`n";l](k\8?.-a(_U@/lhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?qu?fPhV.i,!T)Q/!#XPm
+hV%r0hV-i?hV-i?hV-]3_Rdb8?+SncmO);g`k'%8g=kE;hV-i?hV-i?hV%t`hV-i?h>lEd!8?;`
+!8?90hV.o.)rB<*!8cGd!8cGdg>:Q?g>:]?g=!jL`mS/(hXBkI?.-a(_U@/lhV-i?hV-i?hV-i?
+hV.l-!nuMbqZ$oY!8cGd!8cGdr;ZlPhYdEig>2hdg>:Q?g>:Q?hV-]3_Rdb8?+SnimK7mWb$ff~>
+!rqu=qrS&cc+UKtc1BHc!;t@I!<1OI!<:RN!7fWu!;+eHc+UKtc!%L2qrS&cc+UKtc0j-^s8:FF
+]`Qaaebd&[ec!/be\2"5]tO-i#L0rh^!0`fhY$%1Zis@P]h5u_p=0-CrRLoJrmgrI$.T"Ue^XX"
+eGoU8eHO42[(X^^rj;.V"^90a[(X`SebfFHeb]=IeH#U!!!*#Kr;clJr;clJ!!)]B#L0rh^!0`f
+hYZF;c1_1-bl7_;c26W,>0Xaf^!60!!!)rI!!*#Kr;clJ!W^d$r;cK?#L0rh^!0`fhYZF=>0Xaf
+^!5`jquH`HqZ-ZHr;[#O!7fU"!;=qJc+UKtc!%L2p#c7\"]EUY9"iLCeGoUJec,XKeboISeGoU"
+eGoU"!!)?8"jO`f^!0IS[.!,\>0Xaf^!6)tquH`HqZ$ZI!<1LK!<1OI!<:UJ!<:RL!;4kIc+UKt
+c!%L2qrS"*pA^Z-rrMi<qr[mb"]EUY9"iLCeGoUIeGoUKeboLJeH,a$eboL@eHO429"iJIrj;I_
+"^90a[(X`IebfFHeb]@HeboIOeH".M!!)`C#L0rh^!0`fhY$"7>0Xaf^!60!!!)oH!s$m%!<1LP
+!7fU"e^aTurm^uKrm^uKp!j;l]sPJt>.!/Tjonr5]sPJtn^[O;rmglG!S%2LeGoUKeboLJeboLJ
+eGoUBeHa@4[(X^f[,1]B"3pQ>S:C~>
+!h?&@qsH[HhTa$YhVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2$*pk2,7Wk2,7Wk2,7W
+hWE\O`Pp*Y;SCramKHM=`P'7@k2-%9rndPPs5*_S"lB:9hZ*WMh?VTM]uAN"^#&GM9#]&o;VosC
+c.1t5k2,7Wk2+tWhWE\WhVRDOk2,7WhWE\WhWE\Ok2,7Wk2+tWhWE\WhVRDOk2,7WhWE\WhVRDF
+brO>2;T6o"n*WnJhTa$YhVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2+tWhVQ5jc/)@3hYZ^C0r1<gc2Rj8UbVc75>p@_`Pp]jk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W!8ckpk2,7Wk2,7Wk2+tWhVQ5jc/)@3hYZ_7;Vo[;`STJ6
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hVQ5jc/)@3hY$;/`QcA"hUTTie`P`NhWE\WhVRDOk2,7WhWE\WhWE\Ok2,7Wk2+tWhWE\WhVRDO
+k2,7WhWE\WhWE\Ok2,7WhWEA53Ruta`QcBjmS-U9c,IZYhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOhSmIYhGV&DqsFP@UmrmZrrS^d
+1&LAo`QcA"hUTTie`P`NhWE\WhVRDOk2,7WhWE\WhWE\Ok2,7Wk2+qphWE\WhVRDOk2,8"h?i>p
+c,J5i;T6o"q!LgRhTa$YhVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7WhSmIYhGV&Dp$P=JhTa$YhVRDOk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WhWE\O`Pp*Y;SCrUmS-U9c,IZYhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDOhSmIY
+hGV&DqsFP@Umrla~>
+!liB.qsFVff#GG@dbrgZ!:ebJf##/@elB<<qsGS'd_`T0dam.'g=G!/g=G!/g=G!/g=G!/g=G!/
+g=G!/r;QiLg=H0$!SZ-'rtjDhg=H<(g=G!/g=G!/g=F]d]#)ll]&*,J#f=Tu:tEe'`mVr^#h$^X
+b19D+`kq34"]a-n^;A=7g'?3G^;e`(]&*>P"*r&/@EnfR`l`T(mKHVA`kK=<i7\/2n_+6!_S4%@
+<P%&amKHVA`kK=<_V,7G_S4%@<P%&[mKg\L_GJh+^;eUBg'H-H5g%YS_T'I]mKHVA`kK=<_:f.F
+_S4%@<P%&amK7aW`aR0m!liB.qsFa,`kkR'b.bmDj4XJ5o%FAt`kKUH:r:5hq!J;cf#GG@d_a]C
+f##/@elB<<p$Mu`f#GG@d`:&Hf##/@elB<<n*U?Zf#GG@d_XWBf##/@elB<<qsFQ3b/Rk?~>
+!quZ5qrU+@c+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]e*=e]lXhe]lXhe]lXh
+c.1(`]sPJt;RG!OjrdRH]sPJtc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1):rrUHqc27MAe]n'm
+(Y/Q9c2[goc.1(hc.1(hc-<r/^!0H^eb/)(]gPK;`O*>'e]lXhe]lXhc.1(hc.1(`e]lXhe]l@h
+c.1(hc-=e`e]lXhc.1(hc.1(`e]lXhe]l@hc.1(`e]kd"`Q_$S^$k)X;U)n^^!4gPc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(`e]l@P[(X^^
+[+5'9"3(<6Us8o@pA`,/k!)bg]sPJtc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hblH#=
+c.1(hc.1(hc.1(`e]l@P[(X^^[+5'99N'-K[(X`/e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]l@P[(X^^[+4j3rk1]lc,I''c.1(hc.1(h
+c-=e`e]lXhc.1(hc.1(`e]lXhe]l@hc.1(hc-=e`e]lXhc.1(hc.1(`e]lXhc.1(P9#]%Irk7d_
+9iB6L[(X`/e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhc.1(`]sPJt;RG!Ojo`U&p8$"6!quZ5qr[mk01sL.[(X`7c.1(hc.1(`e]lXhe]l@h
+c.1(hc-=e`e]lXhblH#=c.1(`e]lXhec*ete]ke7`Q_$S^%g_`;U)n^^!4gPc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc-<r/^!0H^eb/&p
+;U)n^^!4gPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c-=e`c+UKtbu1q!n)d>Bc+UKtc-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]l@hc-<r/^!0H^ebeJ2`W,Y-J,~>
+!i2>HqsFVchUTTiec+\;hWE\WhWE\WhWFS5,NdkFhWE\WhWE\W!9W/#hWE\WhWE\WhWEtWk2+A%
+e_X3;k54QN;VosCc.1tSh>l^9h>l^9h>l^9h>l^6`W"]ok5='9k5='9k5='9k5*p?k1._qe_X3;
+k4S0BeI^S0hUO@*hVRDOk2,7Wk2tOq!&!Ejk2tO_hWE\Wk2,7Wk2,7_hWE\WhWEtWk2,7Wk2tO_
+hWEtWhTa<qk"=1ShXBk9;VosCc.2gU$/Xh$k2,7Wk2,7p!&39lhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\Wk2,7Wc,J5i;SD5imK5J>UaaRg!i2>HqsFVchUTTiec+\;hWE\WhWE\W
+hWFS5,NdkFhWE\WhWE\W!9W/#hWE\WhWE\WhWEtWk2+A%e_X3;k54QM;VosCc.2gU(#J*0k2,7W
+k2,7Wk2,7Wk2,7Wk2,7r!%$LahWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhTa$ihGV&Lp$Vk1
+&Dg%9eM5>*hWE\WhWE\Wk2,k50';$Qk2,7Wk2,7_hWE\WhWEtWk2,7Wk2tO_hWE\Wk2,7Wk2tOW
+c-=f$9%DJKn*U?WhUTTiec+\;hWE\WhWE\WhWFP40](sKk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7_hWE\>`RWgC^#o4["$)mI.F.qpUmsIBmf1fKhFcYT1!SS3k2,7Wk2,7_hY7'd
+k2,7_hWE\WhWEr#k2,7Wk2tO_hWE\ok5X9Cbq[c29%DJKq!J;`hUTTiec+\GhWE\WhWE\WhWE\W
+hWE\WhWE\WhWFV6-/Re@k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wc,J5i;SD5cmKHMFe]#e`
+roOODk2,7Wk2,7Wk5#'0k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7_hWE\>`RWgC
+^#neO"]F4-`Qcs4jpBo,hWE\WhWE\WpAco(k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2tO_hTa$ihGV&LqsFPHS>7Ta~>
+!m8N2qsG(jf$;.Pdb`^7g>:Q?g>:Q?g>;T),Mq/2g>:Q?g>:Q?!8cGdg>:Q?g>:Q?g>:]?hU]]`
+cIP\#hYZ^E9\.A#_UAG;("V*ig=G!/g=G!/g=G!/g=G!/g=G!R`Z!F^f%S^/f%S^/f%S^/f%S^/
+f%S^/f%S^/f)FA.d`0#DekE[3p$NI@cI,8;c8`hpg>:Q?g>:Q?hV.`)0&G==hV-i?hV-iCg>:Q?
+g>:]?hV-i?hVQuCg>:Q?hV-i?hVQu;`l?<X8CGf3n*Uf^f$;.Pdb`^7g>:Q?g>:Q?g>;Q(0\YC;
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-iCg>:E#_Tp_+]&*>P"+A23@EnfRb/Sl,
+mLi4EcGITLhV-i?hV-i?hV-i?hY7'qhV-i?hV-i?hV-fdhV-i?hV-i?hV-i?hVQuCf#GSPekE[3
+qsGM!f$;.Pdb`^7g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>;W*-/.50hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i;`kp$P9Y0*RmLmsndR`*;36'P'hV-i?hV-iCg@tY#hV-iCg>:Q?g>:]?hV-i?hVQuC
+g>:Q?hV-i?hV-iCg>:Q?hV-Q#`m3:/da$;0mLi4EcGITLhV-i?hV-i?hV-i?hY."(g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:]?hU]]`cIP\#hYZ^CIE'E<cMmsg`dRaP'%5(R
+8D;?K`n&l#g>:Q?g>:]?p]))dg>:]?hV-i?hVJ7hg>:Q?hV-i?hV.tc$/3tM36p5Kda$;9mN,'Q
+cGITLhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hY@-tg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:E#_Tp_+]&*,J&kpm%_T($\g>:Q?g>:Q?g>:Q?q>`,(g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:]?hU]]`cIP\#hXBkF9\.M+`mW_thV-i?hV-i?hV-i\!&3-`g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?hV-i;`kp$P9Y0*XmK7mWb$ff~>
+!rqu=qrS&Sc,IB0c1KQ]!;=qC!:eSEc+UL'bt>A"qrS&Sc,IB0c03^R^#RWJc+UL'bt>A"p#ZS*
+`Q^^!`Bh2^c1oia!8?!']`lC*6-[Bnn)adGc,IB0c1KQ\!8,g,c+UL'bt>A"qrS"*pA^Z,rrMi<
+qrS&Sc,IB0c1KQ]!;=qC!:eSEc+UL'bt>A"qrS&Sc,IB0c03^R!9;T7c+UL'bt>A"p#ZS*`Q^^!
+`Bh2^c1oia!8?!']`lC*6-[Bnn)adGc,IB0c1KQ\!8,g,c+UL'bt>A"qrS"*pA^Z-rrMi<qrS40
+`Q^^!`Bh2^c1oia!;=qC!:eSE]g9Wf6-[BnpuV`Pc,IB0c03^R!9;T7c+UL'bt>A"p#ZEMc,IB0
+c1KQ_!8H$/c+UL'bt>A"n)adGc,IB0c1KQ\!8,g,c+UL'bt>A"qrS"*pA^Y5~>
+!h?&@qsFbVhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9k5='9k5='9k5F-Ck2+t>c.1Z:^#&YS
+"[V"qc,J5rhYI33hZ(h'e_WU*hY$=9h??g%hTa<qrS@P:qq_>8qq_>8qq_>8qq_>8qq_>8qq_>8
+qq_YAhVRDOeM5q*;Z>PAmKl29e]l(ihWE\Wrn[Y;r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9r8%G9
+r8%G9qq_YAhVQN%e_WU*hYZ^C0r1<gc2Rj8UbVc7#smFuc,JPrk2,8"h>l^9h>l^9h>l^9h>l^9
+h>l^9h>l^9h>l^:h?i?$hTa<qhEej3qsFbVhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9k5='9
+k5='9k5='9k5='9k5='Bk2+t>c.1Z:^#&GMrn[fVc/-^iec">)k54!8k54!8k54!8k54!8k54!8
+k54!8k54!Ak2+tWhUO@;bu4Ptn*UKJhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9k5='9k5='9
+k5='9k5='9k54!Ak2+t>c.1Z:^#&YS"#6UA.F.qpS>7n:mf)&H;U+(Cc.2dL!9X18!9X18!9X18
+!9X18!9X18!9X49#3Odmc/-]CrndG<#smFuc,JPrk2,8"h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9
+h>l^9h>l^9h>l^9h?i?$hTa<qhEej3p$N,PhUTlihVRDOk5O3;k5='9k5='9k5='9k5='9k5='9
+k5='9k5='9k54!Ak2+t>c.1Z:^#&5G#smFuc,JPrk2,8"h>l^9h>l^9h>l^9h>l^9h>l^9h>l^9
+h>l^9h>l^9h>l^8h?i?$hTa<qhEej3qsFP@Umrla~>
+!liB.qsF\Wf$;:Pdb<R,g'QWif#l"Xg-iO/qsFbYf$;.Ldam.'g?[>cs5ql=g=Fip`m3.']&*,J
+s4R\.:s.A3`m2`\s5"%4c8=+p:tF@Sn*UEKf$;:Pdb<Qsg'QWif#l"Xg-iO/qsFQ3b/Rl7rrU3_
+H2I"77+TZ'_U@/pe(P,bg=FEdcIt[thYZ^G7+TZ'_U@/p`nCaUg=FEdcIt[thY$=:g'6,)b1=_T
+cH=l@h?_]X1tKfGf%SjHmKZ/2cGm`Lg>9g&$/XCeb/V`\7(V7PmK7aW`aR0m!liB.qsOL<#1cVn
+f#l"Xe_:&[#hI;Df#gh?g=l>i#=R.g`kp0XhT"7UhV-Q'`m3:+]&*,J#=R.g`kp0XhTOUZhV-Q'
+`m3:+]&)oD#=R.g`kp0XhSn1ThV-Q'`m3:+]&*>P"*r&/@=S~>
+!quZ5qrU+/c,IB0c-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+c.1(`]tMD86+#2>jrZn6`P&t0c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.2Xi,gFlae]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]l@P]uAMf[+4j3"jPTB9#]'S`W+1Ie]lXhe]l@hc.1(hc-=e`e]lXh
+c.1(hc.1(`e]lXhe]l@hc.1(hc-=e`e]lXhc.1(hc.1@h`Au2^9$Po2n)d>1c,IB0c-=e`e]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]l@hc-<r8
+`RR8]ebeJ2`W,Y-c2Rk=s2Flt5=*Q5]tM\8e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]l@hc-<r8`RR8]ebeK&6-[B^^!4gPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc-<r8`RR8]eb/&.c.1'2`QeD$s33dY
+c.1(hc-=e`e]lXhc.1(hc.1(`e]lXhe]l@hc.1(hc-=e`e]lXhc.1(hc.1(`e]lXhe^_p`3R,N8
+c.1)-k"S.d`P&t0c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc-=e`c+Ug0eNpRmqrS""s7W86rrVoo`V\d$c.1'2`QeD$s33CNc.1(hc-=e`
+e]lXhc.1(hc.1(`e]lXhe]l@hc.1(hc-=e`e]lXhc.1@h`Pp*@9$Po2puY79c,IB0c-=e`e]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhc+Ug0
+eNpRmp#\b1c,IB0c-=e`e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhc.1(`]tMD86+#22k"S.d`P&t0c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc-=e`c+Ug0eNpRmqrS""s7W7=~>
+!i2>HqsF\mc/-^qe_]0\joF99joF99joF99joF99joF99joF99joF98jp0bne_\PK^#o4[9No]t
+c-=eqhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\Fc/-]C^#o"U$23fTF0sdHc.1\MjoF98joF98joF98joF98joF98joF98joF98jp^,/
+mcNZ^hVPV\p?qYCmKZq?hTaU$hVS1m!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dP6
+#N""]hT\s3k54QK3Llloc2Rj@S2pK7#?oC/c.1A$hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9hYcL9
+hYZF?hUU05bu27;qsF\mc/-^qe_]0\joF99joF99joF99joF99joF99joF99joF99joF99joF97
+jp0bne_\PK^#o"U$23fTF0sdHc.1\MjoF98joF98joF98joF98joF98joF98joF98jp^,/mcNZ^
+hVPV\p?qYCmKZq?hTaU$hVS1m!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dP6#N""]
+hT\s3k54QK3LllocMmsAS2pK7$23fTF0sdHc.1\MjoF98joF98joF98joF98joF98joF9:jpLP=
+k1(U2Zubs/pA"%\>0YpKe^`O5r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9qW8%>
+e^`O$;SD5cmKZq?hTaU$hVS1m!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dY9!8dP6#N""]hT\s3
+k3q^C>0YpKe^`O5r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9r8n"9q;qq=e^`O$;SD5i
+mK5J>Ua^f~>
+!m8N2qsH7?b1=_Xdb<F3g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q_
+h?`,pcHb"`9Y0*XmKQ\2f#l"Xf#68JhU]upf#CCphY$;/lK7AKZIUGHdam:/hV-i?hVQuCg>:Q?
+hV-i?hV-iCg>:Q?g>:]?hV-i?hVQuCg>:Q?hV-i?hV-iCg>:Q?io8hCf%.-DlK7C#mQjjqf#l.`
+g=kE;hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+rn[q?g<S!pb"TD'qsFQ7`l_`7rrU?_IJ`Fg<Q`n8b0o"thV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?rn[q?g<S!pb"TD'qsI-Xb1=_Xdb<F3g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:]Gg<S!pb"TD'p$PH;k3?fh
+egS\hf&#-;g>:Q?hV-i?hV-iCg>:Q?g>:]?hV-i?hVQuCg>:Q?hV-i?hV-iCg>:Q?g>:]?hV-iG
+ini,7f!9/Xk3DF'5ul(Yb0&/dg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q_h?`,pcHb"`9Y0*XmK7mWb$iTq!m8N2qsH]6k3?fhegS\hf&#-;
+g>:Q?hV-i?hV-iCg>:Q?g>:]?hV-i?hVQuCg>:Q?hV-i?hV-iCio8hC.+Y\@lK7C,mS$X'f#l.`
+g=kE;hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hVR8GcHb"`9Y0*RmQ4Fkf#l.`g=kE;hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV.tc#iaR`cIU-3]&)oD5ul(Yb0&/dg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q_h?`,pcHb"`9Y0*XmK7mWb$ff~>
+!rqu=qrS&[`QcB@c-XuHhTa<ac,E;^hYZF=;T6o"`Qc9Ms31_dc,E;^hXoq9hWARSbq[2^c-+Z;
+h>l+*blb%^k2,Og"]E=a`Pp*=eHk$Vc,IrH9!mIPjo`m%s.%=5!VXe8jonZ%c,IZHd+&EYc-=5P
+`CdMoqrS&[`QcB@c,8';hTa<ac,E;^hXoq9hWARSbq[2^c-+Z;h>l+*blb%^k2,Og"]E=a`Pp*=
+eHk$Vc,IrH9!mIPjo`m%s.%@6!VXe7jp9i+C95Z7`QcZYec4J2e]fhnXD6nSpZ;WW`QcB@c,8';
+hTa<ac,E;^hY$"7;T6o"`QcKS#i<hN`Qc@o[,196"]E=a`Pp*=eHk$Vc,IrH9!mIPjo`m%s."T~>
+!h?&@qsF]1XPVgae_]0\joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF99joOo4
+rn[aY@_Lq$mK.I2hYu(*hF-M_k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7WhUUJa@_Lpsmf*5S`DY7C+Pn7/)!2\')!2\')!2\')!2\')!2\'
+)!2\')!2\')!2\')!2\')!2\')!2\')!2\')!2\')"%[t)!9@H`W#o+mK[g7hVQf5hVS1m!8d_;
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!Uf+Lh?0ig
+^#o4["#6UA.F%koS>7n:mK[g7hVQf5hVS1m!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;
+!8d_;!8dY9!Uf+Lh?0ig^#o4[#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX;hYuX;hYuX;hYuX;hYuX?hWEtgk5O3>XCAm*p$VhZ7)`'ShB:YtmMP('mMP('mMP('
+mMP('mMP('mMP('mMP('mMP('mMP('mMP('mMP('mMP('mMP('mMP?tmMP*:;T8Y8n*UF%XPVga
+e_]0\joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;joF9;
+joOo4rn[aY@_Lq$mK52>S12b`!h?&@qsOI`3Q4nHhB:YtmMP('mMP('mMP('mMP('mMP('mMP('
+mMP('mMP('mMP('mMP('mMP'tp(6BKePaBcs7l!eF0+6Te^`O5r8n"9roO4;roO4;roO4;roO4;
+roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO4;roO@?k2u*orn[aY@_LpsmK[g7hVQf5hVS1m
+!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8d_;!8dY9!Uf+Lh?0ig^#neO
+#BR!'hUU05hYcL9hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;hYuX;
+hYuX;hYuX<mcON*"0>tFk54QK0r1<gJ,~>
+!liB.qsF]/WnPnHcIU_KhDEsCg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+io9+Wf$`9T?+SnimK[a3f$_^`dalIm$JsLng="F#W`cpip$PHGqYIp"cIs\p/E.f3+Q=O'+Q=O'
++Q=O'+Q=O'+Q=O'+Q=O'+Q=O'+Q=O'+Q=O'+Q=O'+Q=O'+Q=O'+Q=O'&F(CpdSR[SqY'CG#B?ct
+da$.hgA]qqg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?io9+Wf$`9T?+SnimK7aW`aR-l!liB.qsF]/WnPnHcIU_KhDEsCg>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?io9+Wf$`9T?+SnimK[a3g="9lf%U,[6/(2LhV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?io9+Wf$`9T?+SncmRm3L
+qS#YKg*kB#iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'
+iZR4ll6+s3:qlf&p@%DSEN7a@cHb"prn]uqhV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-iGio]+Kdb:j0]&*>P"*r&/@F"lS`l`T(mQ^FAqS#YKg*kB#
+iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5'iZR5#mM+O7dSR[SqY'^P#B?ct
+da$.hgA]qpg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:QCio]+Kdb:j0]&*,J#B?ctda$.hgA]qkg>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?g>:Q?
+g>:Q?g>:Q?g>:Q?g>:Q?g>:iKk2+\;g9+_mhXBk;EN7a@cHb"prn]uqhV-i?hV-i?hV-i?hV-i?
+hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-i?hV-iGio]+Kdb:j0]&*>P"*r&/@=S~>
+!quZ5qrS-)Ut*`/`QcZWec+D1e]l@hUft.^qrS-)Ut*`/`QcZJeI(0`hUTlqeYHBUhY$%1p-c8[
+`RQ]f1#=A9.GcN1.GcN1.GcN1.GcN1.GcN1.GcN1.GcN1.GcN1.GcN1.GcN1.GcN1.GcN1.GcN1
+)!3:(bt>ABp@%,KF/7@2`Pp*H`mt(F#M%)DeYHBUhYZF;`W,Y-c2Rk=s2Flt#BQ]kc,IZHc.(;C
+h?VTUc./Un[,1]B#BQ]kc,IZHc,\B6h?VTUc./Un[,1K<rq8ae9#]=8bq\'(hC7;1hC7;1hC7;1
+hC7;1hC7;1hC7;1hC7;1hC7;1hC7;1hC7;1hC7;1hC7;1hC7;1hAGB(hT\["rq>gC#BQ]kc,IZH
+c,S<5h?VTUc./Un[,1]B"3(<6UsAuApA`,/k5P'7ZqA<f1!MH0.GcN1.GcN1.GcN1.GcN1.GcN1
+.GcN1.GcN1.GcN1.GcN1.GcN1.Gc30(tIKf9!nTkpuVg&Ut*`/`QcZJec+D1e]l@hUft.^p#ZL#
+Ut*`/`QcZOec+D1e]l@hUft.^n)ajrUt*`/`QcZIec+D1e]l@hUft.^qrS""s7W7=~>
+!i2>HqsFO!;U,3t!nH/aeE.)*p?q)*eP_=EhYZ^C]i*,3rmf!EroX7;"O0i&`SU:U!;?El"-cEZ
+e]HYPk4\N*Zq?S^rrDc]mK1("c2QQ$e_]0&jpCJLmcNZ^;N&NNqsFPHS>7UYrrT!d3W&4G]i*,S
+h?)6ahULZome6)2k1*@f`SUL[!khLVrn[_,hVQ<8$1@NTk2t2lMoFQGmJut[rr\KXXOYGL#3PXQ
+hR#n>rr2uln*U7j;U,3t!nH/a`o[Tqp?q)*eP_=EhYZ^C3LllocMmsAS2pK7!;?El"-cEZe^WF[
+k4\N*Zq?S^rrDcfmK1("c2QQ$e_]0'jpCJLmcNZ^;N&NNp$Mmp;U,3t!nH/abiT6"p?q)*eP_=E
+hXBk6]i*,Sh?)6ahT"[ame6)2k1*@f`SUL["$)mI.=_~>
+!m8N2qsFa$9Zkr;daH_#eD:MkmcNB_c:ir+hYZ^H\kL8tdaHFhf#QMDhZ):4c:ir+hY$::o)AYU
+O[Q%kf%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/
+hX9scY"4]SrrDWYmKgBtb1>.ldam-lh?i30k2+t?9SL4;qsFQ7`l_`7rrU?_IJ`F<\kL8tf$`!t
+g=4scipPschTefK^>AbT#eE^Pf%/9tf%S1$$0(C8hVQOOKtcF:mJuhWs$Di9V9[ZGf%S^/f%S^/
+f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%T!Ko%'s7OoG@\o'buP
+\kL8tf$`!tg;_tUipPschTefK^>AbT"+A23@F"lSb/Sl,mJuhWs#6'.V9[ZGf%S^/f%S^/f%S^/
+f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^/f%S^3mder38<NoO!:opQ#eE^Pf%/9tf%S1$$0(C8
+hVQOOKtcF:mKgBtb1>.ldam-rh?i30k2+t?9SL4;n*UIm9Zkr;daH_#`nh$]mcNB_c:ir+hYZ^C
+IE'E<J,~>
+!rqu=qrRse9#^eS!l`F/eC=l^k2+Y=`CbcrebeJ1ZqA=:blYl/c2Q5nc2Q5nc2Q5nc2Q5nc2Q5n
+c2Q5nc2Q5nc2Q5nc2Q5nc2Q5nc2Q5nc2Q5nc2Q5nc2Q5nc2,rn`Cbcreb/&)mf*5QMa<lPc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(he`Q;EUe6RE
+rrDKUjoVn^`W"*``QcZIeHt*phUU/q8qXh-qrS"*pA^Z,rrMi<qrRse9#^eS!l`F/eC=l^k2+Y=
+`CbcrebeJ1ZqA=:blYl/c,\?@hWE\Fe\t.5^")f<!:Kjd6An."`QcrXe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe^`gMc(msirr2udn)a\Y9#^eS!l`F/
+`mkCPk2+Y=`CbcrebeJ2c1_1-c2Rh<c26W'mf*5FMa<lPc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1tEc(msirr2udpuVXb9#^eS!l`F/a41LQk2+Y=`Cbcreb/&+
+ZqA=:blYl/c-4]EhWE\Fe\t.5^")T6!jkS=rlkM`c-=8Y$/Xh$e^_W2K>#h4jo`m%s."T~>
+!h?&@qsF[^Mb:)$hWFgo.H]LLhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\o
+jp1>:hR#mi[*AI8"SRaGXOY2E#Njn"X@d67c1LE(pAP"Vc$M`2.5<8+.5<8+.5<8+.5<8+.5<8+
+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5=,0c2IYBp@%DRp5;PEe_]HfhDaTR
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2-+"#O^a2
+Zq>)?c2-i10r1<gc2Rj8UbVc7#53sIXOZ1irn]*dhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhYuXBmcNB58nt`XqX+R]Mb:)$hWFgo60@%dhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWEtgk2*I;C:)7XmJutZs$4hU5qsfC.5<8+
+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+.5<8+6$(<LrrDc]
+mKWBC9!$S"k5O3rk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7WroOIRk2*I;C:)7^mK52>S12b`!h?&@qsFIXrVnb"HU0A80e"h+0e"h+0e"h+0e"h+
+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h+0e"h3.5=,0c2IYBpA"%[p5;PEe_]HfhEg;\k2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7_mcNB58nt`Xo^2qW
+Mb:)$hWFgo1$7?ThWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\o
+jp1>:hR#mi[*A%,#53sIXOZ1irn]TrhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\ojp1>:hR#mi[*AI8"#6UA.=_~>
+!liB.qsF^[NC9Vgf%S^)g&U"/iWdu:885BPk54QLnr6&6b/Dm2g'HQhd]Q,TZHD>&mK)nTrr57'
+EBGd#/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t
+/3Iplrr3#qo'buOnr6&6cIU_#`nCFLro+.5Y"394b3&Th"*r&/@EnfR`l`T(mK`<B7&A2[g=Fd-
+!8d_7#1fqJBsPnDqsF^[NC9Vgf%S]qg&U"/iWdu:885BPk4S-Co(r@c5fRe+/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<&3EQ8"X!W)BUmK`<B
+7&A2[g=F9t!8d_7#1fqJBsPnDqsFQ3b/Rl8rrU3_H2I"1o(r@c29'Vu/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1`2#4E8C?rrMueq!JCXNC9Vgf%S]qg&U"/iWdu:
+885BPk4S-Inr6&6cIU_#bh<'Rro+.5Y"394b3&0\#P*jBV9[ZGf#HDDhYuL=euhPXZHD>,mK7aW
+`aOA~>
+!quZ5qrT^&Mb9eac.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1)<
+ec4J0c(ms@XMt%u9C@^1UrCU/c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(he_\j$Ue5*t`Ur9nme6Y[!kiY8`[LsLF1qSQ!VYsMk!AEn8u0GN
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+rmh&*"jNi8@][QFjo`U&p8#t5!quZ5qrT^&Mb9eac.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1)<ec4J0c(ms@XMt%u9C@^1UrCU/c.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(he_]0-Ue5*t`Ur9nme6Y[!kiY8
+`[LsLF1qSQ!VYsMk!AEn8u0GNe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhrmh&*"jNi8@][QFjo`U&p8$"6!quZ5qrRqIpAY'n]lQ3].0;MN
+^&J$4p?q_<9C@^1UrCU/c.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(hc.1(h
+c.1(hc.1(hc.1(hc.1(he_]0-Ue5*t`Ur:SmYa]5`QcrXe]lXhe]lXhe]lXhe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhrmh&*"jNi8@][Q:k!AEn8u0GNe]lXhe]lXhe]lXh
+e]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhe]lXhrmh&*"jNi8@][QF
+jo`U&p8!3~>
+!i2>HqX+R]]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=@"s"OXS
+K=&>Kq<e@Y]kT:;.0VG(K=&>KoBlVP])Md(mHt2P]kT8N.5C`L!&=I%!&=I%!&=I%!&=I%!&=I%
+!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=I%!&=F$s"OXSK=&>KqX+GGS>7UYrrT!d3Vr.J
+p:Y2q.4I"L.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+".K;+*;M2?ihYHRD
+p:Y2q.4I"L.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%
+.0)+%.K;+*;M2?ihXg.8p:C8(p?h8Pp:Y2q.4I"L.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%
+.0)+%.0)+%.0)+%.0)+%.0)+%.0)+%.0)+$.K;+*;M2?ihYQXB3LllocMmsAS2pH6!;=D3!;?-S
+#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[Ik%"B'lZ^#&AK#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%q^MP""B'lZ^#&/E#55`F0e"P+r$_V#r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%
+r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r[@h%r@.b$"B'lZ^#&VR"$)mI.=_~>
+!m8N2qX-Q<[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbp
+/1<&+<J@`mg?SP&9CfN&1b:%+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nI2TKsJGHlLaKFo(p$!!W)BSmS*2[AMbqd/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t-nHbt1f]78^=qlL
+mK7mWb$iQp!m8N2qX-Q<[Uh9H-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbp/1<&+<J@`mg?SP&9CfN&1b:%+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nI2TKsJGHlLaKFo(p$!!W)BSmS*2[AMbqd/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t-nHbt
+1f]78^=qlLmK7mWb$iTq!m8N2qX+CTqT&U:qXX@J9CfN&1b:%+-nHbt-nHbt-nHbt-nHbt-nHbt
+-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nHbt-nI2TKsJGHlLaL6o!W*d/1<%t
+/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t-nHbt1f]78
+^=ql?mS*2[AMbqd/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t/1<%t
+/1<%t/1<%t/1<%t-nHbt1f]78^=qlLmK7mWb$ff~>
+!rqu=qW7nJZskc7.0VG(K<2c:q;qeIZskc*.0VG(K<2c:oB$)Ap:UD+p?q>1"7EO*0u#.@0iEY*
+^")uA"3pQ>SBV!6p<EHr"7EO*1!M-N0iEY*^")r@"7EO*0u,4A0iEY*^")`:!UfZorrMi]mH+N=
+Zskc).0VG(K<2c:qW7n)pA^Z-rrMi<qW7hHp;d16p?qY:"7EO*0u,4A0iEY*^")`:"7EO*0uYRF
+0iEY*^")N4"7EO*0u#.@0iEY*^")uA"3pQ>S:C~>
+!h?&@qsOIW"7G<r`Qc(!`QdQ5pA=:Wp&jaFc,IK3"NAXJme6>Arq=#)rq>gKrq6H^k0:l[]`c=!
+k3hs?mK52>S12__!h?&@qsOIW"7G<r`Qc(!`QdQ5pA=:Wp&jaFc,IK3"NAXJme6>Arq=#)rq>gK
+rq6H^k0:l[]`c=!k3hs?mK52>S12b`!h?&@qsOIWa8c/4q!S.T"7G<r`PB.i`QdQ5p@[kQp&jaF
+c,IZ8"NAXJme6,;rq6H^k0:l[]`c=!k3hs?mK52>S1/s~>
+!liB.qsF[ZmdfZ"b/2E7"N&=<lLOi?#4h3QlJB\#^q'Zcb22FSp$MqQmdg4grr`,gmdfi7#4h3Q
+lJB\#^UaQbb22FSqsFQ3b/Rl7rrU3_H2I"6o'Z)6hTE^[\cfmmhWj\/mKW7Mo'5)S_SE_c_TLa#
+o(DDQo'Z)F^Ae<3o'Z);mKW7Mo'5)S_S<Yb_TLa#o)%hWH-4-8cMmscb'EmP"7kmNqT8a>qXX(F
+q!J@WmdfZ"b/1s*"N&=<lLOW9#4h3QlJB\#`OZ2hb22FSn*UDNmdfZ"b/1p)"N&=<lLOi?"*r&/
+@=S~>
+!quZ5qr[nG4QbM>]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJd
+[(Wi[[(XH8k3i-/rpEA?hSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]uAjjme,`AmJusprrDclmdK<;mRlWu`P&Xl[(Wi[[(Wi[
+[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(X/[]sPJ[]uAjj
+mec,K`W,Y-c2Rk=s2FltrpDo2hSm18]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]tLed[(Wi[`STbFqr[nG8`nmK]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJlhWF8!k5OcKp:gP,pAXLKk5Od@k2+(j
+[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[
+]sPJ[]sPJlhWF8'jo`U&p8$"6!quZ5qr[nG!;=P7!;?E[pu_SD8`nmK]sPJ[]sPJ[]sPJ[]sPJ[
+]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJ[]sPJlhWF8!k5Od:
+k2+(j[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(X/[
+]sPJ[]uAjjmdK<;mRlWu`P&Xl[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[[(Wi[
+[(Wi[[(Wi[[(Wi[[(Wi[[(X/[]sPJ[]uAjjmec,K`W,Y-J,~>
+!i2>HqX-N?me6):hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\O
+k2,7Wk2,OopA+,Kp?qYBmb[*_k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7WmdBf?mK<1Np@c<%s7QK]p?h9@p?qYBmb[*_k2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2+tWhWE\WhX9h*
+qX+GGS>7UYrrT!d3Vr/,p?qYBmb[*_k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7WhWE\WhWE\_me6JE9(q]HmdArohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhX9h*oBl_Sme6@is8Vcnme6&99D7fImdAro
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\O
+k2,7Wk2,OopA41Z3LllocMmsAS2pH6"8;0Vp<3L9p&XUTp?kQHme6):hWE\WhWE\WhWE\WhWE\W
+hWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\_me68?7J?0C
+mdArohWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhWE\WhVRDO
+k2,7WmdBf9mS!9Ap?qA*k2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7Wk2,7W
+k2,7Wk2,7Wk2,7Wk2,7WhWE\WhWE\_me6MF"$)mI.=_~>
+!m8N2qX+LWmdBB&bME9^lM0cMo'Yr2k.][Qk3DO*"nM*Po(r4$s8VrqncA1LmHt,JmdBB&^"reP
+lM9iMIE'E<c2Rjf`dR^O"S2!KlK6:H!Tr\BmKE+KmcrrKh>ud(o'Q\PmdfrFqS`F6qZ$*emdfc5
+"S2!KlK5e:!Tr\CmK7mWb$iTq!m8N2qX+OXmdfrFqTo3AqZ$*emdg)>"S2!KlK5h;!Tr\<mKE+K
+mcrrPh>ud(m-Y#ImdBB&^"rePlM9iMIE'E<J,~>
+!rqu=qW9s/k3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j,
+hUUK5hUUcNmeQ!;mcNs"k1/>=hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5k2u+'jot28mdBfB`;fl2s6]pMmd9.0mcNs"k1/>=hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUU05e_\j5
+e`Q#^qW7n)pA^Z,rrMi<qW9s/k3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j5e_\j,hUUK5hUUcNmeQ!;mcNs"k1/>=hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5k2u+'jot28mdBfB`;fl2s6]pMmd9.0
+mcNs"k1/>=hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUU05e_\j5e`Q#^qW7n)pA^Z-rrMi<qW7tLk3h[2p<Wd=pAaO]k3hs*9((j0k2t4Ne_\j5
+e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e`Q#^oB&L0k3hBoe_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5e_\j5
+e_\j5e_\j,hUUK5hUUcNmd9.0mcNs"k1/>=hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5
+hUUK5hUUK5hUUK5hUUK5hUUK5hUUK5hUU05e_\j5e`Q#^qW7n)pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+!h?&@JaS*WX6p'EUmrmYrrS^d0nJbDm]5aX0r1<gcMms9UbRGgJaTT,"#6UA.=_~>
+!liB.JaS*WX6p(8b/Rl7rrU3_H%GC7m]5aXH-4-8cMmscb'AR+JaTT,"*r&/@=S~>
+!quZ5J`_OGX6'N's7W85rrVoo`I[0&k,[VH`W,Y-cMmt>s2BQOJ`a#q"3(<6Ujr~>
+!i2>HJaS*WX6p'MS>7UYrrT!d3J$ULm]5aX3LllocMmsAS2l/gJaTT,"$)mI.=_~>
+!m8N2JaS*WX6p(<`l_`7rrU?_I=^g;m]5aXIE'E<cMmsg`dNF+JaTT,"+A23@=S~>
+!rqu=J`_OGX6'N/pA^Z,rrMi<J`_OGX6'N/pA^Z-rrMi<J`_OGX6'N/pA^Y5~>
+"JhPs@VYmOrFu=Arb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrG)=@"DVDAS2&:g"JhPs@VYmOrFu=A
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrG)=@"DVDAS2&=h"JhPs@VYmOrFu=Arb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FBrb;FB
+rb;FBrb;FBrb;FBrG)=@"DVDAS2#N~>
+!QrFYV1GXtWj\r)V#nfZ@EnfQb/X:SJZ=:$[]95$!m8MkcMmpf`qlN_We%1YWr&Uob/Rk?~>
+"98)gmf)n[mXb(_p9OAqme6ASp8#q4s7QH\rq6?[JbFZgZM"Iip@eO[Us8r>p&OO[p&ON3p4;qC
+p''mXpAai^J,~>
+!M#taF8]hRF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnS
+F8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fnSF8fqQ@KN'q.F%knS>?+)rFu=Rrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrb;FS
+rb;FSrb;FSrb;FSrb;FSrb;FSrb;FSrbDC@!h?&8cMmp8V#>B5C&i>SC&i>SC&i>SC&i>SC&i>S
+C&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>S
+C&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>S
+C&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>S
+C&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>S
+C&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>SC&i>S
+C&i>SC&i>SC&i>SCAhTCS>7Ta~>
+!QN:\Xok],WiCQOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)Wii@OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)8?StqWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)Wil?$rM9S8b$iQp!QN:\Xok],
+WiCQOWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)Wii@OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)8?StqWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)Wil?$rM9S8b$iTq!QN:\Xok],WiCQOWiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+Wii@OY,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)Y,\Y)
+Y,\Y)Y,\Y)Y,\Y)8?StqWiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)
+WiiA)WiiA)WiiA)WiiA)WiiA)WiiA)Wil?$rM9S8b$ff~>
+!quZ^rq6?[rUp6Zrq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq?B[#PRTZme6ASSB_'8pAaR[p&OOZ
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[pAaOcp?qYBp@eNVcMmt>s6fm[!:KgZ!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[
+!:Kj[!:Kj[!:Kj[!:Kj[!:Kj[s6^-cme6)BpA^Y5~>
+"f.Z'@VTZVEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tS
+Er]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEr]tSEs-6!F)#Ih@KN?q.F%krUmu1/C23]g
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS
+!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS!,DLS"DW"!C23`W!i2>8cMn'DS8)MJCAi2RCAr8SCAr8S
+CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8S
+CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8S
+CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8S
+CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8S
+CAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8SCAr8S
+CAr8SCAr8SCAr8SCAr8SCAr8WC3+H2CAqZDUmrla~>
+"Nn`\V5f*LJZc8\s/Q'p!m8Mkc2Rph`hfN3JZaR,Z*+,,rhT\=`aR0m"Nn`\V5f*LJZc8\s/Q'p
+!m8MkJ,~>
+!<7WDJbH):"7H3_Us/jip4;q:p&ja_p8#t5JbFZgWV-G^s7W7=~>
+$(Reh>$>BEC1:Y%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peIqiG-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@T$rMC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe@VT@]>$@Gl.F%l!S>9%d
+>%1rU@Uah%@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VTA%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:pe;JKZU@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@]C1:XU>+DB;cMn3@Uf(B"@Ua(]
+@Xi-%C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1;[-@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e@VT@e
+@VT@e@VT@e@VT@e@VT@e@VT@MC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:pe
+C1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:peC1:Xe@U`MES>7Ta~>
+$-(,YTqS<ZWhlPAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lJ#]?FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV,F=iWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lV5gAcSY='G@EnfY`lajG
+Tr"TcV58[AV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_l;Q?RnV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAgWhlD[TuP5`cMn3jb+56"V5:2g
+V15MAWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhk3FV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAlV5gAl
+V5gAlV5gAlV5gAlV5gAlV5g@iWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_l
+Whl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhl_lWhlPlV4jHR`l__?~>
+$24Dep?qYBp?q?up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBJ+i=(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)BmS`cHp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBme6)Bme6ASSB_'?pAaRS
+me6)Bmd>Sume6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6'up?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYB;YKPPme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6):p?qYBp@eNVcMn4Es6fUKp?qYB
+mXOrup?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?mG(me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)Bme6)B
+me6)Bme6)Bme6)Bme6)Bme6'Hp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYB
+p?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qYBp?qABme6)BpA^Y5~>
+"/MGb;Z0f!@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO=@TlrE>%1Z=;P]g;c2RmAS5N8`>5r(2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2
+=o`%2=o`%2=o`%2=o`%2=o`%2=o`%2=pneC>%1ZE>$=h"S2&=h"/MGb;Z0f!@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2@fBO2
+@fBO2@fBO2@fBO2@fBO=@TlrE>%1Z=;P]g;J,~>
+!QrF\SUmJcTs:9qV4F<Nb/Rl7rrL9^rLJM5JYB?B#,RlaS]\r\cMmpf`r2HZTn/oBTa%?aTq0?G
+@=S~>
+#QOMkme6)BmeuhZmf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[
+mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mf)n[mec\]me6)Kp8#q4s7QT`p?qYBrUp6Z
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[
+rq6?[rq6?[rq6?[rq6?[rq6?[rq6?[qt:3]p?qtSUs8r>p&sgWme6)Ip&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[p&OO[
+p&OO[p&OO[p&OOXp''mXmf3!VJ,~>
+!M#tb8d&$a;G'Q2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZIo8m:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8k`,T;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ8lA:\;?EAa.F%knS>?-V
+"B%ii8kOS28lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA92;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ9N"J\8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8R;G-pd!h?&8cMmp8V#Esh;G'hZ
+8q0`2;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G)F:8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z8lA8Z
+8lA8Z8lA8Z8lA8Z8lA8Z8lA8T;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ
+;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'hZ;G'PZ9)_]iS>7Ta~>
+"NJTLR?`>kJXN^0"eD'P`l_`7rrg?aQ'mngR=Ud0R0B.LS]8f\cMn$eb*AB[JXM(WYF,QbR@V@?
+@=S~>
+!VZQmmJutZmJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[
+mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mJut[mK<1Nme6YJs7QKnSB_'7pAb-[!;?BZ
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[
+!;?E[!;?E[!;?E[!;?E[!;?E[!;?E[!;?E["8;0NpAXL[p&Y2`cMmq=s8MEdpAOCZpAXI[pAXI[
+pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[
+pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[
+pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[
+pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[
+pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[pAXI[
+pAXI[pAXI[pAXI[pAXI[pAXI^p?qABrpKg[!WS[?~>
+$)F)eS>;[NS>;s1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NJ"3=)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUf*_YS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NUn"6NUn"6N.F%l!Un"6N
+Un"6NUniL1Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"61S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[N;OjPQUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6VS>;[NS>;Z(cMn3HS>;[NS>;[N
+Ujno1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>:Y)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"5YS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;sNUn"6NUmrla~>
+$-L91`lc<D`lcGR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<DJ&]XNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb#67%`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<Db/VTDb/VTD@EnfYb/VTD
+b/VTDb0#4Rb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VSR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D;T?l!b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTH`lc<D`lc;0cMn3n`lc<D`lc<D
+b(%FR`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`l`eNb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTDb/VTD
+b/VTDb/VTDb/VTDb/VTDb/VS%`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D
+`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lc<D`lcHDb/VTDb/Rk?~>
+$30`!pAajdpAb/BpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds&/RjpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7ZKds7ZKdUs/iEpAajd
+pAajds*sbBpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpA]X9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZIjpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAb0ds7ZKds7W85rs8>upAajdpAb/B
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdJ+ip9s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKds7ZKd
+s7ZKds7ZKds7ZKds7ZKds&/RjpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajd
+pAajdpAajdpAajdpAajdpAajdpAajdpAajdpAajds7ZKds7ZKdUjr~>
+JLQ.!UaaRgJLQ.!UaaUhJLQ.!Ua^f~>
+JRO+<Ug_OJJRO+<Ug_RKJRO+<Ug\c~>
+$(Rf]Un"6NUn!s)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NJ#&U1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS5Q/QUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NS>;[NS>;[NSB_'?S>;[N
+S>;[NS=G))S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6N;P]hYS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[FUn"6NUn"6NcMn3@Un"6NUn"6N
+S:@?)Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUmuq1S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[NS>;[N
+S>;[NS>;[NS>;[NS>;[NS>;ZQUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6N
+Un"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn"6NUn!sNS>;[NS>;[*~>
+%%EndData
+showpage
+%%Trailer
+end
+%%EOF
diff --git a/doc/kmouth/kmouthwizard.png b/doc/kmouth/kmouthwizard.png
new file mode 100644
index 0000000..085f213
--- /dev/null
+++ b/doc/kmouth/kmouthwizard.png
Binary files differ
diff --git a/doc/kmouth/man-kmouth.1.docbook b/doc/kmouth/man-kmouth.1.docbook
new file mode 100644
index 0000000..5e178da
--- /dev/null
+++ b/doc/kmouth/man-kmouth.1.docbook
@@ -0,0 +1,78 @@
+<?xml version="1.0" ?>
+<!DOCTYPE refentry PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
+<!ENTITY % English "INCLUDE">
+]>
+
+<refentry lang="&language;">
+<refentryinfo>
+<title>&kde; User's Manual</title>
+<author>&Lauri.Watts; &Lauri.Watts.mail;</author>
+<date>June 12, 2005</date>
+<productname>K Desktop Environment</productname>
+</refentryinfo>
+
+<refmeta>
+<refentrytitle><command>kmouth</command></refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+
+<refnamediv>
+<refname><command>kmouth</command></refname>
+<refpurpose>A type-and-say front end for speech synthesizers</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+<cmdsynopsis>
+<command>kmouth</command>
+<arg choice="opt"><replaceable>filename</replaceable></arg>
+<arg choice="opt">&kde; Generic Options</arg>
+<arg choice="opt">&Qt; Generic Options</arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+<title>Description</title>
+<para>&kmouth; is an application that enables persons that cannot speak to
+let their computers speak.It includes a history of spoken sentences from
+which the user can select sentences to be re-spoken.</para>
+<para>Note that &kmouth; does not include speech synthesizer. Instead it
+requires a speech synthesizer installed in the system.</para>
+</refsect1>
+
+<refsect1>
+<title>Options</title>
+
+<variablelist>
+<varlistentry>
+<term><option><replaceable>filename</replaceable></option></term>
+<listitem>
+<para>The history file to open.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+
+</refsect1>
+
+<refsect1>
+<title>See Also</title>
+<para>kttsd(1), festival(1), mbrola(1), freetts(1)</para>
+
+<para>More detailed user documentation is available from <ulink
+url="help:/kmouth">help:/kmouth</ulink>
+(either enter this &URL; into &konqueror;, or run
+<userinput><command>khelpcenter</command>
+<parameter>help:/kmouth</parameter></userinput>).</para>
+
+<para>There is also further information available at the <ulink
+url="http://accessibility.kde.org/">&kde; Accessibility project web
+site</ulink>.</para>
+</refsect1>
+
+<refsect1>
+<title>Authors</title>
+<para>&kmouth; was written by
+<personname><firstname>Gunnar</firstname><surname>Schmi
+Dt</surname></personname> <email>kmouth@schmi-dt.de</email>.</para>
+</refsect1>
+
+</refentry>
diff --git a/doc/kttsd/Makefile.am b/doc/kttsd/Makefile.am
new file mode 100644
index 0000000..4169155
--- /dev/null
+++ b/doc/kttsd/Makefile.am
@@ -0,0 +1,3 @@
+KDE_LANG = en
+KDE_DOCS = AUTO
+
diff --git a/doc/kttsd/addtalker.png b/doc/kttsd/addtalker.png
new file mode 100644
index 0000000..15f9e81
--- /dev/null
+++ b/doc/kttsd/addtalker.png
Binary files differ
diff --git a/doc/kttsd/audio.png b/doc/kttsd/audio.png
new file mode 100644
index 0000000..aa5f05d
--- /dev/null
+++ b/doc/kttsd/audio.png
Binary files differ
diff --git a/doc/kttsd/festivalintconf.png b/doc/kttsd/festivalintconf.png
new file mode 100644
index 0000000..b718551
--- /dev/null
+++ b/doc/kttsd/festivalintconf.png
Binary files differ
diff --git a/doc/kttsd/filters.png b/doc/kttsd/filters.png
new file mode 100644
index 0000000..f0f1b37
--- /dev/null
+++ b/doc/kttsd/filters.png
Binary files differ
diff --git a/doc/kttsd/general.png b/doc/kttsd/general.png
new file mode 100644
index 0000000..60662fd
--- /dev/null
+++ b/doc/kttsd/general.png
Binary files differ
diff --git a/doc/kttsd/index.docbook b/doc/kttsd/index.docbook
new file mode 100644
index 0000000..a533d52
--- /dev/null
+++ b/doc/kttsd/index.docbook
@@ -0,0 +1,2834 @@
+<?xml version="1.0" ?>
+<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
+ <!ENTITY ktts "<application>KTTS</application>">
+ <!ENTITY kappname "&ktts;">
+ <!ENTITY package "kdeaccessibility">
+ <!ENTITY mbrola "<application>MBROLA</application>">
+ <!ENTITY % imageobjectco.module "INCLUDE">
+ <!ENTITY % addindex "IGNORE">
+ <!ENTITY % English "INCLUDE">
+]>
+<!-- Note to translators: KTTSD is meant to be built under KDE
+ versions 3.2 and later. Please avoid entities that won't
+ be defined under those KDE versions. Thanks.
+-->
+
+<!-- kdoctemplate v0.9 January 10 2003
+ Changes to comments to clarify entity usage January 10 2003
+ Minor update to "Credits and Licenses" section on August 24, 2000
+ Removed "Revision history" section on 22 January 2001
+ Changed to Installation/Help menu entities 18 October 2001
+ Other minor cleanup and changes 18 October 2001
+ FPI change and minor changes November 2002 -->
+
+<!--
+This template was designed by: David Rugge davidrugge@mindspring.com
+with lots of help from: Eric Bischoff ebisch@cybercable.tm.fr
+and Frederik Fouvry fouvry@sfs.nphil.uni-tuebingen.de
+of the KDE DocBook team.
+
+You may freely use this template for writing any sort of KDE documentation.
+If you have any changes or improvements, please let us know.
+
+Remember:
+- in XML, the case of the <tags> and attributes is relevant ;
+- also, quote all attributes.
+
+Please don't forget to remove all these comments in your final documentation,
+thanks ;-).
+-->
+
+<!-- ................................................................ -->
+
+<!-- The language must NOT be changed here. -->
+<!-- If you are writing original documentation in a language other -->
+<!-- than English, change the language above ONLY, not here -->
+<book lang="&language;">
+
+<!-- This header contains all of the meta-information for the document such
+as Authors, publish date, the abstract, and Keywords -->
+
+<bookinfo>
+<title>The &ktts; Handbook</title>
+
+<authorgroup>
+<author>
+<!-- This is just put in as an example. For real documentation, please
+ define a general entity in entities/contributor.entities, e.g.
+<!ENTITY George.N.Ugnacious "<personname><firstname>George</firstname><othername>N.</othername><surname>Ugnacious</surname></personname>">
+<!ENTITY George.N.Ugnacious.mail "<email>gnu@kde.org</email>">
+and use `&George.N.Ugnacious; &George.N.Ugnacious.mail;' in the author element.
+ -->
+<personname>
+<firstname>Gary</firstname>
+<othername>R.</othername>
+<surname>Cramblitt</surname>
+</personname>
+<email>garycramblitt@comcast.net</email>
+</author>
+
+<!-- TRANS:ROLES_OF_TRANSLATORS -->
+
+</authorgroup>
+
+<copyright>
+<year>2004-2005</year>
+<holder>Gary R. Cramblitt</holder>
+</copyright>
+<!-- Translators: put here the copyright notice of the translation -->
+<!-- Put here the FDL notice. Read the explanation in fdl-notice.docbook
+ and in the FDL itself on how to use it. -->
+<legalnotice>&FDLNotice;</legalnotice>
+
+<!-- Date and version information of the documentation
+Don't forget to include this last date and this last revision number, we
+need them for translation coordination !
+Please respect the format of the date (YYYY-MM-DD) and of the version
+(V.MM.LL), it could be used by automation scripts.
+Do NOT change these in the translation. -->
+
+<date>2005-07-31</date>
+<releaseinfo>1.05.00</releaseinfo>
+
+<!-- Abstract about this handbook -->
+
+<abstract>
+<para>
+&ktts; - the &kde; Text-to-Speech system - is
+a plugin based service that
+allows any &kde; (or non-&kde;) application to speak using the &DCOP; interface.
+</para>
+
+<para>&ktts; intends to be the implementation for the &kde; Text-to-Speech API.</para>
+
+</abstract>
+
+<!-- This is a set of Keywords for indexing by search engines.
+Please at least include KDE, the KDE package it is in, the name
+ of your application, and a few relevant keywords. -->
+
+<keywordset>
+<keyword>KDE</keyword>
+<keyword>accessibility</keyword>
+<keyword>kdeaccessibility</keyword>
+<keyword>TTS</keyword>
+<keyword>Text-to-Speech</keyword>
+<keyword>KTTSD</keyword>
+<keyword>kttsmgr</keyword>
+<keyword>festival</keyword>
+<keyword>flite</keyword>
+<keyword>hadifix</keyword>
+<keyword>MBROLA</keyword>
+<keyword>freetts</keyword>
+<keyword>epos</keyword>
+<keyword>SSML</keyword>
+</keywordset>
+
+</bookinfo>
+
+<!-- The contents of the documentation begin here. Label
+each chapter so with the id attribute. This is necessary for two reasons: it
+allows you to easily reference the chapter from other chapters of your
+document, and if there is no ID, the name of the generated HTML files will vary
+from time to time making it hard to manage for maintainers and for the CVS
+system. Any chapter labelled (OPTIONAL) may be left out at the author's
+discretion. Other chapters should not be left out in order to maintain a
+consistent documentation style across all KDE apps. -->
+
+<!-- ====================================================================== -->
+
+<chapter id="introduction">
+<title>Introduction</title>
+
+<!-- The introduction chapter contains a brief introduction for the
+application that explains what it does and where to report
+problems. Basically a long version of the abstract. Don't include a
+revision history. (see installation appendix comment) -->
+
+<para>&ktts; is a subsysem within &kde; for producing
+Text-to-Speech (TTS). It provides a common API for &kde; programmers to give
+TTS capabilities to their applications. It provides some
+nice capabilities for end users as well.</para>
+
+<para>User features:</para>
+
+<itemizedlist>
+<listitem><para>Speak contents of a text file.</para></listitem>
+<listitem><para>Speak &kde; notification events (KNotify).</para></listitem>
+<listitem><para>Speak all or part of the text of a web page in &konqueror;.</para></listitem>
+<listitem><para>Speak all or part of the text in &kate; text editor,
+including instances where &kate; is embedded in another &kde; application.</para></listitem>
+<listitem><para>Long text is parsed into sentences. User may backup by sentence
+or paragraph, replay, pause, and stop playing.</para></listitem>
+<listitem><para>Audio output via &arts;, ALSA, GStreamer (version 0.8.7 or later), or aKode.</para></listitem>
+<listitem><para>User-configurable filters for substituting misspoken words, choosing
+speech synthesizers, and transforming XHMTL/&XML; documents.</para></listitem>
+</itemizedlist>
+
+<para>Programmer features:</para>
+
+<itemizedlist>
+<listitem><para>Priority system for screen reader outputs, warnings and messages, while still playing regular texts.</para></listitem>
+<listitem><para>Plugin-based architecture for support of a wide variety of speech synthesis engines and drivers.</para></listitem>
+<listitem><para>Permit generation of speech from the command line (or via shell scripts) using the &kde; &DCOP; utilities.</para></listitem>
+<listitem><para>Provide a lightweight and easily usable interface for applications to generate speech output.</para></listitem>
+<listitem><para>Applications need not be concerned about contention over the speech device.</para></listitem>
+<listitem><para>FUTURE: Provide support for speech markup languages, such as VoiceXML, Sable, &Java; Speech Markup Language (JSML), and Speech Markup Meta-language (SMML).</para></listitem>
+<listitem><para>FUTURE: Provide limited support for embedded speech markers.</para></listitem>
+<listitem><para>Asynchronous to prevent system blocking.</para></listitem>
+</itemizedlist>
+
+<para>&ktts; actually consists of several programs:
+<variablelist>
+
+<varlistentry>
+<term><command>kttsd</command></term>
+<listitem><para>the &kde; Text-to-Speech Daemon, which is a non-&GUI;
+application that provides TTS services to applications via &DCOP;.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term><command>kttsmgr</command></term>
+<listitem><para>a &GUI; application for configuring and controlling
+kttsd. kttsmgr sits in the system tray.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term><command>libkhtmlkttsdplugin</command></term>
+<listitem><para>A plugin for the &konqueror; web browser that permits you
+to speak all or a portion of the text on a web page.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term><command>ktexteditor_kttsd</command></term>
+<listitem><para>A plugin for the &kate; text editor that permits you to speak
+all or a portion of a text file.
+</para></listitem></varlistentry>
+
+</variablelist>
+</para>
+
+<!-- ...................................................................... -->
+
+<sect1 id="support">
+<title>Support</title>
+<para>
+In addition to the &kde; Bugzilla database (
+<ulink url="http://bugs.kde.org/">http://bugs.kde.org/</ulink>
+), discussions for &ktts;
+currently take place in the kde-accessibility mailing list. Subscribe at
+<ulink url="https://mail.kde.org/mailman/listinfo/kde-accessibility">
+https://mail.kde.org/mailman/listinfo/kde-accessibility</ulink>. Developers
+also hang out in IRC (irc.kde.org, channel #kde-accessibility).
+</para>
+</sect1>
+
+</chapter>
+
+<!-- ====================================================================== -->
+
+<chapter id="using-kapp">
+<title>Using &ktts;</title>
+
+<para>
+<warning><para>Before you can use &ktts;, you must install at least one speech
+synthesis engine and make sure it is working. See <xref linkend="installation" />.
+</para></warning></para>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="starting-kttsmgr">
+<title>Starting <command>kttsmgr</command></title>
+
+<para>
+To start the &ktts; system, type the following command in a &konsole;
+</para>
+
+<para><userinput>kttsmgr</userinput></para>
+
+<para>or click on kttsmgr in the &kde; Menu.</para>
+
+<para>If this is the first time running <command>kttsmgr</command>, or
+if you have not yet configured any talkers, the <guilabel>Talkers</guilabel>
+screen appears. See <xref linkend="configure-plugin" />.
+If you have already configured at least one talker, the <guilabel>General</guilabel>
+screen appears. See <xref linkend="general" />.</para>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="configure-plugin">
+<title>Configuring Synthesis Plugins (Talkers)</title>
+
+<para>Most text-to-speech (TTS) synthesizers offer multiple languages and voices
+and may offer multiple speaking genders, volumes, and rates. You may configure more than
+one instance of a synthesizer. Each combination of language, synthesizer, voice,
+gender, volume, and rate is called a talker. You must configure at least one talker
+before you can start &ktts; and begin speaking text.</para>
+
+<note><para>Multiple talkers for the same synthesizer is similar to multiple print
+queues for a single physical printer.</para></note>
+
+<para>When applications send text to &ktts;, they may specify the
+attributes of the preferred talker to do the synthesis. For example,
+an application may request an English language female talker. If you have
+configured a talker with both the English language and female gender, that
+talker will be used, otherwise the closest matching talker will be automatically
+picked. To learn more about how &ktts; picks talkers, see
+<xref linkend="filters" />.</para>
+
+<para>When you click the <guilabel>Talkers</guilabel> tab in <command>kttsmgr</command>,
+the <guilabel>Talkers</guilabel> screen appears. This screen also automatically
+appears if you start <command>kttsmgr</command> and you have not yet configured
+any talkers.</para>
+
+<para>
+<screenshot>
+<screeninfo>The &kde; Text-to-Speech Manager (Talkers tab).</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-talker-1" coords="1 1"/>
+ <area id="pt-talker-2" coords="1 1"/>
+ <area id="pt-talker-3" coords="1 1"/>
+ <area id="pt-talker-4" coords="1 1"/>
+ <area id="pt-talker-5" coords="1 1"/>
+ <area id="pt-talker-6" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="talkers.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>The &kde; Text-to-Speech Manager (Talkers tab)</phrase>
+ </textobject>
+ </mediaobjectco>
+</screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-talker-1"><para>Click to add a new talker.</para></callout>
+<callout arearefs="pt-talker-2"><para>All the configured <guilabel>Talkers</guilabel> are listed here. Highest priority <guilabel>Talkers</guilabel> are listed at the top. The top-most talker will be used to do the speaking when an application does not specify a talker.</para></callout>
+<callout arearefs="pt-talker-3"><para>Click on a talker in the list to highlight it and click this button to remove it.</para></callout>
+<callout arearefs="pt-talker-4"><para>Click on a talker in the list to highlight it and click this button to display the synthesis plugin's configuration dialog. See below.</para></callout>
+<callout arearefs="pt-talker-5"><para>Click on a talker in the list to highlight it and click this button to move it down one row in the list. The lower a talker appears in the list, the lower its priority.</para></callout>
+<callout arearefs="pt-talker-6"><para>Click one of these buttons to apply the changes you have made to the running &ktts; system.</para></callout>
+</calloutlist>
+</para>
+
+<para>When you click the <guibutton>Add</guibutton> button, the <guilabel>Add Talker</guilabel> screen appears.</para>
+
+<para>
+ <screenshot>
+ <screeninfo>Add Talker screen.</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-addtalker-1" coords="1 1"/>
+ <area id="pt-addtalker-2" coords="1 1"/>
+ <area id="pt-addtalker-3" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="addtalker.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>Add Talker screen</phrase>
+ </textobject>
+ </mediaobjectco>
+ </screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-addtalker-1"><para>You can select a speech synthesis
+plugin by either <guilabel>Synthesizer</guilabel> name, or by the <guilabel>Language</guilabel> the synthesizer can speak.
+Check the radio button next to the corresponding box. When the
+<guilabel>Language</guilabel> radio button is checked, the
+<guilabel>Language</guilabel> box displays all the languages supported by
+all available synthesizers, and the <guilabel>Synthesizer</guilabel> box
+displays only those synthesizers that support the chosen language.
+When the <guilabel>Synthesizer</guilabel> radio button is checked,
+the <guilabel>Synthesizer</guilabel> box displays all available
+synthesizers, and the <guilabel>Language</guilabel> box displays
+only the languages supported by the chosen synthesizer.</para></callout>
+<callout arearefs="pt-addtalker-2"><para>Choose the language and
+synthesizer plugin here.</para></callout>
+<callout arearefs="pt-addtalker-3"><para>When you click here,
+most synthesizer plugins will automatically configure themselves,
+choosing a default setup. A new talker
+will appear in the list in the <guilabel>Talkers</guilabel> screen.
+Click the <guibutton>Edit</guibutton> button to display or edit the talker's
+configuration.</para></callout>
+</calloutlist>
+</para>
+
+<para>When you click the <guibutton>Add</guibutton> button on the
+<guilabel>Talkers</guilabel> tab and add a talker that cannot
+automatically configure itself, or click the
+<guibutton>Edit</guibutton> button,
+the <guilabel>Talker Configuration</guilabel> screen appears.
+Each speech synthesis plugin has a different
+<guilabel>Talker Configuration</guilabel> screen. The following is an example for
+configuring the Festival Interactive plugin. For specifics for each
+kind of plugin, see <xref linkend="configuration" />.</para>
+
+<para>
+<screenshot>
+<screeninfo>Talker Configuration</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-prop-1" coords="1 1"/>
+ <area id="pt-prop-2" coords="1 1"/>
+ <area id="pt-prop-3" coords="1 1"/>
+ <area id="pt-prop-4" coords="1 1"/>
+ <area id="pt-prop-5" coords="1 1"/>
+ <area id="pt-prop-6" coords="1 1"/>
+ <area id="pt-prop-7" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="festivalintconf.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>Talker Configuration</phrase>
+ </textobject>
+ </mediaobjectco>
+</screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-prop-1"><para>Specify the path to the Festival executable program.
+If Festival is in your PATH environment variable, just enter
+<userinput><replaceable>festival</replaceable></userinput>.</para></callout>
+<callout arearefs="pt-prop-2"><para>Click to scan for available voices.</para></callout>
+<callout arearefs="pt-prop-3"><para>Select a voice.</para></callout>
+<callout arearefs="pt-prop-4"><para>Select a character encoding for text sent to Festival.
+For voices that are known to &ktts;, this setting will be picked for you automatically. In general, western languages use ISO 8859-1. Eastern European languages such
+as Czech or Slovak use ISO 8859-2.</para></callout>
+<callout arearefs="pt-prop-5"><para>Click to test. You should hear a test sentence spoken.</para></callout>
+<callout arearefs="pt-prop-6"><para>Use these controls to set the volume, talking speed, and
+pitch (tone) of the synthesized speech. If any of these are disabled (grayed), the chosen
+voice does not support changing them.</para></callout>
+<callout arearefs="pt-prop-7"><para>Some voices, such as the MultiSyn voices, are so large
+that they require several seconds to load. Checking this box will cause them to be loaded
+when KTTSD is started, thereby saving time (at the expense of using more memory)
+before the first sentence is synthesized.</para></callout>
+</calloutlist>
+</para>
+
+<para>Click the <guibutton>OK</guibutton> button to save the talker configuration settings.</para>
+
+<warning><para>
+Be sure to click the <guibutton>Apply</guibutton> button, otherwise your
+changes will not take effect in the running &ktts; system.
+</para></warning>
+
+<para>Assuming the test worked, you are almost ready to begin using &ktts;.
+Now go back to the <guilabel>General</guilabel> tab and check the
+<guilabel>Enable Text-to-Speech System (KTTSD)</guilabel> box. This
+will start the &kde; TTS Daemon. See <xref linkend="general" />.
+You may now begin using &ktts; to
+speak text. Click the <guilabel>Jobs</guilabel> tab to create and manage text jobs.
+See <xref linkend="jobmgr" />.
+</para>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="general">
+<title>Starting KTTSD and Setting General Options</title>
+
+<para>Once you have configured at least one talker,
+you can start the &kde; Text-to-Speech System. Click on the
+<guilabel>General</guilabel> tab. The <guilabel>General</guilabel>
+screen appears. You can also set some general options on this screen.
+</para>
+
+<para>
+ <screenshot>
+ <screeninfo>The &kde; Text-to-Speech Manager (General tab).</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-gen-1" coords="1 1"/>
+ <area id="pt-gen-2" coords="1 1"/>
+ <area id="pt-gen-3" coords="1 1"/>
+ <area id="pt-gen-4" coords="1 1"/>
+ <area id="pt-gen-5" coords="1 1"/>
+ <area id="pt-gen-6" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="general.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>The &kde; Text-to-Speech Manager (General tab)</phrase>
+ </textobject>
+ </mediaobjectco>
+ </screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-gen-1"><para>Check this box to activate the &ktts; system.
+This starts the &kde; TTS Daemon (KTTSD). If KTTSD starts successfully,
+the <guilabel>Jobs</guilabel> tab will appear.
+Once KTTSD has been started, you can begin creating and speaking text jobs.
+See <xref linkend="jobmgr" />. Unchecking will stop KTTSD and deactivate the &kde; TTS system.
+<note><para>If this box is disabled, you have not yet configured any talkers
+(or you forgot to click the <guibutton>Apply</guibutton> button).
+See <xref linkend="configure-plugin"/>.</para></note>
+</para></callout>
+<callout arearefs="pt-gen-2"><para>When this box is checked, an icon appears
+in the system tray whenever <command>kttsmgr</command> is running. In this
+mode, clicking <guibutton>OK</guibutton> or <guibutton>Cancel</guibutton> does
+not cause <command>kttsmgr</command> to exit. Instead, the screen
+disappears but <command>kttsmgr</command> continues running in the system
+tray. Click the icon to restore the screen. To quit <command>kttsmgr</command>,
+right-click on the icon in the system tray and choose <guilabel>Quit</guilabel>.
+When unchecked, an icon does not appear in the system tray. Clicking <guibutton>OK</guibutton>
+or <guibutton>Cancel</guibutton> quits <command>kttsmgr</command>.
+<note><para>When <command>kttsmgr</command> exits,
+&ktts; keeps running if the <guilabel>Enable Text-to-Speech System (KTTSD)</guilabel> box is checked.</para></note>
+<note><para>This option does not take effect until the next time
+<command>kttsmgr</command> is started.</para></note>
+<note><para>This option has no effect when <command>kttsmgr</command> is
+running in the &kcontrol;.</para></note>
+</para></callout>
+<callout arearefs="pt-gen-3"><para>When this box is checked, the <command>kttsmgr</command> screen appears when you start <command>kttsmgr</command>. If unchecked, the
+<command>kttsmgr</command> icon appears in the system tray when
+<command>kttsmgr</command> is started, but the screen does not appear.
+Click the icon in the system tray to make the screen appear.</para></callout>
+<callout arearefs="pt-gen-4"><para>When this box is checked, and <command>kttsmgr</command> is
+not already running, it will appear in the system tray whenever KTTSD is speaking.
+This gives you an opportunity to stop or otherwise manage the speaking.</para></callout>
+<callout arearefs="pt-gen-5"><para>When this box is checked, and <command>kttsmgr</command>
+automatically appears in the system tray whenever speaking, it will also disappear
+automatically when speaking has finished.</para></callout>
+<callout arearefs="pt-gen-6"><para>Be sure to click here to save your settings.</para></callout>
+</calloutlist>
+</para>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="jobmgr">
+<title>Managing Text Jobs</title>
+
+<para>When you click the <guilabel>Jobs</guilabel> tab in <command>kttsmgr</command>,
+the <guilabel>Jobs</guilabel> screen appears.</para>
+
+<para>
+<screenshot>
+<screeninfo>The &kde; Text-to-Speech Manager (Jobs tab).</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-jobmgr-1" coords="1 1"/>
+ <area id="pt-jobmgr-2" coords="1 1"/>
+ <area id="pt-jobmgr-3" coords="1 1"/>
+ <area id="pt-jobmgr-4" coords="1 1"/>
+ <area id="pt-jobmgr-5" coords="1 1"/>
+ <area id="pt-jobmgr-6" coords="1 1"/>
+ <area id="pt-jobmgr-7" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="jobs.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>The &kde; Text-to-Speech Manager (Jobs tab)</phrase>
+ </textobject>
+ </mediaobjectco>
+</screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-jobmgr-1"><para>All of the text jobs currently in the queue
+are listed here, together with the application that queued the job,
+the current job state, number of sentences in the job,
+and current sentence number. The <guilabel>Talker ID</guilabel> corresponds to the
+<guilabel>ID</guilabel> column on the <guilabel>Talkers</guilabel> screen.
+</para></callout>
+<callout arearefs="pt-jobmgr-2"><para>The buttons in this row permit you to start,
+delete, and pause text jobs. Select a job in the list above, then click
+one of these buttons.</para></callout>
+<callout arearefs="pt-jobmgr-3"><para>The buttons in this row permit
+you to advance or rewind by sentence within the job selected in the list
+above. (Not all jobs have multiple parts.)</para></callout>
+<callout arearefs="pt-jobmgr-4"><para>The buttons in this row permit
+you to speak the text currently in the &kde; clipboard, or open a text file
+for speaking. You can also refresh the list of text jobs or
+change the talker for a job. See <xref linkend="selecttalker" />.</para></callout>
+<callout arearefs="pt-jobmgr-5"><para>The currently-speaking sentence
+appears here.</para></callout>
+<callout arearefs="pt-jobmgr-6"><para>When you click <guibutton>OK</guibutton>,
+all changes to settings on other screens are applied (if any) and
+<command>kttsmgr</command> minimizes to the system tray. Click on the icon
+in the system tray to restore the screen.</para></callout>
+<callout arearefs="pt-jobmgr-7"><para>Drag this divider to resize
+the jobs listing and <guilabel>Current sentence</guilabel> panels.</para></callout>
+</calloutlist>
+</para>
+
+<note><para>The <guilabel>Jobs</guilabel> tab only appears when KTTSD is running. If you do not see the <guilabel>Jobs</guilabel> tab, click on the
+<guilabel>General</guilabel> tab and check the
+<guilabel>Enable Text-to-Speech (KTTSD)</guilabel> box.</para>
+</note>
+
+<note><para>If you do not have the &arts; audio subsystem installed, but you
+do have ALSA, GStreamer, or aKode installed, click the <guilabel>Audio</guilabel> tab.
+See <xref linkend="audio" />.</para></note>
+
+<note><para>Only Text jobs are listed and controlled on this screen.
+Screen Reader Output, Warnings, and Messages are not displayed. For more information
+about &ktts; message types, see <xref linkend="filters" />.</para></note>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+<sect1 id="audio">
+<title>Audio Settings</title>
+
+<para>When you click the <guilabel>Audio</guilabel> tab in <command>kttsmgr</command>,
+the <guilabel>Audio</guilabel> screen appears.</para>
+
+<para>
+ <screenshot>
+ <screeninfo>The &kde; Text-to-Speech Manager (Audio tab).</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-audio-1" coords="1 1"/>
+ <area id="pt-audio-2" coords="1 1"/>
+ <area id="pt-audio-3" coords="1 1"/>
+ <area id="pt-audio-4" coords="1 1"/>
+ <area id="pt-audio-5" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="audio.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>The &kde; Text-to-Speech Manager (Audio tab)</phrase>
+ </textobject>
+ </mediaobjectco>
+ </screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-audio-1"><para>Select the method of audio output here.
+If a component is is grayed, either &ktts; was compiled
+without that support for that audio plugin, or &ktts; was unable to load the
+necessary libraries.
+</para></callout>
+<callout arearefs="pt-audio-2"><para>If GStreamer or aKode is selected for audio output,
+choose the audio sink method here. If no sinks are listed, you need
+to install at least one. If ALSA is selected, choose the PCM device here. See <xref linkend="requirements" />.
+</para></callout>
+<callout arearefs="pt-audio-3"><para>Adjust the speed of talking here.
+50% is approximately twice as slow as normal while 200% is approximately
+twice as fast. You must have the <command>sox</command> utility installed for this setting
+to work.
+</para></callout>
+<callout arearefs="pt-audio-4"><para>When this box is checked, &ktts; will
+copy temporary audio files (.wav files) into the indicated folder. Choose
+any folder on your hard drive you like, but you must have write access to it.
+This can be useful for creating audio files of speech for other purposes.
+The files will have names of the form <filename>kttsd-J-SS</filename> where
+<filename>J</filename> is the job number and <filename>SS</filename> is the sentence number.
+Existing files with the same name will be deleted.
+<emphasis>Do not forget to uncheck this box, otherwise your hard drive will fill up!</emphasis>
+</para></callout>
+<callout arearefs="pt-audio-5"><para>Be sure to click <guibutton>Apply</guibutton>
+to apply the new settings to the running &ktts; system.
+</para></callout>
+</calloutlist>
+</para>
+
+<note><para>There are two ways to adjust the speed of speech in &ktts;.
+Many of the <guilabel>Talkers</guilabel> have a <guilabel>Speed</guilabel>
+setting in their configuration dialogs, which you can display by clicking
+<guibutton>Edit</guibutton> on the <guilabel>Talkers</guilabel> screen. This
+<guilabel>Speed</guilabel> setting on the <guilabel>Audio</guilabel> screen
+is in addition to the talker speed setting and generally can be used
+even if the talker does not support a speed setting. For this speed setting
+to work, you must have the <command>sox</command>
+utility installed on your system (Debian users:
+<command>apt-get install sox</command>). Also, this speed setting is ignored
+when speaking text containing SSML. (See <xref linkend="ssml" />)</para></note>
+
+<note><para>The list of ALSA devices includes all the ALSA PCM devices and
+plugins configured in your system. Many of the choices will not work.
+You must experiment to find a device that works for you. If in doubt,
+choose <guilabel>default</guilabel>.</para></note>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+<sect1 id="interruption">
+<title>Text Interruption Settings</title>
+
+<para>When you click the <guilabel>Interruption</guilabel> tab in <command>kttsmgr</command>,
+the <guilabel>Interruption</guilabel> screen appears.</para>
+
+<para>
+<screenshot>
+<screeninfo>The &kde; Text-to-Speech Manager (Interruption tab).</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-interruption-1" coords="1 1"/>
+ <area id="pt-interruption-2" coords="1 1"/>
+ <area id="pt-interruption-3" coords="1 1"/>
+ <area id="pt-interruption-4" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="interruption.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>The &kde; Text-to-Speech Manager (Interruption tab)</phrase>
+ </textobject>
+ </mediaobjectco>
+</screenshot>
+</para>
+
+<para>This screen permits you to specify special actions to be taken whenever
+a text job is interrupted by another, higher priority, message. There are
+four kinds of speech jobs that &ktts; handles:
+<itemizedlist>
+<listitem><para>Regular text.</para></listitem>
+<listitem><para>Messages.</para></listitem>
+<listitem><para>Warnings.</para></listitem>
+<listitem><para>Screen Reader Output.</para></listitem>
+</itemizedlist>
+</para>
+
+<para>Screen Reader Output has the highest priority. It is reserved for use
+by Screen Reader applications. Screen Reader Output preempts all other
+messages, causing those jobs to pause. Once the Screen Reader Output has
+been spoken, the preempted jobs will automatically resume.
+</para>
+
+<para>Warnings are the next highest priority. It is reserved for high-priority
+messages, such as "CPU is over-heating." A Warning will preempt Messages
+and regular text, causing those jobs to pause. Once the Warning has been
+spoken, the preempted jobs will automatically resume.</para>
+
+<para>Messages are the next highest priority. A Message will preempt regular
+text jobs. &kmouth; is an example of an application that uses Messages.
+For example, while reading out long text from a web page,
+&kmouth; can be used to greet someone who walks into the room.</para>
+
+<para>All four kinds of jobs are queues, except for Screen Reader Output.
+If a Screen Reader Output is sent from an application while
+&ktts; is speaking another Screen Reader Output, the speaking message
+is stopped and discarded.</para>
+
+<para>When a text job is interrupted by a Message, Warning, or Screen Reader Output,
+&ktts; will add the audio outputs on this screen to the stream.</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-interruption-1"><para>This message is spoken whenever a regular text job is interrupted.</para></callout>
+<callout arearefs="pt-interruption-2"><para>This audio file is sounded whenever a regular text job is interrupted. If both a <guilabel>Pre-sound</guilabel>
+and a <guilabel>Pre-message</guilabel> are specified, the
+<guilabel>Pre-sound</guilabel> is sounded before the <guilabel>Pre-message</guilabel>.</para></callout>
+<callout arearefs="pt-interruption-3"><para>This message is spoken whenever an
+interrupted text job resumes.</para></callout>
+<callout arearefs="pt-interruption-4"><para>This audio file is sounded whenever an
+interrupted text job resumes. It is sounded last.</para></callout>
+</calloutlist>
+</para>
+
+<note><para>The settings on this screen apply only to regular text jobs.
+Messages, Warnings, and Screen Reader Outputs have no special actions when
+they are preempted by a higher-priority message.</para></note>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="web">
+<title>Speaking Text from Web Pages</title>
+
+<para>While running the &kde; &konqueror; web browser, you can speak the text
+of the web page displayed. First ensure that &ktts; is running.
+Highlight the text you want spoken and choose
+<menuchoice>
+ <guisubmenu>Tools</guisubmenu>
+ <guisubmenu>Speak Text</guisubmenu>
+</menuchoice> on the main menu.
+<action>After a moment, the highlighted text should begin speaking.</action>
+</para>
+
+<tip><para>It is almost always a good idea to highlight the text on the
+web page you want spoken. You can skip this step, but you will
+hear a lot of &HTML; headers and other invisible tags spoken.</para></tip>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="kate">
+<title>Speaking Text from &kate; Text Editor</title>
+
+<para>While running the &kde; Advanced Text Editor (&kate;), you can speak the text
+displayed. First ensure that &ktts; is running.
+Highlight the text you want spoken and choose
+<menuchoice>
+ <guisubmenu>Tools</guisubmenu>
+ <guisubmenu>Speak Text</guisubmenu>
+</menuchoice> on the main menu.
+<action>After a moment, the highlighted text should begin speaking.</action>
+</para>
+
+<tip><para>You do not have to first highlight text. In this case, the entire
+file will be spoken.</para></tip>
+
+<tip><para>This also works when &kate; is running embedded in another application,
+such as &konqueror; or &quanta;.</para></tip>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+<sect1 id="knotify">
+<title>Speaking Notifications (KNotify)</title>
+
+<para>KNotify is the notification subsystem within &kde;, which alerts you
+to events you configure within the &kde; system. You can configure
+&ktts; to speak text notifications.</para>
+
+<para>For example, &konversation;, a &kde; IRC application, permits you
+to configure a wide variety of notifications. For instance, you can tell
+&konversation; to notify you whenever a message appears in an IRC channel
+with your nickname in it. Together with &ktts; you can
+have &kde; speak the text of the IRC message to you.</para>
+
+<para>In general, if a &kde; application supports KNotify, a
+<guilabel>Notifications</guilabel> menu item will appear under the
+application's <guilabel>Settings</guilabel> menu. The specifics for configuring
+each application with KNotify vary from application to application.</para>
+
+<para>To enable &ktts; to speak KNotify text notifications,
+start <command>kttsmgr</command> and click the <guilabel>Notifications</guilabel> tab.
+The <guilabel>Notifications</guilabel> screen appears.</para>
+
+<para>
+<screenshot>
+<screeninfo>The &kde; Text-to-Speech Manager (Notifications tab).</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-notify-1" coords="1 1"/>
+ <area id="pt-notify-2" coords="1 1"/>
+ <area id="pt-notify-3" coords="1 1"/>
+ <area id="pt-notify-4" coords="1 1"/>
+ <area id="pt-notify-5" coords="1 1"/>
+ <area id="pt-notify-6" coords="1 1"/>
+ <area id="pt-notify-7" coords="1 1"/>
+ <area id="pt-notify-8" coords="1 1"/>
+ <area id="pt-notify-9" coords="1 1"/>
+ <area id="pt-notify-10" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="notifications.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>The &kde; Text-to-Speech Manager (Notification tab)</phrase>
+ </textobject>
+ </mediaobjectco>
+</screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-notify-1"><para>Check this box to enable speaking of
+&kde; notifications. If unchecked, everything else on this screen is disabled
+and &ktts; does not speak any notifications.</para></callout>
+<callout arearefs="pt-notify-2"><para>When checked, any application
+that sends an event with a sound will not be spoken by &ktts;.</para></callout>
+<callout arearefs="pt-notify-3"><para>Use these buttons to add or delete
+application events from the list below. When you click
+the <guibutton>Add</guibutton> button, a screen appears in which
+you select the application and event you want to add to the list.
+</para></callout>
+<callout arearefs="pt-notify-4"><para>This event will speak the message
+&konversation; sends when someone mentions your nickname in an Internet Relay Chat message.
+</para></callout>
+<callout arearefs="pt-notify-5"><para>For all other events coming from
+&konversation;, no action will be taken in &ktts;.</para></callout>
+<callout arearefs="pt-notify-6"><para>For all events not otherwise
+specified in the list, no action will be taken in &ktts;.</para></callout>
+<callout arearefs="pt-notify-7"><para>Use this box to specify what
+&ktts; should do when it receives an event. Your choices are:</para>
+<para>
+<variablelist>
+<varlistentry>
+<term>Speak event name</term>
+<listitem><para>Speaks the name of the event; what you see listed in the
+event list on this screen.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>Speak the notification message</term>
+<listitem><para>Speaks the message as it is sent from the application.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>Do not speak the notification</term>
+<listitem><para>Does not speak this event at all.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>Speak custom text</term>
+<listitem><para>Speaks the text you enter in the box to the right.</para></listitem>
+</varlistentry>
+</variablelist>
+</para>
+</callout>
+<callout arearefs="pt-notify-8"><para>If the action is
+<guilabel>Speak custom text</guilabel>, enter the text of the message
+you would like spoken here. Within the message, you may use the following
+substitution strings:</para>
+<para>
+<variablelist>
+<varlistentry>
+<term>%e</term>
+<listitem><para>The name of the event</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>%a</term>
+<listitem><para>The name of the application that sent the event</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>%m</term>
+<listitem><para>The message the application sent</para></listitem>
+</varlistentry>
+</variablelist>
+</para>
+</callout>
+<callout arearefs="pt-notify-9"><para>Test the message by clicking here.</para></callout>
+<callout arearefs="pt-notify-10"><para>You may specify the attributes of the
+desired talker to speak the notification message here.
+<command><userinput>default</userinput></command>
+will use the topmost talker listed in the <guilabel>Talkers</guilabel>
+screen. See <xref linkend="selecttalker" />.
+</para></callout>
+</calloutlist>
+</para>
+
+<para>Notice there are three levels of events. If an action for a specific event
+of a specific application is specified, that action is taken. Otherwise, if
+an action for all other events of a specific application is specified, that
+action is taken. Otherwise, the action specified for all other events
+under <guilabel>Default (all other events)</guilabel> is taken.</para>
+
+<para>The event <guilabel>all notifications</guilabel>
+for application <guilabel>Default (all other events)</guilabel>
+may not be deleted from the list. For the default all other events,
+you may specify the kind of notifications that are spoken, as follows:</para>
+
+<variablelist>
+<varlistentry>
+<term>none</term>
+<listitem><para>None will be spoken.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>notification dialogs</term>
+<listitem><para>Notifications that display a dialog on your screen, that you must then
+dismiss, will be spoken.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>passive popups</term>
+<listitem><para>Notifications that display a passive dialog on your screen,
+that automatically disappear after a moment, will be spoken.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>notification dialogs and passive popups</term>
+<listitem><para>Notifications that display on screen, passively or not,
+will be spoken.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>all notifications</term>
+<listitem><para>All notifications, regardless of whether they produce
+a display on screen, will be spoken.</para></listitem>
+</varlistentry>
+</variablelist>
+
+<tip><para>String Replacer filters are a good way to clean up messages
+sent from applications if they are mispronounced or misspoken in
+&ktts;. The <filename>kmail.xml</filename> file, which
+comes with &ktts;, is a good example. It removes <command>br</command>,
+and <command>b</command> tags from the &kmail; notification messages and also removes the
+phrase <command>/local/inbox/</command>, since this
+may be safely assumed in most cases. See <xref linkend="stringreplacer" />.
+</para></tip>
+
+<para>Use the <guibutton>Save</guibutton> button to save your
+notification settings to a file. Use the <guibutton>Load</guibutton>
+button to load saved settings from a file. The loaded events are merged
+with existing events in the list. If you want to start with
+an empty event list, click the <guibutton>Clear</guibutton>
+button first. All events except for <guilabel>all notifications</guilabel>
+will be erased.</para>
+
+<note><para>Be sure to click <guibutton>Apply</guibutton>
+or <guibutton>OK</guibutton> to save your settings.</para></note>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+<sect1 id="ssml">
+<title>SSML</title>
+
+<para>The Speech Synthesis Markup Language (SSML) is a W3C standard
+for marking up text for speech output. It provides tags for controlling
+voices, rate of speech, volume, gender, and pitch (tone). It also
+provides tags for controlling how words are spoken, for instance
+spelling out abbreviations. SSML is part of the VoiceXML specification,
+which is also a W3C standard.</para>
+
+<para>At this time, &ktts; provides limited and very basic support for
+SSML. It currently has the following restrictions.</para>
+
+<itemizedlist>
+<listitem><para>Works only with the Festival Interactive and Hadifix Talkers.</para></listitem>
+<listitem><para>You must install the <command>rab_diphone</command>
+(British male) voice, as this is the default voice Festival uses when speaking
+SSML.</para></listitem>
+<listitem><para>The <guilabel>Speed</guilabel> setting on the <guilabel>Audio</guilabel>
+screen is ignored when speaking text containing SSML.</para></listitem>
+<listitem><para>If the <guilabel>Speed</guilabel> or <guilabel>Pitch</guilabel>
+settings in the Festival configuration dialog are not set to 100%, it
+will usually cause the SSML text to be spoken in a monotone.</para></listitem>
+</itemizedlist>
+
+<para>The following sample text can be used to experiment with SSML.</para>
+
+<programlisting><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE speak PUBLIC "-//W3C//DTD SYNTHESIS 1.0//EN"
+ "http://www.w3.org/TR/speech-synthesis/synthesis.dtd">
+
+<speak version="1.0" xml:lang="en-US">
+ <prosody pitch="low">
+ Who's been sleeping in my bed?
+ </prosody>
+ said papa bear.
+ <prosody pitch="medium">
+ Who's been sleeping in my bed?
+ </prosody>
+ said momma bear.
+ <prosody pitch="high">
+ Who's been sleeping in my bed?
+ </prosody>
+ said baby bear.
+</speak>
+]]></programlisting>
+
+<para>More robust support for SSML is planned for the next version of
+&ktts;.
+</para>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+<sect1 id="filters">
+<title>Filters (Advanced)</title>
+
+<para>Filters are an advanced feature of &ktts;. For the
+basic operation of &ktts;, they are not needed.</para>
+
+<para>Filters are used to pre-process text before it is sent to the
+speech synthesis engine. They are useful for enhancing speech,
+substituting for misspoken words or abbreviations, choosing the
+appropriate language and talker to do the speaking, or working around
+certain limitations of speech synthesizers and their voices.</para>
+
+<!-- ...................................................................... -->
+
+<sect2 id="msg-types">
+<title>Types of &ktts; Messages</title>
+
+<para>To understand how to use filters, it is
+helpful to first understand how text is processed by &ktts;.
+Text spoken by &ktts; is of four possible types.</para>
+
+<para>
+<itemizedlist>
+<listitem><para>Screen Reader Output.</para></listitem>
+<listitem><para>Warnings.</para></listitem>
+<listitem><para>Messages</para></listitem>
+<listitem><para>Text Jobs</para></listitem>
+</itemizedlist>
+</para>
+
+<para>The type is determined by the application that sends the text
+to &ktts;.</para>
+
+<para>Screen Reader Output has the highest priority. It is reserved for use
+by Screen Reader applications. Screen Reader Output preempts all other
+messages, causing those jobs to pause. Once the Screen Reader Output has
+been spoken, the preempted messages will automatically resume.
+</para>
+
+<para>Warnings are the next highest priority. It is reserved for high-priority
+messages, such as "CPU is over-heating." A Warning will preempt Messages
+and regular text, causing those jobs to pause. Once the Warning has been
+spoken, the preempted messages will automatically resume.</para>
+
+<para>Messages are the next highest priority. A Message will preempt regular
+text jobs. &kmouth; is an example of an application that uses Messages.
+For example, while reading out long text from a web page,
+&kmouth; can be used to greet someone who walks into the room.
+&kde; Notifications are also Messages (see <xref linkend="knotify" />).</para>
+
+<para>The rest are ordinary Text Jobs. Any job you initiate from the
+<guilabel>Jobs</guilabel> tab is a Text Job. KSayit is an example
+of an application that uses Text Jobs. Text Jobs are intended for
+longer speech output that is not urgent.</para>
+
+<para>All four kinds of jobs are queues, except for Screen Reader Output.
+If a Screen Reader Output is sent from an application while
+&ktts; is speaking another Screen Reader Output, the speaking message
+is stopped and discarded.</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+<sect2 id="filter-types">
+<title>Types of Filters</title>
+
+<para>The first thing you must know about filters is that they are
+never applied to Screen Reader Output. They are applied to
+Warnings, Messages, and Text jobs, and also &kde; notifications (KNotify).</para>
+
+<para>There are two kinds of filters --
+ordinary filters and Sentence Boundary Detector (SBD) filters.
+SBDs break text up into individual sentences. This allows
+&ktts; to begin speaking faster because it need only
+synthesize the first sentence; not the entire Text Job.
+It also permits you to advance or rewind by sentence in the
+<guilabel>Jobs</guilabel> tab, or to stop or pause Text Jobs when
+the speech synthesizer does not directly support stopping of speech.
+</para>
+
+<para>Ordinary filters process the text and pass it on to the
+next filter. There are currently three kinds of ordinary filters.
+</para>
+
+<para>
+<itemizedlist>
+<listitem><para>String Replacers.</para></listitem>
+<listitem><para>&XML; Transformers</para></listitem>
+<listitem><para>Talker Choosers.</para></listitem>
+</itemizedlist>
+</para>
+
+<note><para>Filters are implemented using a plugin architecture.
+In the future, there may be additional kinds of filters.</para></note>
+
+<para>String Replacer filters substitute pieces of text with
+other text. The replaced pieces are matched either as words or
+as regular expressions. &ktts; comes with pre-defined
+String Replacer filters for speaking abbreviations, speaking
+chat emoticons, such as ":-)", or reformatting notification
+messages from &konversation; or &kmail; into a more understandable
+form.
+</para>
+
+<para>&XML; Transformers use an &XML; Style Language - Transforms (XSLT)
+file to convert &XML; of one format to another format.
+&ktts; comes with a couple of XSLT files for converting
+&XHTML; into SSML.
+</para>
+
+<para>Talker Choosers permit you redirect jobs to a talker
+based on the contents of the text, or upon the application that sent it
+to &ktts;. For example, if you have configured a female talker
+in the <guilabel>Talkers</guilabel> tab, you can direct text coming from
+KSayIt to that talker. See <xref linkend="configure-plugin" />.
+</para>
+
+<para>Each of these kinds of filters has configurable rules for when
+the filter should apply itself to the text to be spoken. If the
+filter determines that it should not apply itself, the text
+is passed on to the next filter unaltered.</para>
+
+<para>When a Text Job, Message, Warning, or &kde; Notification message is sent to &ktts;,
+it passes through each of the enabled filters you have configured in the
+screen below. The order is from top to bottom. After passing through
+each of the ordinary filters listed in the top portion of the screen, Text Jobs
+are passed to the <guilabel>Sentence Boundary Detector</guilabel> (SBD) filters.
+(&kde; Notifications, Warnings, and Messages never pass through SBD filters.)
+Unlike ordinary filters, the first SBD filter that makes changes to the text
+stops any further filtering.
+</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+<sect2 id="configure-filters">
+<title>Configuring Filters</title>
+
+<para>To use filters, click the <guilabel>Filters</guilabel> tab in <command>kttsmgr</command>.</para>
+
+<para>
+ <screenshot>
+ <screeninfo>The &kde; Text-to-Speech Manager (Filters tab).</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-filters-1" coords="1 1"/>
+ <area id="pt-filters-2" coords="1 1"/>
+ <area id="pt-filters-3" coords="1 1"/>
+ <area id="pt-filters-4" coords="1 1"/>
+ <area id="pt-filters-5" coords="1 1"/>
+ <area id="pt-filters-6" coords="1 1"/>
+ <area id="pt-filters-7" coords="1 1"/>
+ <area id="pt-filters-8" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="filters.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>The &kde; Text-to-Speech Manager (Filters tab)</phrase>
+ </textobject>
+ </mediaobjectco>
+ </screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-filters-1"><para>This is the list of configured ordinary filters.
+If unchecked, the filter is inactive and will be bypassed.
+Filters are applied in the order specified here, top to bottom.</para></callout>
+<callout arearefs="pt-filters-2"><para>Click here to add a new filter. You will
+be prompted for the kind of filter to add. After choosing the kind,
+see the configuration dialogs below.</para></callout>
+<callout arearefs="pt-filters-3"><para>Click here to remove a filter.</para></callout>
+<callout arearefs="pt-filters-4"><para>Click here to change the configuration
+of a filter. See the configuration dialogs below.</para></callout>
+<callout arearefs="pt-filters-5"><para>Click these buttons to move a filter
+up or down in the list.</para></callout>
+<callout arearefs="pt-filters-6"><para>These are the Sentence Boundary Detector
+filters. When you first start &ktts;, the Standard Sentence Boundary Detector
+is automatically configured for you. You can change this filter's configuration,
+or add additional Sentence Boundary Detectors, but we advise beginners not
+to change them.</para></callout>
+<callout arearefs="pt-filters-7"><para>This drop-down button permits you
+to add, remove, edit, or change the order of Sentence Boundary Detector filters.</para></callout>
+<callout arearefs="pt-filters-8"><para>Be sure to click here, otherwise your
+settings will not take effect.</para></callout>
+</calloutlist>
+</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+<sect2 id="stringreplacer">
+<title>Configuring String Replacer Filters</title>
+
+<para>You configure String Replacer filters by supplying
+a list of words or regular expressions to be matched.
+When the matched words or regular expressions are found in the
+text, each is replaced by a substitute string you supply.
+Matching is case insensitive.</para>
+
+<para>
+ <screenshot>
+ <screeninfo>String Replacer</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-stringreplacer-1" coords="1 1"/>
+ <area id="pt-stringreplacer-2" coords="1 1"/>
+ <area id="pt-stringreplacer-3" coords="1 1"/>
+ <area id="pt-stringreplacer-4" coords="1 1"/>
+ <area id="pt-stringreplacer-5" coords="1 1"/>
+ <area id="pt-stringreplacer-6" coords="1 1"/>
+ <area id="pt-stringreplacer-7" coords="1 1"/>
+ <area id="pt-stringreplacer-8" coords="1 1"/>
+ <area id="pt-stringreplacer-9" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="stringreplacer.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>String Replacer</phrase>
+ </textobject>
+ </mediaobjectco>
+ </screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-stringreplacer-1"><para>Enter a name for your filter. Use any
+name you like that distinquishes it from all other filters.</para></callout>
+<callout arearefs="pt-stringreplacer-2"><para>This is the list of words
+and regular expressions. The filter searches for matches on each string in
+the <guilabel>Match</guilabel> column, replacing the matched string
+with the string in the <guilabel>Replace With</guilabel> column. The list
+is processed in the order displayed, top to bottom.</para></callout>
+<callout arearefs="pt-stringreplacer-3"><para>Click here to add another word or
+regular expression to the list.</para></callout>
+<callout arearefs="pt-stringreplacer-4"><para>Click here to move the currently
+highlighted word or regular expression up or down in the list.</para></callout>
+<callout arearefs="pt-stringreplacer-5"><para>Click to change an existing word
+or regular expression in the list.</para></callout>
+<callout arearefs="pt-stringreplacer-6"><para>Click to remove the currently
+highlighted word or regular expression from the list.</para></callout>
+<callout arearefs="pt-stringreplacer-7"><para>Use these buttons to load
+a list of words or regular expression from a file, save the current list to
+a file, or clear the entire list. When loading from a file, the items in the
+file are appended to the existing list.</para></callout>
+<callout arearefs="pt-stringreplacer-8"><para>If not blank, the filter will
+apply itself only if the job's talker language matches
+the language you enter here. Click the button to display a list of languages.
+You may select more than one language by pressing
+<keycap>&Ctrl;</keycap> while clicking.</para></callout>
+<callout arearefs="pt-stringreplacer-9"><para>If not blank, the filter will
+apply itself only if the text came from one of the applications listed.
+You may enter more than one application separated by commas.
+Example: <command><userinput>konversation,kmail</userinput></command></para>
+<tip><para>You can discover the <guilabel>Application ID</guilabel>
+of running programs using the <command>&kdcop;</command> program.
+You should leave the &DCOP; numbers out. For example, if &kdcop; shows
+an Application ID of <command>kopete-3432</command>, you would just
+enter <command><userinput>kopete</userinput></command>.</para></tip></callout>
+</calloutlist>
+</para>
+
+<para>The String Replacer filter will only apply itself to the text
+if all non-blank conditions are met in the
+<guilabel>Apply This Filter When</guilabel> box.
+if all the boxes are blank, the filter will apply to all text.</para>
+
+<para>All matching is case insensitive.</para>
+
+<para>When matching words, the String Replacer filter internally uses a
+regular expression of the form <command>\s<userinput>word</userinput>\s</command>.
+In other words, the word must have word boundaries (spaces) on either side of it.</para>
+
+<para>A discussion on how to write regular expressions is outside the scope
+of this handbook. If you have the &kde; Regular Expression editor installed,
+there is a button available on the <guilabel>Add</guilabel> or
+<guilabel>Edit</guilabel> screens that will assist you at
+constructing regular expressions. The &kde; Regular Expression Editor is part
+of the <command>kdeutils</command> package.</para>
+
+<para>&ktts; comes with a few word list files, including a list
+of emoticons, such as ":-)", some abbreviations typically used in IRC or
+instant messaging applications, and a list of other abbreviations.
+There is also a list of special characters which the current version
+of the Polish Festival voice cannot handle.
+If you develop useful word lists of your own, use the <guibutton>Save</guibutton>
+button to save them to a file and send them to the
+&ktts; team for inclusion in the next version.</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+<sect2 id="xmltransformer">
+<title>Configuring &XML; Transformer Filters</title>
+
+<para>The &XML; Transformer filter uses XSLT files to transform &XML; from
+one format to another. XSLT, the &XML; Style Language - Transforms, is a W3C
+standard language for performing such transformations.
+It can only be used on well-formed &XML;. You must have the
+<command>xsltproc</command> utility installed.</para>
+
+<para>
+ <screenshot>
+ <screeninfo>&XML; Transformer</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-xmltransformer-1" coords="1 1"/>
+ <area id="pt-xmltransformer-2" coords="1 1"/>
+ <area id="pt-xmltransformer-3" coords="1 1"/>
+ <area id="pt-xmltransformer-4" coords="1 1"/>
+ <area id="pt-xmltransformer-5" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="xmltransformer.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>&XML; Transformer</phrase>
+ </textobject>
+ </mediaobjectco>
+ </screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-xmltransformer-1"><para>Enter a name for your filter. Use any
+name you like that distinquishes it from all other filters.</para></callout>
+<callout arearefs="pt-xmltransformer-2"><para>Enter the full path
+to an existing XSLT file, which will perform the transformation.</para></callout>
+<callout arearefs="pt-xmltransformer-3"><para>Specify the path to the
+<command>xsltproc</command> utility. If xsltproc is in your environment
+PATH, simply enter <command><userinput>xsltproc</userinput></command>.</para></callout>
+<callout arearefs="pt-xmltransformer-4"><para>If not blank, the filter
+will apply itself only if the &XML; has the specified root element
+or a <command><![CDATA[<!DOCTYPE]]></command> specification
+beginning with the entered string. This distinquishes one
+form of &XML; from another. For example,
+<command><userinput>html</userinput></command> in the
+<guilabel>DOCTYPE</guilabel> box will match
+<command><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">]]></command>.
+</para></callout>
+<callout arearefs="pt-xmltransformer-5"><para>If not blank, the filter will
+apply itself only if the text came from one of the applications listed.
+You may enter more than one application separated by commas.
+Example: <command><userinput>konversation,kmail</userinput></command></para>
+<tip><para>You can discover the <guilabel>Application ID</guilabel>
+of running programs using the <command>&kdcop;</command> program.
+You should leave the &DCOP; numbers out. For example, if &kdcop; shows
+an Application ID of <command>kopete-3432</command>, you would just
+enter <command><userinput>kopete</userinput></command>.</para></tip></callout>
+</calloutlist>
+</para>
+
+<para>The &XML; Transformer filter will only apply itself to the text
+if the specified root element or DOCTYPE are met and if the
+application ID is met in the
+<guilabel>Apply This Filter When</guilabel> box. If an item in this
+box is blank, the test is not performed, so if all the
+boxes are blank, the filter will apply itself to all text. However,
+you should fill in at least one box, since many text jobs will not be in
+&XML; format.</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+<sect2 id="talkerchooser">
+<title>Configuring Talker Chooser Filters</title>
+
+<para>Talker Chooser filters are used to direct the text to a desired
+talker configured in the <guilabel>Talker</guilabel> tab, or to any
+talker having specified attributes. For example,
+you can specify that text coming from <command>kmail</command>
+should be spoken using a talker configured with a female voice.
+See <xref linkend="configure-plugin" />.</para>
+
+<para>Just before &ktts; begins sending text to each of the
+filters, it picks a talker to speak the text. The talker chosen is
+based on the talker attributes specified by the application that sent
+the text to &ktts; and the attributes of the talkers that
+you have configured on the <guilabel>Talkers</guilabel> tab.
+The Talker Chooser filter permits you to override the
+chosen talker.
+</para>
+
+<para>
+ <screenshot>
+ <screeninfo>Talker Chooser</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-talkerchooser-1" coords="1 1"/>
+ <area id="pt-talkerchooser-2" coords="1 1"/>
+ <area id="pt-talkerchooser-3" coords="1 1"/>
+ <area id="pt-talkerchooser-4" coords="1 1"/>
+ <area id="pt-talkerchooser-5" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="talkerchooser.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>Talker Chooser</phrase>
+ </textobject>
+ </mediaobjectco>
+ </screenshot>
+</para>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-talkerchooser-1"><para>Enter a name for your filter. Use any
+name you like that distinquishes it from all other filters.</para></callout>
+<callout arearefs="pt-talkerchooser-2"><para>If not blank, the filter will apply
+itself only if the text contains the entered regular expression. If it is installed,
+click the browse button to launch the &kde; Regular Expression Editor to assist you at entering
+the regular expression.</para>
+<tip><para>For better performance, try to "anchor" the regular expression to the
+start of the string. In other words, start your regular expression with
+<command><userinput><![CDATA[^]]></userinput></command>.</para></tip></callout>
+<callout arearefs="pt-talkerchooser-3"><para>If not blank, the filter will
+apply itself only if the text came from one of the applications listed.
+You may enter more than one application separated by commas.
+Example: <command><userinput>konversation,kmail</userinput></command></para>
+<tip><para>You can discover the <guilabel>Application ID</guilabel>
+of running programs using the <command>&kdcop;</command> program.
+You should leave the &DCOP; numbers out. For example, if &kdcop; shows
+an Application ID of <command>kopete-3432</command>, you would just
+enter <command><userinput>kopete</userinput></command>.</para></tip></callout>
+<callout arearefs="pt-talkerchooser-4"><para>Specify the attributes of the
+talker you prefer to speak the text here. If the text meets the filter
+conditions above, a talker will be chosen that most closely matches
+the attributes you specify here. Click the button at the right to
+display the <guilabel>Select Talker</guilabel> screen.
+See <xref linkend="selecttalker" />.</para></callout>
+<callout arearefs="pt-talkerchooser-5"><para>Use these buttons
+to save your Talker Chooser settings, load settings from a saved file,
+or clear all the settings.</para></callout>
+</calloutlist>
+</para>
+
+<para>The Talker Chooser filter will only apply itself to the text
+if all non-blank conditions are met in the
+<guilabel>Apply This Filter When</guilabel> box. You must fill in
+at least one of the boxes.</para>
+
+<para>The easiest way to learn how to configure Talker Choosers is
+to experiment. Disable the Talker Chooser and submit some text.
+In the <guilabel>Jobs</guilabel> tab, note the talker that
+&ktts; chooses. Click the <guibutton>Change Talker</guibutton>
+button, enter some attributes, and try again to see how the choice is affected.
+Of course, you must have more than one talker configured for
+the Talker Chooser to do anything.</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+<sect2 id="sbd">
+<title>Configuring Sentence Boundary Detector Filters</title>
+
+<para>Sentence Boundary Detector (SBD) filters break text up into individual sentences.
+This is important because it</para>
+
+<itemizedlist>
+<listitem><para>allows &ktts; to begin speaking faster
+because it need only synthesize the first sentence, rather than the entire
+block of text, which might be very long, and</para></listitem>
+<listitem><para>allows you to rewind and advance by sentences in the
+<guilabel>Jobs</guilabel> tab, and</para></listitem>
+<listitem><para>allows you to pause or stop Text Jobs in the
+<guilabel>Jobs</guilabel> tab even if the speech synthesizer is not
+capable of being stopped.</para></listitem>
+</itemizedlist>
+
+<para>For these reasons, the Standard Sentence Boundary Detector filter
+is automatically configured the first time you run <command>kttsmgr</command>
+and cannot be disabled (although you can remove it). We advise you
+not to modify this filter unless you know what you are doing.</para>
+
+<para>You can, however, add additional SBD filters to solve certain
+problems. For example, as of February 2005, the Polish Festival voice
+has the annoying attribute of speaking sentence punctuation. It will
+speak the periods at the end of each sentence, for instance. You cannot solve this problem
+by creating a String Replacer filter to remove the sentence punctuation,
+because doing so will prevent the Standard SBD from recognizing any
+sentences. Instead, you can create a modified version of the
+Standard SBD that recognizes sentences while simultaneously removing
+the sentence punctuation. To do this, add an SBD filter and use the
+<guibutton>Load</guibutton> button to load the <filename>polish_festival_sbdrc</filename>
+file that comes with &ktts;.</para>
+
+<para>SBD filters work by matching an end-of-sentence regular expression
+and inserting Tab (decimal 8) characters at the sentence boundaries.
+(All Tab characters are automatically stripped from text before filtering begins.)
+Note that the Standard SBD preserves the sentence punctuation.
+</para>
+
+<para>SBD filters are never applied to &kde; Notification messages (knotify),
+Warnings, Messages, or Screen Reader Outputs.</para>
+
+<para>If you accidentally remove the Standard Sentence Boundary Detectory filter,
+you can get it back by loading the <filename>standard_sbdrc</filename> file,
+which comes with &ktts;.</para>
+
+</sect2>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+<sect1 id="selecttalker">
+<title>Selecting Talkers (Advanced)</title>
+
+<para>You can configure
+any number of talkers in the <guilabel>Talkers</guilabel> tab.
+See <xref linkend="configure-plugin" />. When applications send text
+to &ktts;, they may specify the attributes of a desired
+talker to speak the text. &ktts; will pick the closest
+matching talker from among the talkers you have configured to satisfy
+the application's request. For example, an application might request
+the text be spoken by an English female voice. If you have configured
+a talker with English language and female gender, that talker will be used.
+If you have configured all English male talkers, one of those talkers
+will be used. If an application specifies no attributes,
+the default (topmost) talker listed in the <guilabel>Talkers</guilabel>
+tab is used.</para>
+
+<para>When applications specify the attributes of the desired talker,
+they may indicate that certain attributes are "preferred" over other
+attributes. For example, an application may specify that it wishes
+that a female loud voice speak the text, and that the loud attribute is
+"preferred" over the female attribute. If you had a female soft talker
+and a male loud talker configured, &ktts; will choose the male
+loud talker to do the speaking. Since language is a critical parameter
+in making speech understandable, it is always a "preferred" attribute.</para>
+
+<para>Using the <guilabel>Select Talker</guilabel> screen, you may
+override application talker settings. The screen is displayed</para>
+
+<itemizedlist>
+<listitem><para>when you click the <guibutton>Change Talker</guibutton>
+button on the <guilabel>Jobs</guilabel> tab, or</para></listitem>
+<listitem><para>when you click the <guilabel>Talker</guilabel> button
+on the <guilabel>Filter Configuration</guilabel> dialog for
+a Talker Chooser filter, or</para></listitem>
+<listitem><para>when you click the <guilabel>Talker</guilabel> button
+on the <guilabel>Notifications</guilabel> tab.</para></listitem>
+</itemizedlist>
+
+<para>
+ <screenshot>
+ <screeninfo>Select Talker</screeninfo>
+ <mediaobjectco>
+ <imageobjectco>
+ <areaspec units="calspair">
+ <area id="pt-selecttalker-1" coords="1 1"/>
+ <area id="pt-selecttalker-2" coords="1 1"/>
+ <area id="pt-selecttalker-3" coords="1 1"/>
+ <area id="pt-selecttalker-4" coords="1 1"/>
+ <area id="pt-selecttalker-5" coords="1 1"/>
+ </areaspec>
+ <imageobject>
+ <imagedata fileref="selecttalker.png" format="PNG"/>
+ </imageobject>
+ </imageobjectco>
+ <textobject>
+ <phrase>Select Talker</phrase>
+ </textobject>
+ </mediaobjectco>
+ </screenshot>
+</para>
+
+<para>The screen offers three methods to specify desired talker
+attributes:</para>
+
+<itemizedlist>
+<listitem><para>Use the default talker (topmost in the
+<guilabel>Talkers</guilabel> tab). In other words, no talker attributes
+are specified.</para></listitem>
+<listitem><para>Use the closest matching talker having one or more specified attributes.</para></listitem>
+<listitem><para>Use the closest matching talker having all the attributes
+of a configured talker. If you don't delete or modify the talker's settings,
+&ktts; will pick that specific talker. If you delete or modify the
+talker's settings, then &ktts; will pick the closest matching talker
+having the talker's original attributes.</para></listitem>
+</itemizedlist>
+
+<para>
+<calloutlist>
+<callout arearefs="pt-selecttalker-1"><para>Choose the method for entering
+the desired talker attributes by clicking one of these radio buttons.</para></callout>
+<callout arearefs="pt-selecttalker-2"><para>Choose the attributes of the desired
+talker here. Leave an attribute blank if you do not care about that attribute.</para></callout>
+<callout arearefs="pt-selecttalker-3"><para>Check this box if you wish the
+attribute to be "preferred" over other attributes. You may check more than one
+box.</para></callout>
+<callout arearefs="pt-selecttalker-4"><para>Since language is a critical factor
+in making speech understandable, it is always a preferred attribute. It is rare
+that you will use this attribute. The only time you might specify the language
+attribute is when you know a specific application sends text in a language
+different from your desktop.</para></callout>
+<callout arearefs="pt-selecttalker-5"><para>This is a list of the talkers
+you currently have configured in &ktts;. By choosing one of these,
+in effect, you are specifying all the attributes of that talker. If that
+talker is still configured when text is sent, you'll get an exact match and that
+talker will be chosen. However, if you later delete the talker, or modify
+its settings, it might not be the chosen talker anymore. The talker
+most closely matching the original attributes will be chosen.</para></callout>
+</calloutlist>
+</para>
+
+<para>The <guilabel>Language</guilabel> attribute is special because
+text will probably be unintelligible if spoken by a talker that
+speaks a language different from the text. Therefore, language
+is automatically a "preferred" attribute. If you specify a language,
+it will override the chosen language, but if you leave it blank,
+the existing language setting will be used. If the application that sent the
+text to &ktts; did not specify a language, &ktts; assigns
+the language of the topmost talker you have configured in the
+<guilabel>Talkers</guilabel> tab. In other words, the topmost
+talker is assumed to speak the language of your desktop.</para>
+
+<tip><para>To clear all the attributes in the
+<guilabel>Use closest matching Talker having</guilabel> section,
+first click the <guilabel>Use default Talker</guilabel> radio button,
+then click the <guilabel>Use closest matching Talker having</guilabel>
+radio button.</para></tip>
+
+</sect1>
+
+</chapter>
+
+<!-- ====================================================================== -->
+
+<chapter id="commands">
+<title>Command Reference</title>
+
+<!-- (OPTIONAL, BUT RECOMMENDED) This chapter should list all of the
+application windows and their menubar and toolbar commands for easy reference.
+Also include any keys that have a special function but have no equivalent in the
+menus or toolbars. This may not be necessary for small apps or apps with no tool
+or menu bars. -->
+
+<para>TODO</para>
+
+</chapter>
+
+<!--
+
+<sect1 id="kapp-mainwindow">
+<title>The main &ktts; window</title>
+
+<sect2>
+<title>The File Menu</title>
+<para>
+<variablelist>
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;<keycap>N</keycap></keycombo>
+</shortcut>
+<guimenu>File</guimenu>
+<guimenuitem>New</guimenuitem>
+</menuchoice></term>
+<listitem><para><action>Creates a new document</action></para></listitem>
+</varlistentry>
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;<keycap>S</keycap></keycombo>
+</shortcut>
+<guimenu>File</guimenu>
+<guimenuitem>Save</guimenuitem>
+</menuchoice></term>
+<listitem><para><action>Saves the document</action></para></listitem>
+</varlistentry>
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;<keycap>Q</keycap></keycombo>
+</shortcut>
+<guimenu>File</guimenu>
+<guimenuitem>Quit</guimenuitem>
+</menuchoice></term>
+<listitem><para><action>Quits</action> &ktts;</para></listitem>
+</varlistentry>
+</variablelist>
+</para>
+
+</sect2>
+
+-->
+
+<!-- ====================================================================== -->
+
+<chapter id="developers">
+<title>Developer's Guide to &ktts;</title>
+
+<para>&ktts; has two Application Programmer Interfaces (APIs):
+</para>
+
+<itemizedlist>
+<listitem><para>The &kde; Text-to-Speech API, which is used by application
+programmers to give their applications TTS capabilities. Applications
+communicate with KTTSD via &DCOP;.</para></listitem>
+<listitem><para>The KTTSD Plugin API, which is used to add speech
+synthesis plugins to KTTSD so that &ktts; will work with
+a new speech synthesis engine.</para></listitem>
+</itemizedlist>
+
+<para>The following section gives a short description of the &kde; Text-to-Speech API
+&DCOP; Interface.
+Full documentation for both APIs is available online at the
+<ulink url="http://accessibility.kde.org/developer/kttsd/">
+&kde; Accessibility</ulink> web site (http://accessibility.kde.org).
+</para>
+
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="dcop-interface">
+<title>The &ktts; &DCOP; Interface</title>
+
+<para>Applications communicate requests for Text-to-Speech services via the
+&kde; &DCOP; interface to program <command>kttsd</command> object <command>KSpeech</command>.
+</para>
+
+<para>Enter the following commands in a &konsole;.</para>
+
+<para>If KTTSD is not already running</para>
+
+<para><userinput>kttsd</userinput></para>
+
+<para>To queue a text job to be spoken</para>
+
+<para><userinput>dcop kttsd KSpeech setText "<replaceable>text</replaceable>" "<replaceable>talker</replaceable>"</userinput></para>
+
+<para>where <userinput><replaceable>text</replaceable></userinput> is the text to be spoken, and <userinput><replaceable>talker</replaceable></userinput> is a language code
+such as <userinput><replaceable>en</replaceable></userinput>, <userinput><replaceable>cy</replaceable></userinput>, &etc; This command does
+not speak the text; instead it queues a text job for speaking.</para>
+
+<para>Example.</para>
+
+<para><userinput>dcop kttsd KSpeech setText "This is a test." "en"</userinput></para>
+
+<para>To speak the last queued text job</para>
+
+<para><userinput>dcop kttsd KSpeech startText <replaceable>0</replaceable></userinput></para>
+
+<para>In this case, <userinput>0</userinput> refers to the last text job queued.
+You may also specify a specific job number. (If no job number is given, a <userinput>0</userinput> is required.)</para>
+
+<para>To stop the currently speaking text job</para>
+
+<para><userinput>dcop kttsd KSpeech stopText 0</userinput></para>
+
+<para>Depending upon the speech plugin used, speaking may not immediately stop.</para>
+
+<para>There are many more commands that can be sent. To see a list of possible
+commands,</para>
+
+<para><userinput>dcop kttsd KSpeech</userinput></para>
+
+<para>or read the
+<ulink url="http://accessibility.kde.org/developer/kttsd/">
+&kde; Text-to-Speech API</ulink> online.</para>
+
+</sect1>
+
+</chapter>
+
+<!-- ====================================================================== -->
+
+<chapter id="faq">
+<title>Questions and Answers</title>
+
+<!-- (OPTIONAL but recommended) This chapter should include all of the silly
+(and not-so-silly) newbie questions that fill up your mailbox. This chapter
+should be reserved for BRIEF questions and answers! If one question uses more
+than a page or so then it should probably be part of the
+"Using this Application" chapter instead. You should use links to
+cross-reference questions to the parts of your documentation that answer them.
+This is also a great place to provide pointers to other FAQ's if your users
+must do some complicated configuration on other programs in order for your
+application work. -->
+
+&reporting.bugs;
+&updating.documentation;
+
+<qandaset id="faqlist">
+<qandaentry>
+<question>
+<para><command>kttsmgr</command> immediately crashes when I start it. I
+compiled with debug support and I don't even get a backtrace.</para>
+</question>
+<answer>
+<para>GStreamer has crashed taking &ktts; down with it. You most
+likely need to "register" GStreamer. For GStreamer 0.8x, the command is
+<command>gst-register-0.8</command>. If this doesn't solve the problem,
+you may have an incompatible version of GStreamer installed. You could
+try upgrading or uninstalling GStreamer.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>ALSA audio output is not working if I am playing music in another
+application at the same time. When I pause a text job, &ktts;
+freezes. I notice "unable to open PCM" in the &konsole; output.</para>
+</question>
+<answer>
+<para>You have the ALSA device contention problem, which prevents opening
+more than one PCM device at one time. See the ALSA website (dmix) for
+possible solutions. <ulink url="www.alsa-project.org">www.alsa-project.org</ulink>
+</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>I need to start over. How do I get &ktts; completely terminated?</para>
+</question>
+<answer>
+<para>Enter the following commands in a &konsole;:
+<programlisting>
+killall kttsd
+killall kttsmgr
+</programlisting>
+</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>How can I see debugging output from <command>kttsd</command>?</para>
+</question>
+<answer>
+<para>Open two &konsole; windows. First start <command>kttsd</command> in one
+window, then start <command>kttsmgr</command> in the second.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>I have an additional Festival voice I downloaded from the Internet.
+I installed it, and I can use it in Festival, but it does not show up in <command>kttsmgr</command>.</para>
+</question>
+<answer>
+<para>Edit file <command>$KDEHOME/share/apps/kttsd/festivalint/voices</command> to
+add the new voice. The other entries can be used as a guide. If you
+successfully add a voice, please send a patch to the developers along
+with the &URL; from which you obtained the voice file.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>None of the supported speech synthesizers support the language I need.
+Where can I get a synth for my language?</para>
+</question>
+<answer>
+<para>Google(tm) is your friend. This
+<ulink url="http://tcts.fpms.ac.be/synthesis/mbrola/mbrtts.html">link</ulink>
+might also help. If you find a free synthesis engine that supports your
+desired language, and want to add support for it to &ktts;, please
+contact the development team. Open source engines are especially welcome.
+If you know of a commercial synth, perhaps you can pursuade the vendor
+to donate a free copy to the &ktts; development team.
+In the meantime, you may be able to get
+the synth working using the <guilabel>Command</guilabel> plugin.
+See <xref linkend="using-with-command" />.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>&ktts; is speaking too slow. How can I speed it up?</para>
+</question>
+<answer>
+<para>There is a <guilabel>Speed</guilabel> setting on the <guilabel>Audio</guilabel>
+tab. For this to work, you must have the <command>sox</command> utility
+installed and available in the PATH. Some synthesis plugins, such as
+Festival Interactive also provide a <guilabel>Speed</guilabel>
+setting in the talker configuration dialog. Depending upon the
+voice used, it may or may not be enabled.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>OK, that works for some things, but web pages are still spoken too slow.</para>
+</question>
+<answer>
+<para>The speed settings are ignored when &ktts; is speaking
+&HTML;. (This is because the &HTML; is converted into SSML, which has its own
+"rate" tags.) Either disable the &HTML; &XML; Transformer filter
+(see <xref linkend="filters"/>), or if you are brave, edit the .xsl file
+in the &HTML; to SSML Transformer filter and increase the default talking rate.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>I cannot get web pages to speak in a female voice. I have female Festival talker
+configured, but &ktts; always speaks web pages in a male voice.</para>
+</question>
+<answer>
+<para>As of Festival 1.95 beta, the SABLE GENDER tag doesn't seem to be working.
+To keep Festival from producing errors, the SSML to SABLE .xsl file strips the
+gender tags out. The same applies to voice tags as well.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>I have the &HTML; &XML; Transformer filter configured, but web pages are not spoken at
+all using the Festival plugin.</para>
+</question>
+<answer>
+<para>Due to a bug in Festival 1.95 beta, you must install the
+<command>rab_diphone</command> (British male) voice for SABLE to work at all, even
+if you are not using that voice to speak the web pages. Also,
+make sure the <command>xsltproc</command> utility is installed and in the PATH.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>Certain characters or punctuation seem to be producing errors in the synthesizer,
+making it skip entire sentences, or pronounce gibberish. What can I do?</para>
+</question>
+<answer>
+<para>First, make sure the <guilabel>Character encoding</guilabel> option in the
+talker's configuration dialog is properly set for the language. If certain words
+or characters are causing problems, a String Replacer filter might help.
+If certain sentence punctuation characters are confusing the synth, you'll need to
+configure a Sentence Boundary Detector filter. See <xref linkend="filters" />.</para>
+</answer>
+</qandaentry>
+<qandaentry>
+<question>
+<para>I added a String Replacer filter of my own and now &ktts;
+will not allow me to rewind or advance by sentence. On the <guilabel>Jobs</guilabel>
+tab, it claims each job has only one sentence. What did I do wrong?</para>
+</question>
+<answer>
+<para>You must not filter out sentence punctuation characters (period, question mark,
+exclamation mark, colon, and semicolon).
+For these characters, use a Sentence Boundary Detector filter instead.</para>
+</answer>
+</qandaentry>
+</qandaset>
+</chapter>
+
+<!-- ====================================================================== -->
+
+<chapter id="credits">
+
+<!-- Include credits for the programmers, documentation writers, and
+contributors here. The license for your software should then be included below
+the credits with a reference to the appropriate license file included in the KDE
+distribution. -->
+
+<title>Credits and License</title>
+
+<para>
+&ktts;
+</para>
+<para>
+Program Copyright &copy; 2002 Jos&#233; Pablo Ezequiel "Pupeno" Fern&#225;ndez <email>pupeno@kde.org</email>
+</para>
+<para>
+Current Maintainer: Gary Cramblitt <email>garycramblitt@comcast.net</email>
+</para>
+<para>
+Contributors:
+<itemizedlist>
+<listitem><para>Olaf Schmidt <email>ojschmidt@kde.org</email></para>
+</listitem>
+<listitem><para>Gunnar Schmi Dt <email>gunnar@schmi-dt.de</email></para>
+</listitem>
+<listitem><para>Paul Giannaros <email>ceruleanblaze@gmail.com</email></para>
+</listitem>
+</itemizedlist>
+</para>
+
+<para>
+Documentation Copyright &copy; 2004 Gary R. Cramblitt <email>garycramblitt@comcast.net</email>
+</para>
+
+<!-- TRANS:CREDIT_FOR_TRANSLATORS -->
+
+&underFDL; <!-- FDL: do not remove -->
+
+<!-- Determine which license your application is licensed under,
+ and delete all the remaining licenses below:
+
+ (NOTE: All documentation are licensed under the FDL,
+ regardless of what license the application uses) -->
+
+&underGPL; <!-- GPL License -->
+
+<note><para>Speech synthesis engines used by &ktts; have their own
+licenses. See each engine's documentation or website for details.
+Some voices also have their own licensing.</para></note>
+
+</chapter>
+
+<!-- ====================================================================== -->
+
+<appendix id="installation">
+<title>Installation</title>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="getting-kapp">
+<title>How to obtain &ktts;</title>
+
+<!-- This first entity contains boiler plate for applications that are
+part of KDE CVS. You should remove it if you are releasing your
+application -->
+
+<para>
+&install.intro.documentation;
+</para>
+
+<para>(FUTURE) Debian Install Command: <command>apt-get install kdeaccessibility</command></para>
+
+<note>
+<para>You will find links to source and binary packages
+on the <ulink url="http://accessibility.kde.org/developer/kttsd/">
+&kde; Accessibility</ulink> web site (http://accessibility.kde.org).</para>
+
+<para>If you have access to the &kde; code repository, you can download &ktts;
+by checking out the <command>kdeaccessibility</command> module. &ktts;
+will be found in the <command>kttsd</command> folder. You can also
+download tarballs of the kdeaccessibility source code from
+<ulink url="ftp://ftp.kde.org/pub/kde/">
+ftp://ftp.kde.org/pub/kde/</ulink></para>
+</note>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="requirements">
+<title>Requirements</title>
+
+<para>Mandatory requirements:</para>
+
+<para>
+<itemizedlist>
+<listitem><para>&kde; version 3.2 or later.</para></listitem>
+<listitem><para>A speech synthesis engine. The following engines
+and spoken languages are currently supported.</para>
+
+<para>
+<informaltable id="synth-engines">
+<tgroup cols="2">
+<tbody>
+
+<row>
+<entry>Festival</entry>
+<entry>American English, British, Spanish, German, Finnish, Czech, Polish, Russian,
+Italian, French Canadian, Kiswahili, Zulu, and Ibibio</entry>
+</row>
+
+<row>
+<entry>Festival Lite (flite)</entry>
+<entry>English</entry>
+</row>
+
+<row>
+<entry>Hadifix (&mbrola; and txt2pho)</entry>
+<entry>German, Hungarian</entry>
+</row>
+
+<row>
+<entry>Epos</entry>
+<entry>Czech, Slovak</entry>
+</row>
+
+<row>
+<entry>FreeTTS</entry>
+<entry>English</entry>
+</row>
+
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+<para>It also works with any synthesis engine that can be run from a command in
+a &konsole;.</para>
+
+<note><para>
+The languages listed above may not be comprehensive or up-to-date.
+Check the specifications for each engine for a complete list of supported
+languages. Also check the
+<ulink url="http://accessibility.kde.org/developer/kttsd/index.php">
+&ktts;</ulink> website for additional
+information that might not have made it into this handbook.
+</para></note>
+
+<note>
+<para>&ktts; uses a flexible plugin architecture for
+speech synthesis engines. If you
+want to enhance &ktts; to support another engine, contact the
+development team.
+</para>
+</note>
+
+<para>
+See <xref linkend="configuration" /> for specific instructions for each
+of these engines.
+</para>
+
+</listitem>
+
+<listitem>
+<para>At least one of the following audio subsystems:
+
+<itemizedlist>
+<listitem><para>&kde; &arts; Soundsystem. &arts; is usually installed with &kde;.</para></listitem>
+<listitem><para>ALSA (Advanced &Linux; Sound Architecture). ALSA is installed with
+most &Linux; systems. (<ulink url="www.alsa-project.org">www.alsa-project.org</ulink>)</para></listitem>
+<listitem><para>GStreamer version 0.8.7 or greater. <emphasis>Note</emphasis>:
+Be sure to register your GStreamer plugins by running the <command>gst-register</command>
+command prior to using GStreamer in &ktts;.
+(<ulink url="http://gstreamer.freedesktop.org">
+http://gstreamer.freedesktop.org</ulink>)</para></listitem>
+<listitem><para>aKode library. aKode is a decoder library that is part of &kde;.
+</para></listitem>
+</itemizedlist>
+
+<note><para>The &kde; project plans to drop &arts; starting in version 4.</para></note>
+
+<note><para>Some users experience device contention with ALSA. If your system
+has this problem, you will not be able to simultaneously play music while speaking.
+&ktts; will also freeze if you pause a text job and then
+start another. See the ALSA website (dmix) for possible solutions.</para></note>
+
+<note><para>As of July 2005, aKode does not support a true pause capability.
+When you pause a text job in &ktts; it will finish speaking the
+current sentence.</para></note>
+
+</para>
+</listitem>
+
+</itemizedlist>
+</para>
+
+<para>Optional components:</para>
+
+<para>
+<itemizedlist>
+
+<listitem>
+<para>The <command>sox</command> audio utility is needed for
+adjusting overall speech speed, but not required. Debian users can install
+sox with the command <command>apt-get install sox</command>.
+Sox is included on most &Linux; distribution CDs.</para>
+</listitem>
+
+<listitem>
+<para>The <command>xsltproc</command> utility is needed for
+SSML support and for the &XML; Transformer filter, but not required. Debian users can install
+xsltproc with the command <command>apt-get install xsltproc</command>.</para>
+</listitem>
+
+</itemizedlist>
+</para>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="compilation">
+<title>Compilation and Installation</title>
+
+<!-- This entity contains the boilerplate text for standard -->
+<!-- compilation instructions. If your application requires any -->
+<!-- special handling, remove it, and replace with your own text. -->
+
+<!-- &install.compile.documentation; -->
+
+<para>In order to compile &ktts;, you must have a
+recent (&kde; 3.4 or greater) copy of the &kde; development files,
+including kdelibs and arts.</para>
+
+<para>If you downloaded &ktts; as a tarball, log in
+as a normal user and untar the tarball to a suitable folder,
+change to that folder, and enter the following commands.</para>
+
+<programlisting>
+./configure
+make
+</programlisting>
+
+<para>The following <command>configure</command> options are available:</para>
+
+<para>
+<informaltable id="configure-audio-options">
+<tgroup cols="3">
+<tbody>
+
+<row>
+<entry><emphasis>Default Option</emphasis></entry>
+<entry><emphasis>Description</emphasis></entry>
+<entry><emphasis>Alternate</emphasis></entry>
+</row>
+<row>
+<entry>--with-arts</entry>
+<entry>Builds the arts audio plugin.</entry>
+<entry>--without-arts</entry>
+</row>
+<row>
+<entry>--with-alsa=check</entry>
+<entry>Builds the ALSA audio plugin.</entry>
+<entry>--with-alsa=no</entry>
+</row>
+<row>
+<entry>--with-gstreamer=no</entry>
+<entry>Does not build the GStreamer audio plugin.</entry>
+<entry>--with-gstreamer=check</entry>
+</row>
+<row>
+<entry>--with-akode=no</entry>
+<entry>Does not build the aKode audio plugin.</entry>
+<entry>--with-akode=check</entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+<note><para>
+In &kde; 4, the &arts; plugin will likely be removed or at least not built by default.
+</para></note>
+
+<para>The following speech synthesizer plugins are all built by default.
+Some of them are runtime only dependent upon non-free software.
+(Non-free according to Debian Policy). The "Configure Option to
+not build" column shows the configure command to not build the plugin:</para>
+
+<para>
+<informaltable id="configure-synth-options">
+<tgroup cols="3">
+<tbody>
+
+<row>
+<entry><emphasis>Synth</emphasis></entry>
+<entry><emphasis>License</emphasis></entry>
+<entry><emphasis>Configure Option to not build</emphasis></entry>
+</row>
+<row><entry>Festival</entry><entry>free</entry><entry>--disable-kttsd-festivalint</entry></row>
+<row><entry>Festival Lite</entry><entry>free</entry><entry>--disable-kttsd-flite</entry></row>
+<row><entry>Epos</entry><entry>free</entry><entry>--disable-kttsd-epos</entry></row>
+<row><entry>Command</entry><entry>free</entry><entry>--disable-kttsd-command</entry></row>
+<row><entry>Hadifix</entry><entry>non-free</entry><entry>--disable-kttsd-hadifix</entry></row>
+<row><entry>FreeTTS</entry><entry>non-free</entry><entry>--disable-kttsd-freetts</entry></row>
+</tbody></tgroup></informaltable></para>
+
+<para>By default, the commands above will install &ktts; to
+<filename>/opt/kde3</filename>. If this folder is not in your
+$<envar>KDEDIRS</envar> path, you may need to add a
+<userinput>--prefix=<replaceable>target</replaceable></userinput> option.
+For example,</para>
+
+<programlisting>
+./configure --prefix=/usr/local
+make
+</programlisting>
+
+<note><para>On Debian systems, <filename><replaceable>/usr/local</replaceable></filename>
+is the usual place to install applications compiled from source code.
+</para></note>
+
+<para>Login as root and install the compiled &ktts;
+using the following commands.</para>
+
+<programlisting>
+su
+make install
+</programlisting>
+
+<para>If you downloaded the &ktts; source from the
+<filename>kdeaccessibility</filename> code repository module, or downloaded the nightly
+tarball, use the following commands to compile and install.
+</para>
+
+<programlisting>
+cd kdeaccessibility
+echo kttsd>inst-apps
+make -f Makefile.cvs
+./configure
+cd kttsd
+make
+su
+make install
+</programlisting>
+
+</sect1>
+
+<!-- ...................................................................... -->
+
+
+<sect1 id="configuration">
+<title>Configuration</title>
+
+<para>Make sure your speech synthesis engine is working before using
+&ktts;. Follow the instructions that came with the engine.</para>
+
+<tip>
+<para>In some cases, you may need to grant write access to the audio device.</para>
+<para><userinput>chmod a+rw <replaceable>/dev/dsp*</replaceable></userinput></para>
+</tip>
+
+<!-- ...................................................................... -->
+
+
+<sect2 id="using-with-festival">
+<title>Using with Festival (Interactive)</title>
+
+<para>Festival is one of the best free and open source TTS
+engines available. Voice quality is generally good and there are quite
+a few languages and voices supported.
+For many voices, you can control the volume,
+speed of the generated speech, and pitch (tone) from &ktts;.</para>
+
+<para>Synthesizer Name: <guilabel>Festival Interactive</guilabel></para>
+
+<para>&URL;: <ulink url="http://www.cstr.ed.ac.uk/projects/festival/">
+http://www.cstr.ed.ac.uk/projects/festival/</ulink>
+</para>
+
+<para>Debian Install Command: <userinput>apt-get install festival</userinput></para>
+
+<para>
+You will need to install at least one language. Follow the instructions
+that come with Festival. If you will be speaking web pages,
+you must install the <command>rab_diphone</command> (British Male)
+voice.
+</para>
+
+<para>Additional English festival voices are available from</para>
+
+<para><ulink url="http://hts.ics.nitech.ac.jp/">http://hts.ics.nitech.ac.jp/</ulink>.
+</para>
+
+<para>Additional Spanish, English, and German voices are available from</para>
+
+<para><ulink url="http://cslu.cse.ogi.edu/tts/download/">
+http://cslu.cse.ogi.edu/tts/download/</ulink></para>
+
+<para>You must compile an additional module
+for these voices, therefore, you must have the Festival source code.
+The German voices have limited distribution.
+</para>
+
+<para>A Finnish male voice is available from </para>
+
+<para><ulink url="http://www.ling.helsinki.fi/suopuhe/download/">
+http://www.ling.helsinki.fi/suopuhe/download/</ulink>.
+</para>
+
+<para>A Polish male voice is available from </para>
+
+<para><ulink url="http://www.artegence.com/download/voicexml/speech/festival_polish_voice.tgz">
+http://www.artegence.com/download/voicexml/speech/festival_polish_voice.tgz</ulink>.
+</para>
+
+<para>A Russian male voice is available from </para>
+
+<para><ulink url="http://nshmyrev.narod.ru/festival/festival.html">
+http://nshmyrev.narod.ru/festival/festival.html
+</ulink></para>
+
+<para>You must have Festival 1.95 beta or later to use this voice. The voice
+is still in early development. Untar to
+<filename>festival/lib/voices/russian/</filename>. When you configure the Russian
+talker, the voice code is <userinput>msu_ru_nsh_diphone</userinput>. Be sure to
+select an 8-bit cryllic encoding, such as <userinput>KOI8-R</userinput>.</para>
+
+<para>Italian voices for Festival 1.95 beta are available at</para>
+
+<para><ulink url="http://www.csrf.pd.cnr.it/TTS/It-FESTIVAL-download.htm">
+http://www.csrf.pd.cnr.it/TTS/It-FESTIVAL-download.htm</ulink>.</para>
+
+<para>If you get CRC errors when you unzip, try downloading again.</para>
+
+<para>Kiswahili, Zulu, and Ibibio voices for Festival 1.95 beta are available at</para>
+
+<para><ulink url="http://www.llsti.org/">http://www.llsti.org/</ulink>.</para>
+
+<para>Unfortunately, the Hindi voice also available there will not work with
+&ktts;.</para>
+
+<para>Commercial voices, including a French Canadian voice,
+can be purchased from Cepstral, LLC at</para>
+
+<para><ulink url="http://www.cepstral.com/">http://www.cepstral.com/</ulink></para>
+
+<para>The FAQ on their Support page has information about using their voices
+in Festival.</para>
+
+<para>Festival is typically included with &Linux; distributions. Check your
+distro CDs to see if it is included.</para>
+
+<note>
+<para>When using the Polish, Hungarian, or Czech languages, be sure the <guilabel>Encoding</guilabel>
+option is set to <userinput>ISO 8859-2</userinput>.
+</para>
+<para>When using the Russian voice, be sure the <guilabel>Encoding</guilabel>
+option is set to an 8-bit cryllic encoding, such as <userinput>KOI8-R</userinput>.
+</para>
+</note>
+
+<!-- ...................................................................... -->
+
+
+<sect3 id="festival-with-mbrola">
+<title>Using Festival with &mbrola;</title>
+
+<para>Festival can be used in combination with the &mbrola; synthesizer.
+In this mode, Festival does the lexical analysis and &mbrola; produces the
+audio. The &mbrola; binary and &mbrola; voice files can be downloaded from</para>
+
+<para><ulink url="http://festvox.org/mbrola/">http://festvox.org/mbrola/</ulink>.</para>
+
+<para>Follow the instructions in the <filename>readme.txt</filename> that comes with
+the download.</para>
+
+<para>Note that &mbrola; is not a complete Text-to-Speech system. &mbrola; synthesizes
+speech from diphone files. You must have additional software that can produce
+the diphones. When combined with Festival, Festival produces the diphones needed
+by &mbrola;. <command>txt2pho</command> can also be used to produce diphones
+from German text. See <xref linkend="using-with-hadifix"/> for more information.</para>
+
+<para>There are three methods of combining Festival with &mbrola;.</para>
+
+<para>
+<itemizedlist>
+<listitem><para><link linkend="mbrola-wrappers">&mbrola; Wrappers</link>.
+At the time of writing this Handbook,
+this method is limited to English voices.</para></listitem>
+<listitem><para><link linkend="ims-german-festival">IMS German Festival</link>.</para></listitem>
+<listitem><para><link linkend="festival-czech">Festival-Czech</link>.</para></listitem>
+</itemizedlist>
+</para>
+
+<!-- ...................................................................... -->
+
+<sect4 id="mbrola-wrappers">
+<title>Using Festival with &mbrola; Wrappers</title>
+
+<para>In this method, additional
+wrapper code is added to Festival to enable speech synthesis using
+&mbrola; voice files. Note that the &mbrola; voice files are <emphasis>not</emphasis>
+installed in the &mbrola; folder tree. Instead, they are installed
+in the <filename>festival/lib/</filename> folder tree. For instructions, see</para>
+
+<para><ulink url="http://www.cstr.ed.ac.uk/projects/festival/mbrola.html">
+http://www.cstr.ed.ac.uk/projects/festival/mbrola.html</ulink></para>
+
+</sect4>
+
+<!-- ...................................................................... -->
+
+<sect4 id="ims-german-festival">
+<title>Using IMS German Festival</title>
+
+<para>IMS German Festival is a modified version of Festival that uses German &mbrola;
+voices. It works with either Festival version 1.4.1 or Festival 2.0 (1.95beta).
+First install Festival and &mbrola;, if you have not already done so.
+Next, download IMS German Festival, from</para>
+
+<para>
+<ulink url="http://www.ims.uni-stuttgart.de/phonetik/synthesis/festival_opensource.html">
+http://www.ims.uni-stuttgart.de/phonetik/synthesis/festival_opensource.html</ulink>.</para>
+
+<para>Follow the instructions in the <filename>README</filename> that comes with the
+download. (Note, if using in combination with Festival 2.0, it is <emphasis>not</emphasis>
+necessary to apply the <filename>fixes</filename> tarball, but you must still
+rebuild festival.) Finally, add the following
+lines to the <filename>festival/lib/siteinit.scm</filename> file.</para>
+
+<para>
+<programlisting>
+(voice-location "german_de1_os" "/usr/local/mbrola/de1"
+ "German Female, IMS Festival de1")
+(voice-location "german_de2_os" "/usr/local/mbrola/de2"
+ "German Male, IMS Festival de2")
+(voice-location "german_de3_os" "/usr/local/mbrola/de3"
+ "German Female, IMS Festival de3")
+</programlisting>
+</para>
+
+<para>just above the line that reads</para>
+
+<para>
+<programlisting>
+(provide 'siteinit)
+</programlisting>
+</para>
+
+<para>On some systems, the file you edit is <filename>/etc/festival.scm</filename>.
+Only add the lines that correspond to the German voices you have installed.
+Substitute the correct path for
+<userinput><replaceable>/usr/local/mbrola/</replaceable></userinput>.
+Also note that (at the time of this writing)
+IMS German Festival does not work with the de4, de5, or de6 German voices.</para>
+
+</sect4>
+
+<!-- ...................................................................... -->
+
+<sect4 id="festival-czech">
+<title>Using Festival-Czech</title>
+
+<para>This method uses some special code to enable speech synthesis
+using Festival with an &mbrola; Czech voice. To install, first download and
+install Festival and &mbrola;, and make sure both are working. Next, download
+Festival-Czech from</para>
+
+<para><ulink url="http://www.freebsoft.org/festival-czech">
+http://www.freebsoft.org/festival-czech</ulink></para>
+
+<note><para>In the following procedures substitute the correct folder
+paths as needed.</para></note>
+
+<para>Untar the download to a suitable folder and make
+the lexicon. The Festival executable must be in your <envar>PATH</envar>.
+</para>
+
+<para>
+<programlisting>
+cd /usr/local
+tar xvfz festival-czech.tar.gz
+cd festival-czech
+make
+</programlisting>
+</para>
+
+<para>Download the <filename>cz2</filename> voice file from the &mbrola;
+website, and unzip it in the &mbrola; folder.</para>
+
+<para>
+<programlisting>
+cd /usr/local/mbrola
+mkdir cz2
+cd cz2
+unzip cz2-001009.zip
+</programlisting>
+</para>
+
+<para>Add the following lines to the <filename>festival/lib/siteinit.scm</filename> file.</para>
+
+<para>
+<programlisting>
+(set! czech-lexicon-file "/usr/local/festival-czech/czech-lexicon.out")
+(set! load-path (cons "/usr/local/festival-czech" load-path))
+(require 'czech)
+(set! czech-mbrola_database "/usr/local/mbrola/cz2/cz2")
+(set! mbrola_progname "/usr/local/mbrola/mbrola")
+(voice-location "czech_mbrola_cz2" "/usr/local/mbrola/cz2"
+ "Czech Male, MBROLA")
+(require 'czech-mbrola)
+</programlisting>
+</para>
+
+<para>just above the line that reads</para>
+
+<para>
+<programlisting>
+(provide 'siteinit)
+</programlisting>
+</para>
+
+<para>On some systems, the file you edit is <filename>/etc/festival.scm</filename>.</para>
+
+</sect4>
+
+</sect3>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+<sect2 id="using-with-flite">
+<title>Using with Festival Lite (flite)</title>
+
+<para>Festival Lite is a free open source engine that currently supports
+a limited number of voices and languages. It is light weight, but
+sacrifices voice quality somewhat.
+You cannot control the pitch, volume, or speed of this engine
+from &ktts;.</para>
+
+<para>Synthesizer Name: <guilabel>Festival Lite (flite)</guilabel></para>
+
+<para>&URL;: <ulink url="http://www.speech.cs.cmu.edu/flite/index.html">
+http://www.speech.cs.cmu.edu/flite/index.html</ulink>
+</para>
+
+<para>Debian Install Command: <userinput>apt-get install flite</userinput></para>
+
+<para>flite is typically included with &Linux; distributions. Check your
+distro CDs to see if it is included.</para>
+
+<para>Build and install flite following the instructions in the
+<filename>README</filename> that comes with it.</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+
+<sect2 id="using-with-hadifix">
+<title>Using with Hadifix (&mbrola; and txt2pho)</title>
+
+<para>Hadifix is a two-stage synthesis engine based on diphones.
+The <command>txt2pho</command> utility converts text into diphones
+and the &mbrola; engine synthesizes the diphones to sound.
+Voice quality is good, but language support is currently somewhat limited.
+You can control the voice, pitch, speed, and volume from <application>kttsmgr</application>.
+</para>
+
+<para>Synthesizer Name: <guilabel>Hadifix</guilabel></para>
+
+<para>&URL;: see below</para>
+
+<para>Debian Install Command: none</para>
+
+<para>If you do not already have Hadifix installed, do this:</para>
+
+<procedure>
+<step><para>Download &mbrola; binary from
+<ulink url="http://festvox.org/mbrola/">http://festvox.org/mbrola/</ulink>.</para></step>
+<step><para>Install &mbrola; to <filename>/usr/local/mbrola</filename> folder.</para></step>
+<step><para>Download at least one german language file from the &mbrola; site.
+Unzip to the <filename>/usr/local/mbrola</filename> folder.</para></step>
+<step><para>Download txt2pho from</para>
+<para>
+<ulink url="http://www.ikp.uni-bonn.de/dt/forsch/phonetik/hadifix/HADIFIXforMBROLA.html">
+http://www.ikp.uni-bonn.de/dt/forsch/phonetik/hadifix/HADIFIXforMBROLA.html</ulink>.</para>
+</step>
+<step><para>Unzip txt2pho to <filename>/usr/local/txt2pho</filename>.</para></step>
+<step><para>Edit <command>txt2phorc</command> file, putting correct data paths in.</para></step>
+<step><para>Either copy <command>txt2phorc</command> to <filename>~/.txt2phorc</filename> or to <filename>/etc/txt2pho</filename>.
+Note that you drop the "rc" in file name.</para></step>
+<step><para>In <application>kttsmgr</application>, choose the German language
+(<guilabel>de</guilabel>), and add <guilabel>Hadifix</guilabel>.</para></step>
+<step><para>On the <guilabel>Configure Talker</guilabel> screen,
+configure a voice and the paths to &mbrola; and txt2pho.</para></step>
+<step><para>Click the <guibutton>Test</guibutton> button to test.</para></step>
+</procedure>
+
+<para>A Hungarian implementation for &mbrola; and txt2pho is available at</para>
+
+<para>
+<ulink url="http://tkltrans.sourceforge.net/">http://tkltrans.sourceforge.net/</ulink>.
+</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+
+<sect2 id="using-with-epos">
+ <title>Using with Epos</title>
+
+<para>Epos is a free Czeck and Slovak open source engine.
+It is light weight, but sacrifices voice quality somewhat.
+You cannot control the volume of this engine
+from &ktts;.</para>
+
+<para>Synthesizer Name: <guilabel>Epos TTS Synthesis System</guilabel></para>
+
+<para>&URL;: <ulink url="http://epos.ure.cas.cz/">
+http://epos.ure.cas.cz/</ulink>
+</para>
+
+<para>Debian Install Command: <userinput>apt-get install epos</userinput></para>
+
+<para>Start <application>kttsmgr</application>. On the <guilabel>Talkers</guilabel> tab,
+click the <guibutton>Add</guibutton> button. Choose Czeck or Slovak
+language and <guilabel>Epos TTS Synthesis System</guilabel>.
+If the epos server executable and client are not
+in your <envar>PATH</envar>, specify the paths to these executables
+in the <guilabel>Configure Talker</guilabel> screen. The options boxes
+permit you to pass additional options to the server and client. In a
+&konsole;, type <userinput>epos -h</userinput>
+or <userinput>say -h</userinput> for information.</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+
+<sect2 id="using-with-freetts">
+ <title>Using with FreeTTS</title>
+
+<para>FreeTTS is a free open source speech engine written in &Java;, which means
+that you must have the &Java; Virtual Machine software installed on your
+system to use it. It currently has limited voice and language support.
+You cannot control the pitch, volume, or speed of this engine
+from &ktts;.</para>
+
+<para>Synthesizer Name: <guilabel>FreeTTS</guilabel></para>
+
+<para>&URL;: <ulink url="http://sourceforge.net/projects/freetts/">
+http://sourceforge.net/projects/freetts/</ulink>
+</para>
+
+<para>Debian Install Command: none</para>
+
+</sect2>
+
+<!-- ...................................................................... -->
+
+
+<sect2 id="using-with-command">
+ <title>Using the Command Plugin</title>
+
+<para>The command plugin permits you to use &ktts; with any
+speech synthesis engine that can be run as a command in a
+&konsole;.</para>
+
+<para>Synthesizer Name: <guilabel>Command</guilabel></para>
+
+<para>&URL;: none</para>
+
+<para>Debian Install Command: none</para>
+
+<para>Ideally, you should use a command that synthesizes to a temporary audio
+(wav) file, rather than send the speech directly to the audio device.</para>
+
+<para>If the speech synthesis engine requires text to be encoded
+differently from your desktop encoding setting, you must use the
+<command>%f</command> parameter to pass the text to the engine.
+&ktts; will encode the text in the setting you specify when
+it writes the text to the temporary file. If you attempt to pass text
+on the command line using the <command>%t</command> parameter,
+it will be encoded using your desktop locale setting.
+You can also use the <guilabel>Send the data as standard input</guilabel>
+option to solve this problem, if the engine accepts input from StdIn.
+For example, here is a sample command to send polish text to Festival using
+ISO 8859-2 encoding and removing unspeakable punctuation characters.</para>
+
+<para><command>cat %f | tr '(){}[]"' ' ' | festival --tts --language polish</command>
+</para>
+
+</sect2>
+
+<!-- ====================================================================== -->
+
+</sect1>
+
+</appendix>
+
+&documentation.index;
+</book>
+
+<!--
+Local Variables:
+mode: xml
+sgml-minimize-attributes:nil
+sgml-general-insert-case:lower
+sgml-indent-step:0
+sgml-indent-data:nil
+End:
+
+vim:tabstop=2:shiftwidth=2:expandtab
+-->
diff --git a/doc/kttsd/interruption.png b/doc/kttsd/interruption.png
new file mode 100644
index 0000000..9c56e34
--- /dev/null
+++ b/doc/kttsd/interruption.png
Binary files differ
diff --git a/doc/kttsd/jobs.png b/doc/kttsd/jobs.png
new file mode 100644
index 0000000..2873d0c
--- /dev/null
+++ b/doc/kttsd/jobs.png
Binary files differ
diff --git a/doc/kttsd/notifications.png b/doc/kttsd/notifications.png
new file mode 100644
index 0000000..9a6bf8c
--- /dev/null
+++ b/doc/kttsd/notifications.png
Binary files differ
diff --git a/doc/kttsd/selecttalker.png b/doc/kttsd/selecttalker.png
new file mode 100644
index 0000000..1c56d38
--- /dev/null
+++ b/doc/kttsd/selecttalker.png
Binary files differ
diff --git a/doc/kttsd/stringreplacer.png b/doc/kttsd/stringreplacer.png
new file mode 100644
index 0000000..ade5cd3
--- /dev/null
+++ b/doc/kttsd/stringreplacer.png
Binary files differ
diff --git a/doc/kttsd/talkerchooser.png b/doc/kttsd/talkerchooser.png
new file mode 100644
index 0000000..0188033
--- /dev/null
+++ b/doc/kttsd/talkerchooser.png
Binary files differ
diff --git a/doc/kttsd/talkers.png b/doc/kttsd/talkers.png
new file mode 100644
index 0000000..6ae5469
--- /dev/null
+++ b/doc/kttsd/talkers.png
Binary files differ
diff --git a/doc/kttsd/xmltransformer.png b/doc/kttsd/xmltransformer.png
new file mode 100644
index 0000000..31cd65f
--- /dev/null
+++ b/doc/kttsd/xmltransformer.png
Binary files differ
diff --git a/kbstateapplet/Makefile.am b/kbstateapplet/Makefile.am
new file mode 100644
index 0000000..23466d9
--- /dev/null
+++ b/kbstateapplet/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES = $(all_includes)
+
+kde_module_LTLIBRARIES = kbstate_panelapplet.la
+
+kbstate_panelapplet_la_SOURCES = kbstate.cpp
+
+METASOURCES = AUTO
+noinst_HEADERS = kbstate.h kdeexportfix.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = kbstateapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+kbstate_panelapplet_la_LDFLAGS = $(KDE_PLUGIN) -module $(all_libraries)
+kbstate_panelapplet_la_LIBADD = $(LIB_KDEUI)
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kbstateapplet.pot
+
+srcdoc:
+ kdoc -a -p -H -d $$HOME/web/src/kbstateapplet kbstateapplet *.h -lqt -lkdecore -lkdeui -lkfile
+
+SUBDIRS = images
diff --git a/kbstateapplet/configure.in.in b/kbstateapplet/configure.in.in
new file mode 100644
index 0000000..3989388
--- /dev/null
+++ b/kbstateapplet/configure.in.in
@@ -0,0 +1,23 @@
+# add this here so the test programs below compile
+KDE_CHECK_HEADER(X11/Xlib.h)
+KDE_CHECK_HEADER(X11/extensions/XKBstr.h, ,
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kbstateapplet",
+[
+#include <X11/Xlib.h>
+])
+
+dnl Solaris lacks this file, so we should skip kbstateapplet here
+KDE_CHECK_HEADER(X11/XKBlib.h, ,
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kbstateapplet",
+[
+#include <X11/Xlib.h>
+])
+
+dnl Solaris lacks this file, so we should skip kbstateapplet here
+KDE_CHECK_HEADER(X11/extensions/XKB.h, ,
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kbstateapplet",
+[
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+])
diff --git a/kbstateapplet/images/Makefile.am b/kbstateapplet/images/Makefile.am
new file mode 100644
index 0000000..b8ded81
--- /dev/null
+++ b/kbstateapplet/images/Makefile.am
@@ -0,0 +1,2 @@
+kbstateiconsdir = $(kde_datadir)/kbstateapplet/icons
+kbstateicons_ICON = AUTO \ No newline at end of file
diff --git a/kbstateapplet/images/cr16-action-altkey.png b/kbstateapplet/images/cr16-action-altkey.png
new file mode 100644
index 0000000..e049c31
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-altkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-capskey.png b/kbstateapplet/images/cr16-action-capskey.png
new file mode 100644
index 0000000..fb98d7b
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-capskey.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-controlkey.png b/kbstateapplet/images/cr16-action-controlkey.png
new file mode 100644
index 0000000..3593fdd
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-controlkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-hyperkey.png b/kbstateapplet/images/cr16-action-hyperkey.png
new file mode 100644
index 0000000..da3fc29
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-hyperkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_mouse.png b/kbstateapplet/images/cr16-action-kbstate_mouse.png
new file mode 100644
index 0000000..a1121c5
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_mouse.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_mouse_left.png b/kbstateapplet/images/cr16-action-kbstate_mouse_left.png
new file mode 100644
index 0000000..59bf8fb
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_mouse_left.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_mouse_left_selected.png b/kbstateapplet/images/cr16-action-kbstate_mouse_left_selected.png
new file mode 100644
index 0000000..40e28d8
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_mouse_left_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_mouse_mid.png b/kbstateapplet/images/cr16-action-kbstate_mouse_mid.png
new file mode 100644
index 0000000..c5b9141
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_mouse_mid.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_mouse_mid_selected.png b/kbstateapplet/images/cr16-action-kbstate_mouse_mid_selected.png
new file mode 100644
index 0000000..8e7e570
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_mouse_mid_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_mouse_right.png b/kbstateapplet/images/cr16-action-kbstate_mouse_right.png
new file mode 100644
index 0000000..673495b
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_mouse_right.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_mouse_right_selected.png b/kbstateapplet/images/cr16-action-kbstate_mouse_right_selected.png
new file mode 100644
index 0000000..fb35c27
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_mouse_right_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_slowkeys.png b/kbstateapplet/images/cr16-action-kbstate_slowkeys.png
new file mode 100644
index 0000000..ebda302
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_slowkeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-kbstate_stickykeys.png b/kbstateapplet/images/cr16-action-kbstate_stickykeys.png
new file mode 100644
index 0000000..744802d
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-kbstate_stickykeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-key.png b/kbstateapplet/images/cr16-action-key.png
new file mode 100644
index 0000000..55b8c22
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-key.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-keypressno.png b/kbstateapplet/images/cr16-action-keypressno.png
new file mode 100644
index 0000000..ed3b5a5
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-keypressno.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-keypressok.png b/kbstateapplet/images/cr16-action-keypressok.png
new file mode 100644
index 0000000..040bae2
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-keypressok.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-lockkey.png b/kbstateapplet/images/cr16-action-lockkey.png
new file mode 100644
index 0000000..f5920e1
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-lockkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-metakey.png b/kbstateapplet/images/cr16-action-metakey.png
new file mode 100644
index 0000000..9537dcd
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-metakey.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-shiftkey.png b/kbstateapplet/images/cr16-action-shiftkey.png
new file mode 100644
index 0000000..f329803
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-shiftkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-superkey.png b/kbstateapplet/images/cr16-action-superkey.png
new file mode 100644
index 0000000..69b5495
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-superkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr16-action-unlatched.png b/kbstateapplet/images/cr16-action-unlatched.png
new file mode 100644
index 0000000..55b8c22
--- /dev/null
+++ b/kbstateapplet/images/cr16-action-unlatched.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-altkey.png b/kbstateapplet/images/cr22-action-altkey.png
new file mode 100644
index 0000000..12a2ffd
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-altkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-capskey.png b/kbstateapplet/images/cr22-action-capskey.png
new file mode 100644
index 0000000..4a89ba2
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-capskey.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-controlkey.png b/kbstateapplet/images/cr22-action-controlkey.png
new file mode 100644
index 0000000..3072dac
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-controlkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-hyperkey.png b/kbstateapplet/images/cr22-action-hyperkey.png
new file mode 100644
index 0000000..84653a1
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-hyperkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_mouse.png b/kbstateapplet/images/cr22-action-kbstate_mouse.png
new file mode 100644
index 0000000..fa62c4a
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_mouse.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_mouse_left.png b/kbstateapplet/images/cr22-action-kbstate_mouse_left.png
new file mode 100644
index 0000000..8068f76
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_mouse_left.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_mouse_left_selected.png b/kbstateapplet/images/cr22-action-kbstate_mouse_left_selected.png
new file mode 100644
index 0000000..d305816
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_mouse_left_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_mouse_mid.png b/kbstateapplet/images/cr22-action-kbstate_mouse_mid.png
new file mode 100644
index 0000000..7cc9365
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_mouse_mid.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_mouse_mid_selected.png b/kbstateapplet/images/cr22-action-kbstate_mouse_mid_selected.png
new file mode 100644
index 0000000..ca10e56
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_mouse_mid_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_mouse_right.png b/kbstateapplet/images/cr22-action-kbstate_mouse_right.png
new file mode 100644
index 0000000..3c8b806
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_mouse_right.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_mouse_right_selected.png b/kbstateapplet/images/cr22-action-kbstate_mouse_right_selected.png
new file mode 100644
index 0000000..eeedcfe
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_mouse_right_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_slowkeys.png b/kbstateapplet/images/cr22-action-kbstate_slowkeys.png
new file mode 100644
index 0000000..6f3c784
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_slowkeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-kbstate_stickykeys.png b/kbstateapplet/images/cr22-action-kbstate_stickykeys.png
new file mode 100644
index 0000000..8380024
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-kbstate_stickykeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-key.png b/kbstateapplet/images/cr22-action-key.png
new file mode 100644
index 0000000..8839538
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-key.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-keypressno.png b/kbstateapplet/images/cr22-action-keypressno.png
new file mode 100644
index 0000000..36e6c45
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-keypressno.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-keypressok.png b/kbstateapplet/images/cr22-action-keypressok.png
new file mode 100644
index 0000000..eb8bf1d
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-keypressok.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-lockkey.png b/kbstateapplet/images/cr22-action-lockkey.png
new file mode 100644
index 0000000..eab7fe8
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-lockkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-metakey.png b/kbstateapplet/images/cr22-action-metakey.png
new file mode 100644
index 0000000..7bb6091
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-metakey.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-shiftkey.png b/kbstateapplet/images/cr22-action-shiftkey.png
new file mode 100644
index 0000000..57728a4
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-shiftkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-superkey.png b/kbstateapplet/images/cr22-action-superkey.png
new file mode 100644
index 0000000..c281174
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-superkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr22-action-unlatched.png b/kbstateapplet/images/cr22-action-unlatched.png
new file mode 100644
index 0000000..8839538
--- /dev/null
+++ b/kbstateapplet/images/cr22-action-unlatched.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-altkey.png b/kbstateapplet/images/cr32-action-altkey.png
new file mode 100644
index 0000000..a14311e
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-altkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-capskey.png b/kbstateapplet/images/cr32-action-capskey.png
new file mode 100644
index 0000000..ae9c16b
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-capskey.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-controlkey.png b/kbstateapplet/images/cr32-action-controlkey.png
new file mode 100644
index 0000000..34edc2b
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-controlkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-hyperkey.png b/kbstateapplet/images/cr32-action-hyperkey.png
new file mode 100644
index 0000000..12022e1
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-hyperkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_mouse.png b/kbstateapplet/images/cr32-action-kbstate_mouse.png
new file mode 100644
index 0000000..7bb545f
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_mouse.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_mouse_left.png b/kbstateapplet/images/cr32-action-kbstate_mouse_left.png
new file mode 100644
index 0000000..1285dee
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_mouse_left.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_mouse_left_selected.png b/kbstateapplet/images/cr32-action-kbstate_mouse_left_selected.png
new file mode 100644
index 0000000..f14a894
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_mouse_left_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_mouse_mid.png b/kbstateapplet/images/cr32-action-kbstate_mouse_mid.png
new file mode 100644
index 0000000..73e8d86
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_mouse_mid.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_mouse_mid_selected.png b/kbstateapplet/images/cr32-action-kbstate_mouse_mid_selected.png
new file mode 100644
index 0000000..1b7fa59
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_mouse_mid_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_mouse_right.png b/kbstateapplet/images/cr32-action-kbstate_mouse_right.png
new file mode 100644
index 0000000..76da4bb
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_mouse_right.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_mouse_right_selected.png b/kbstateapplet/images/cr32-action-kbstate_mouse_right_selected.png
new file mode 100644
index 0000000..243f3f5
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_mouse_right_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_slowkeys.png b/kbstateapplet/images/cr32-action-kbstate_slowkeys.png
new file mode 100644
index 0000000..4d898a0
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_slowkeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-kbstate_stickykeys.png b/kbstateapplet/images/cr32-action-kbstate_stickykeys.png
new file mode 100644
index 0000000..765c27d
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-kbstate_stickykeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-key.png b/kbstateapplet/images/cr32-action-key.png
new file mode 100644
index 0000000..6e3cb09
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-key.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-keypressno.png b/kbstateapplet/images/cr32-action-keypressno.png
new file mode 100644
index 0000000..b227c56
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-keypressno.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-keypressok.png b/kbstateapplet/images/cr32-action-keypressok.png
new file mode 100644
index 0000000..75a1d77
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-keypressok.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-lockkey.png b/kbstateapplet/images/cr32-action-lockkey.png
new file mode 100644
index 0000000..f3b7bfb
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-lockkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-metakey.png b/kbstateapplet/images/cr32-action-metakey.png
new file mode 100644
index 0000000..3ab3ed8
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-metakey.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-shiftkey.png b/kbstateapplet/images/cr32-action-shiftkey.png
new file mode 100644
index 0000000..0f73f01
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-shiftkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-superkey.png b/kbstateapplet/images/cr32-action-superkey.png
new file mode 100644
index 0000000..fb3e9a9
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-superkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr32-action-unlatched.png b/kbstateapplet/images/cr32-action-unlatched.png
new file mode 100644
index 0000000..6e3cb09
--- /dev/null
+++ b/kbstateapplet/images/cr32-action-unlatched.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-altkey.png b/kbstateapplet/images/cr48-action-altkey.png
new file mode 100644
index 0000000..109267f
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-altkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-capskey.png b/kbstateapplet/images/cr48-action-capskey.png
new file mode 100644
index 0000000..6418494
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-capskey.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-controlkey.png b/kbstateapplet/images/cr48-action-controlkey.png
new file mode 100644
index 0000000..6167b81
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-controlkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-hyperkey.png b/kbstateapplet/images/cr48-action-hyperkey.png
new file mode 100644
index 0000000..0e115a7
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-hyperkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_mouse.png b/kbstateapplet/images/cr48-action-kbstate_mouse.png
new file mode 100644
index 0000000..30067fa
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_mouse.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_mouse_left.png b/kbstateapplet/images/cr48-action-kbstate_mouse_left.png
new file mode 100644
index 0000000..522e36a
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_mouse_left.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_mouse_left_selected.png b/kbstateapplet/images/cr48-action-kbstate_mouse_left_selected.png
new file mode 100644
index 0000000..e42fe28
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_mouse_left_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_mouse_mid.png b/kbstateapplet/images/cr48-action-kbstate_mouse_mid.png
new file mode 100644
index 0000000..3119781
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_mouse_mid.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_mouse_mid_selected.png b/kbstateapplet/images/cr48-action-kbstate_mouse_mid_selected.png
new file mode 100644
index 0000000..511076c
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_mouse_mid_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_mouse_right.png b/kbstateapplet/images/cr48-action-kbstate_mouse_right.png
new file mode 100644
index 0000000..d4bd834
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_mouse_right.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_mouse_right_selected.png b/kbstateapplet/images/cr48-action-kbstate_mouse_right_selected.png
new file mode 100644
index 0000000..b35029f
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_mouse_right_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_slowkeys.png b/kbstateapplet/images/cr48-action-kbstate_slowkeys.png
new file mode 100644
index 0000000..6c707e0
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_slowkeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-kbstate_stickykeys.png b/kbstateapplet/images/cr48-action-kbstate_stickykeys.png
new file mode 100644
index 0000000..3150fdf
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-kbstate_stickykeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-key.png b/kbstateapplet/images/cr48-action-key.png
new file mode 100644
index 0000000..91ffaf8
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-key.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-keypressno.png b/kbstateapplet/images/cr48-action-keypressno.png
new file mode 100644
index 0000000..6a27e01
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-keypressno.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-keypressok.png b/kbstateapplet/images/cr48-action-keypressok.png
new file mode 100644
index 0000000..3137bda
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-keypressok.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-lockkey.png b/kbstateapplet/images/cr48-action-lockkey.png
new file mode 100644
index 0000000..a149438
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-lockkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-metakey.png b/kbstateapplet/images/cr48-action-metakey.png
new file mode 100644
index 0000000..87b30fb
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-metakey.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-shiftkey.png b/kbstateapplet/images/cr48-action-shiftkey.png
new file mode 100644
index 0000000..9f35c0b
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-shiftkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-superkey.png b/kbstateapplet/images/cr48-action-superkey.png
new file mode 100644
index 0000000..e28d56a
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-superkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr48-action-unlatched.png b/kbstateapplet/images/cr48-action-unlatched.png
new file mode 100644
index 0000000..91ffaf8
--- /dev/null
+++ b/kbstateapplet/images/cr48-action-unlatched.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-altkey.png b/kbstateapplet/images/cr64-action-altkey.png
new file mode 100644
index 0000000..2bc4fdf
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-altkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-capskey.png b/kbstateapplet/images/cr64-action-capskey.png
new file mode 100644
index 0000000..aeb8d37
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-capskey.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-controlkey.png b/kbstateapplet/images/cr64-action-controlkey.png
new file mode 100644
index 0000000..6474c9c
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-controlkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-hyperkey.png b/kbstateapplet/images/cr64-action-hyperkey.png
new file mode 100644
index 0000000..7d07b5d
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-hyperkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_mouse.png b/kbstateapplet/images/cr64-action-kbstate_mouse.png
new file mode 100644
index 0000000..65c0bed
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_mouse.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_mouse_left.png b/kbstateapplet/images/cr64-action-kbstate_mouse_left.png
new file mode 100644
index 0000000..477a376
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_mouse_left.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_mouse_left_selected.png b/kbstateapplet/images/cr64-action-kbstate_mouse_left_selected.png
new file mode 100644
index 0000000..7238a43
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_mouse_left_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_mouse_mid.png b/kbstateapplet/images/cr64-action-kbstate_mouse_mid.png
new file mode 100644
index 0000000..af48eac
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_mouse_mid.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_mouse_mid_selected.png b/kbstateapplet/images/cr64-action-kbstate_mouse_mid_selected.png
new file mode 100644
index 0000000..09090f6
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_mouse_mid_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_mouse_right.png b/kbstateapplet/images/cr64-action-kbstate_mouse_right.png
new file mode 100644
index 0000000..9358126
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_mouse_right.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_mouse_right_selected.png b/kbstateapplet/images/cr64-action-kbstate_mouse_right_selected.png
new file mode 100644
index 0000000..6b89e7d
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_mouse_right_selected.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_slowkeys.png b/kbstateapplet/images/cr64-action-kbstate_slowkeys.png
new file mode 100644
index 0000000..737fb13
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_slowkeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-kbstate_stickykeys.png b/kbstateapplet/images/cr64-action-kbstate_stickykeys.png
new file mode 100644
index 0000000..4b705d7
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-kbstate_stickykeys.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-key.png b/kbstateapplet/images/cr64-action-key.png
new file mode 100644
index 0000000..0858c19
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-key.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-keypressno.png b/kbstateapplet/images/cr64-action-keypressno.png
new file mode 100644
index 0000000..c8abb2f
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-keypressno.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-keypressok.png b/kbstateapplet/images/cr64-action-keypressok.png
new file mode 100644
index 0000000..04af637
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-keypressok.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-lockkey.png b/kbstateapplet/images/cr64-action-lockkey.png
new file mode 100644
index 0000000..66f92c2
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-lockkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-metakey.png b/kbstateapplet/images/cr64-action-metakey.png
new file mode 100644
index 0000000..d862c94
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-metakey.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-shiftkey.png b/kbstateapplet/images/cr64-action-shiftkey.png
new file mode 100644
index 0000000..93fe232
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-shiftkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-superkey.png b/kbstateapplet/images/cr64-action-superkey.png
new file mode 100644
index 0000000..2c80b3b
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-superkey.png
Binary files differ
diff --git a/kbstateapplet/images/cr64-action-unlatched.png b/kbstateapplet/images/cr64-action-unlatched.png
new file mode 100644
index 0000000..0858c19
--- /dev/null
+++ b/kbstateapplet/images/cr64-action-unlatched.png
Binary files differ
diff --git a/kbstateapplet/images/crsc-action-altkey.svg b/kbstateapplet/images/crsc-action-altkey.svg
new file mode 100644
index 0000000..237120c
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-altkey.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 50 L 50 50 " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-capskey.svg b/kbstateapplet/images/crsc-action-capskey.svg
new file mode 100644
index 0000000..35a5abe
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-capskey.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 32 50 L 14 32 L 24 32 L 24 14 L 40 14 L 40 32 L 50 32 L 32 50 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-controlkey.svg b/kbstateapplet/images/crsc-action-controlkey.svg
new file mode 100644
index 0000000..1adda99
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-controlkey.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 32 L 32 14 L 50 32 " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-hyperkey.svg b/kbstateapplet/images/crsc-action-hyperkey.svg
new file mode 100644
index 0000000..dee8c43
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-hyperkey.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 14 L 50 14 " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 32 L 50 32 " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 50 L 50 50 " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_mouse.svg b/kbstateapplet/images/crsc-action-kbstate_mouse.svg
new file mode 100644
index 0000000..fc20b85
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_mouse.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 13,31 L 13,32 C 13,46 21,50 22,51 L 42,51 C 42,51 51,46 51,32 L 51,31 L 39,29 L 25,29 L 13,31 z " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 13,31 L 13,15 L 25,13 L 25,29 L 13,31 z " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 25,29 L 25,13 L 39,13 L 39,29 L 25,29 z " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 39,29 L 39,13 L 51,15 L 51,31 L 39,29 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_mouse_left.svg b/kbstateapplet/images/crsc-action-kbstate_mouse_left.svg
new file mode 100644
index 0000000..52bffea
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_mouse_left.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:#808080;stroke:#808080;stroke-width:2"
+ d="M 21 23 A 2 2 0 1 1 17,23 A 2 2 0 1 1 21 23 z" />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_mouse_left_selected.svg b/kbstateapplet/images/crsc-action-kbstate_mouse_left_selected.svg
new file mode 100644
index 0000000..c98a3a7
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_mouse_left_selected.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:#808080;stroke:#808080;stroke-width:2"
+ d="M 13,31 L 13,15 L 25,13 L 25,29 L 13,31 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_mouse_mid.svg b/kbstateapplet/images/crsc-action-kbstate_mouse_mid.svg
new file mode 100644
index 0000000..9080915
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_mouse_mid.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:#808080;stroke:#808080;stroke-width:2"
+ d="M 34 21 A 2 2 0 1 1 30,21 A 2 2 0 1 1 34 21 z" />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_mouse_mid_selected.svg b/kbstateapplet/images/crsc-action-kbstate_mouse_mid_selected.svg
new file mode 100644
index 0000000..4c0bf2b
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_mouse_mid_selected.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:#808080;stroke:#808080;stroke-width:2"
+ d="M 25,29 L 25,13 L 39,13 L 39,29 L 25,29 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_mouse_right.svg b/kbstateapplet/images/crsc-action-kbstate_mouse_right.svg
new file mode 100644
index 0000000..652c3d7
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_mouse_right.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:#808080;stroke:#808080;stroke-width:2;"
+ d="M 47 23 A 2 2 0 1 1 43,23 A 2 2 0 1 1 47 23 z" />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_mouse_right_selected.svg b/kbstateapplet/images/crsc-action-kbstate_mouse_right_selected.svg
new file mode 100644
index 0000000..2d890fd
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_mouse_right_selected.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:#808080;stroke:#808080;stroke-width:2"
+ d="M 39,29 L 39,13 L 51,15 L 51,31 L 39,29 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_slowkeys.svg b/kbstateapplet/images/crsc-action-kbstate_slowkeys.svg
new file mode 100644
index 0000000..bfff429
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_slowkeys.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 53 33 A 20 20 0 1 1 13,33 A 20 20 0 1 1 53 33 z" />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 33,16 L 33,33 L 46,33" />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-kbstate_stickykeys.svg b/kbstateapplet/images/crsc-action-kbstate_stickykeys.svg
new file mode 100644
index 0000000..9d9c2dc
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-kbstate_stickykeys.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="64" width="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 32 L 32 50 L 50 32 " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 32,14 L 32,50" />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-key.svg b/kbstateapplet/images/crsc-action-key.svg
new file mode 100644
index 0000000..644dca1
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-key.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+</svg>
diff --git a/kbstateapplet/images/crsc-action-keypressno.svg b/kbstateapplet/images/crsc-action-keypressno.svg
new file mode 100644
index 0000000..e59b782
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-keypressno.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:none;stroke:#ff0000;stroke-width:4;"
+ d="M 25 25 L 55 55 " />
+ <path style="fill:none;stroke:#ff0000;stroke-width:4;"
+ d="M 25 55 L 55 25 " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-keypressok.svg b/kbstateapplet/images/crsc-action-keypressok.svg
new file mode 100644
index 0000000..7ae244d
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-keypressok.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:#00ff00;stroke:#00c000;stroke-width:2;"
+ d="M 14 31 L 23 55 L 55 22 L 25 42 L 14 31 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-lockkey.svg b/kbstateapplet/images/crsc-action-lockkey.svg
new file mode 100644
index 0000000..9611a09
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-lockkey.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 32 50 L 22 40 L 28 40 L 28 30 L 36 30 L 36 40 L 42 40 L 32 50 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-metakey.svg b/kbstateapplet/images/crsc-action-metakey.svg
new file mode 100644
index 0000000..49e07ad
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-metakey.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:#000000;stroke:#808080;stroke-width:2;"
+ d="M 32 14 L 14 32 L 32 50 L 50 32 L 32 14 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-shiftkey.svg b/kbstateapplet/images/crsc-action-shiftkey.svg
new file mode 100644
index 0000000..8ec78c9
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-shiftkey.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 32 14 L 14 32 L 24 32 L 24 50 L 40 50 L 40 32 L 50 32 L 32 14 z " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-superkey.svg b/kbstateapplet/images/crsc-action-superkey.svg
new file mode 100644
index 0000000..c0f6e58
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-superkey.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 14 L 50 14 " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 32 L 50 32 " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 50 L 50 50 " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 14 14 L 14 50 " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 32 14 L 32 50 " />
+ <path style="fill:none;stroke:#808080;stroke-width:2;"
+ d="M 50 14 L 50 50 " />
+</svg>
diff --git a/kbstateapplet/images/crsc-action-unlatched.svg b/kbstateapplet/images/crsc-action-unlatched.svg
new file mode 100644
index 0000000..644dca1
--- /dev/null
+++ b/kbstateapplet/images/crsc-action-unlatched.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="64" height="64">
+</svg>
diff --git a/kbstateapplet/kbstate.cpp b/kbstateapplet/kbstate.cpp
new file mode 100644
index 0000000..05ee26a
--- /dev/null
+++ b/kbstateapplet/kbstate.cpp
@@ -0,0 +1,1079 @@
+/*
+ * Copyright (c) 2004 Gunnar Schmi Dt <gunnar@schmi-dt.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ */
+
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qdrawutil.h>
+#include <qcursor.h>
+#include <qimage.h>
+#include <qpopupmenu.h>
+
+#include <kaboutapplication.h>
+#include <kpopupmenu.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kiconeffect.h>
+#include <knotifyclient.h>
+#include <kshortcut.h>
+#include <kkeynative.h>
+#include <kdemacros.h>
+#include <kprocess.h>
+#include "kdeexportfix.h"
+#include "kbstate.h"
+#include "kbstate.moc"
+
+extern "C"
+{
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/XKBlib.h>
+#define XK_MISCELLANY
+#define XK_XKB_KEYS
+#include <X11/keysymdef.h>
+#include <X11/extensions/XKB.h>
+
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("kbstateapplet");
+ KbStateApplet *applet = new KbStateApplet(configFile, KPanelApplet::Normal, KPanelApplet::About, parent, "kbstateapplet");
+ return applet;
+ }
+}
+
+struct ModifierKey {
+ const unsigned int mask;
+ const KeySym keysym;
+ const char *name;
+ const char *icon;
+ const char *text;
+ const bool isModifier;
+};
+
+static ModifierKey modifierKeys[] = {
+ { ShiftMask, 0, I18N_NOOP("Shift"), "shiftkey", "", true },
+ { ControlMask, 0, I18N_NOOP("Control"), "controlkey", "", true },
+ { 0, XK_Alt_L, I18N_NOOP("Alt"), "altkey", "", true },
+ { 0, 0, I18N_NOOP("Win"), "superkey", "", true },
+ { 0, XK_Meta_L, I18N_NOOP("Meta"), "metakey", "", true },
+ { 0, XK_Super_L, I18N_NOOP("Super"), "superkey", "", true },
+ { 0, XK_Hyper_L, I18N_NOOP("Hyper"), "hyperkey", "", true },
+ { 0, 0, I18N_NOOP("Alt Graph"), "", I18N_NOOP("æ"), true },
+ { 0, XK_Num_Lock, I18N_NOOP("Num Lock"), "lockkey", I18N_NOOP("Num"), false },
+ { LockMask, 0, I18N_NOOP("Caps Lock"), "capskey", "", false },
+ { 0, XK_Scroll_Lock, I18N_NOOP("Scroll Lock"), "lockkey", I18N_NOOP("Scroll"), false },
+ { 0, 0, "", "", "", false }
+};
+
+
+/********************************************************************/
+
+KbStateApplet::KbStateApplet(const QString& configFile, Type t, int actions,
+ QWidget *parent, const char *name)
+ : KPanelApplet( configFile, t, actions, parent, name )
+{
+ for (int i = 0; i < 8; i++) {
+ icons[i] = 0;
+ }
+ instance = new KInstance ("kbstateapplet");
+ loadConfig();
+ initMasks();
+ mouse = new MouseIcon (instance, this, "mouse");
+ sticky = new TimeoutIcon (instance, "", "kbstate_stickykeys", this, "sticky");
+ slow = new TimeoutIcon (instance, "", "kbstate_slowkeys", this, "slow");
+ bounce = new TimeoutIcon (instance, "", "", this, "bounce");
+
+ xkb = XkbGetMap(qt_xdisplay(), 0, XkbUseCoreKbd);
+
+ if (xkb != 0) {
+ XkbGetControls (qt_xdisplay(), XkbAllControlsMask, xkb);
+ if (xkb->ctrls != 0)
+ accessxFeatures = xkb->ctrls->enabled_ctrls;
+ else
+ accessxFeatures = 0;
+ }
+ else
+ accessxFeatures = 0;
+
+ //startTimer(100); // ten times a second
+ connect(kapp, SIGNAL(kdisplayPaletteChanged()), SLOT(paletteChanged()));
+
+ kapp->installX11EventFilter (this);
+ int opcode_rtn, error_rtn;
+ XkbQueryExtension (this->x11Display(), &opcode_rtn, &xkb_base_event_type, &error_rtn, NULL, NULL);
+ XkbSelectEvents (this->x11Display(), XkbUseCoreKbd, XkbAllEventsMask,
+ XkbAllEventsMask);
+
+ buildPopupMenu();
+}
+
+KbStateApplet::~KbStateApplet() {
+ kapp->removeX11EventFilter (this);
+ setCustomMenu(0);
+ delete instance;
+ delete popup;
+ delete sizePopup;
+}
+// Builds, connects _popup menu
+void KbStateApplet::buildPopupMenu()
+{
+ sizePopup=new KPopupMenu(this);
+ sizePopup->setCheckable( true );
+ sizePopup->insertItem(i18n("Small"), 13);
+ sizePopup->insertItem(i18n("Medium"), 20);
+ sizePopup->insertItem(i18n("Large"), 26);
+ connect(sizePopup,SIGNAL(activated(int)), this, SLOT(setIconDim(int)));
+
+ showPopup=new KPopupMenu(this);
+ showPopup->setCheckable( true );
+ modifierItem=showPopup->insertItem(i18n("Modifier Keys"), this, SLOT(toggleModifier()));
+ lockkeysItem=showPopup->insertItem(i18n("Lock Keys"), this, SLOT(toggleLockkeys()));
+ mouseItem=showPopup->insertItem(i18n("Mouse Status"), this, SLOT(toggleMouse()));
+ accessxItem=showPopup->insertItem(i18n("AccessX Status"), this, SLOT(toggleAccessX()));
+
+ popup = new KPopupMenu(this);
+ popup->setCheckable( true );
+ popup->insertTitle(0, i18n("Keyboard Status Applet"));
+ popup->insertItem(i18n("Set Icon Size"),sizePopup);
+ fillSpaceItem = popup->insertItem(i18n("Fill Available Space"),
+ this, SLOT(toggleFillSpace()));
+ popup->insertItem(i18n("Show"),showPopup);
+ popup->insertItem(i18n("Configure AccessX Features..."), this, SLOT(configureAccessX()));
+ popup->insertItem(i18n("Configure Keyboard..."), this, SLOT(configureKeyboard()));
+ popup->insertItem(i18n("Configure Mouse..."), this, SLOT(configureMouse()));
+ popup->insertSeparator();
+ popup->insertItem(i18n("About"), this, SLOT(about()));
+ setCustomMenu(popup);
+ updateMenu();
+}
+
+void KbStateApplet::updateMenu()
+{ if (popup) {
+ showPopup->setItemChecked (modifierItem, showModifiers);
+ showPopup->setItemChecked (lockkeysItem, showLockkeys);
+ showPopup->setItemChecked (mouseItem, showMouse);
+ showPopup->setItemChecked (accessxItem, showAccessX);
+ popup->setItemChecked (fillSpaceItem, fillSpace);
+ sizePopup->setItemChecked(13, size == 13);
+ sizePopup->setItemChecked(20, size == 20);
+ sizePopup->setItemChecked(26, size == 26);
+ }
+}
+
+void calculateSizes (int space, int modifiers, int lockkeys, int accessx,
+ bool showMouse, int &lines, int &length, int &size)
+// Calculates the layout based on a given number of modifiers, lockkeys and
+// accessx features.
+// Output:
+// lines: number of lines
+// length: number of icons per line
+// size: size of the icons
+{
+ // Calculate lines and length
+ if (showMouse)
+ ++accessx;
+
+ lines = space>=size ? space/size : 1;
+ length = modifiers + lockkeys + accessx;
+
+ if (length > 0 && lines >= 2) {
+ length = (length + lines-1)/lines;
+
+ // As we want to have some line breaks, we need to do some corrections:
+ // Calculate the number of lines that are really needed:
+ int linesNeeded = (modifiers+length-1)/length + (lockkeys+length-1)/length;
+ int tmp1 = modifiers%length == 0 ? 0 : length - modifiers%length;
+ int tmp2 = lockkeys%length == 0 ? 0 : length - lockkeys%length;
+ if ((tmp1 + tmp2) < accessx)
+ linesNeeded = (modifiers+lockkeys+accessx + length-1)/length;
+
+ // If we need more lines than we have, try with more icons per line:
+ while (linesNeeded > lines) {
+ length++;
+ linesNeeded = (modifiers+length-1)/length + (lockkeys+length-1)/length;
+ int tmp1 = modifiers%length == 0 ? 0 : length - modifiers%length;
+ int tmp2 = lockkeys%length == 0 ? 0 : length - lockkeys%length;
+ if ((tmp1 + tmp2) < accessx)
+ linesNeeded = (modifiers+lockkeys+accessx + length-1)/length;
+ }
+ lines = linesNeeded;
+ }
+}
+
+int KbStateApplet::widthForHeight(int h) const {
+ int lines, length;
+ int size = this->size;
+
+ int accessx = 0;
+ if ((accessxFeatures & XkbStickyKeysMask) != 0)
+ accessx++;
+ if ((accessxFeatures & XkbSlowKeysMask) != 0)
+ accessx++;
+ if ((accessxFeatures & XkbBounceKeysMask) != 0)
+ accessx++;
+
+ calculateSizes (h, showModifiers?modifiers.count():0,
+ showLockkeys?lockkeys.count():0,
+ showAccessX?accessx:0,
+ showMouse, lines, length, size);
+
+ if (fillSpace)
+ size = h/lines;
+
+ return length*size;
+}
+
+int KbStateApplet::heightForWidth(int w) const {
+ int lines, length;
+ int size = this->size;
+
+ int accessx = 0;
+ if ((accessxFeatures & XkbStickyKeysMask) != 0)
+ accessx++;
+ if ((accessxFeatures & XkbSlowKeysMask) != 0)
+ accessx++;
+ if ((accessxFeatures & XkbBounceKeysMask) != 0)
+ accessx++;
+
+ calculateSizes (w, showModifiers?modifiers.count():0,
+ showLockkeys?lockkeys.count():0,
+ showAccessX?accessx:0,
+ showMouse, lines, length, size);
+
+ if (fillSpace)
+ size = w/lines;
+
+ return length*size;
+}
+
+void KbStateApplet::mousePressEvent(QMouseEvent *e) {
+ if (e->button() == RightButton)
+ popup->popup(e->globalPos());
+}
+
+void KbStateApplet::setIconDim (int size) {
+ this->size = size;
+ saveConfig();
+ updateMenu();
+ update();
+ updateGeometry();
+ emit updateLayout();
+}
+
+void KbStateApplet::toggleFillSpace() {
+ fillSpace = !fillSpace;
+ saveConfig();
+ updateMenu();
+ layout();
+ updateGeometry();
+ emit updateLayout();
+}
+
+void KbStateApplet::resizeEvent( QResizeEvent*e ) {
+ QWidget::resizeEvent(e);
+ layout();
+}
+
+void KbStateApplet::layout() {
+ int size = this->size;
+
+ int lines, length, x,y,dx,dy, ldx,ldy;
+ int modifierCount = showModifiers?modifiers.count():0;
+ int lockkeyCount = showLockkeys?lockkeys.count():0;
+ int accessxCount = 0;
+
+ if (showAccessX) {
+ if ((accessxFeatures & XkbStickyKeysMask) != 0)
+ accessxCount++;
+ if ((accessxFeatures & XkbSlowKeysMask) != 0)
+ accessxCount++;
+ if ((accessxFeatures & XkbBounceKeysMask) != 0)
+ accessxCount++;
+ }
+
+ if (orientation() == Vertical) {
+ calculateSizes (width(), modifierCount, lockkeyCount, accessxCount,
+ showMouse, lines, length, size);
+
+ if (fillSpace)
+ size = width()/lines;
+
+ x = (width()-lines*size)/2;
+ y = 0;
+ dx = 0;
+ dy = size;
+ ldx= size;
+ ldy= 0;
+ }
+ else {
+ calculateSizes (height(), modifierCount, lockkeyCount, accessxCount,
+ showMouse, lines, length, size);
+
+ if (fillSpace)
+ size = height()/lines;
+
+ x = 0;
+ y = (height()-lines*size)/2;
+ dx = size;
+ dy = 0;
+ ldx= 0;
+ ldy= size;
+ }
+
+ StatusIcon *icon;
+ int item = 1;
+ for (icon = modifiers.first(); icon; icon = modifiers.next()) {
+ if (showModifiers) {
+ icon->setGeometry (x, y, size, size);
+ icon->show();
+ icon->update();
+ item++; x+=dx; y+=dy;
+ if (item > length) {
+ x = x - length*dx + ldx;
+ y = y - length*dy + ldy;
+ item = 1;
+ }
+ }
+ else
+ icon->hide();
+ }
+
+ int lockkeyLines = (lockkeyCount+length-1)/length;
+ int accessxLines = lines - (modifierCount+length-1)/length - lockkeyLines;
+
+ if (showMouse)
+ ++accessxCount;
+
+ if (lockkeyLines*length + accessxLines*length
+ >= lockkeyCount + accessxCount)
+ {
+ if (lines > 1 && item > 1) {
+ x = x - (item-1)*dx + ldx;
+ y = y - (item-1)*dy + ldy;
+ item = 1;
+ }
+ }
+ else {
+ accessxLines++;
+ }
+
+ if (showMouse && showAccessX && accessxLines > 0) {
+ mouse->setGeometry (x, y, size, size);
+ mouse->show();
+ mouse->update();
+ accessxCount--;
+ item++; x+=dx; y+=dy;
+ if (item > length) {
+ x = x - length*dx + ldx;
+ y = y - length*dy + ldy;
+ item = 1;
+ accessxLines--;
+ }
+ }
+ else
+ mouse->hide();
+
+ if ((accessxFeatures & XkbStickyKeysMask) != 0
+ && showAccessX && accessxLines > 0)
+ {
+ sticky->setGeometry (x, y, size, size);
+ sticky->show();
+ sticky->update();
+ accessxCount--;
+ item++; x+=dx; y+=dy;
+ if (item > length) {
+ x = x - length*dx + ldx;
+ y = y - length*dy + ldy;
+ item = 1;
+ accessxLines--;
+ }
+ }
+ else
+ sticky->hide();
+
+ if ((accessxFeatures & XkbSlowKeysMask) != 0
+ && showAccessX && accessxLines > 0)
+ {
+ slow->setGeometry (x, y, size, size);
+ slow->show();
+ slow->update();
+ accessxCount--;
+ item++; x+=dx; y+=dy;
+ if (item > length) {
+ x = x - length*dx + ldx;
+ y = y - length*dy + ldy;
+ item = 1;
+ accessxLines--;
+ }
+ }
+ else
+ slow->hide();
+
+ if ((accessxFeatures & XkbBounceKeysMask) != 0
+ && showAccessX && accessxLines > 0)
+ {
+ bounce->setGeometry (x, y, size, size);
+ bounce->show();
+ bounce->update();
+ accessxCount--;
+ item++; x+=dx; y+=dy;
+ if (item > length) {
+ x = x - length*dx + ldx;
+ y = y - length*dy + ldy;
+ item = 1;
+ accessxLines--;
+ }
+ }
+ else
+ bounce->hide();
+
+ if (lines > 1) {
+ if (item != 1) {
+ x = x - (item-1)*dx + ldx;
+ y = y - (item-1)*dy + ldy;
+ }
+ item = 1;
+ }
+ for (icon = lockkeys.first(); icon; icon = lockkeys.next()) {
+ if (showLockkeys) {
+ icon->setGeometry (x, y, size, size);
+ icon->show();
+ icon->update();
+ item++; x+=dx; y+=dy;
+ if (item > length) {
+ x = x - length*dx + ldx;
+ y = y - length*dy + ldy;
+ item = 1;
+ }
+ }
+ else
+ icon->hide();
+ }
+
+ if ((accessxFeatures & XkbBounceKeysMask) != 0
+ && showAccessX && accessxCount > 0)
+ {
+ bounce->setGeometry (x, y, size, size);
+ bounce->show();
+ bounce->update();
+ item++; x+=dx; y+=dy;
+ accessxCount--;
+ }
+
+ if ((accessxFeatures & XkbSlowKeysMask) != 0
+ && showAccessX && accessxCount > 0)
+ {
+ slow->setGeometry (x, y, size, size);
+ slow->show();
+ slow->update();
+ item++; x+=dx; y+=dy;
+ accessxCount--;
+ }
+
+ if ((accessxFeatures & XkbStickyKeysMask) != 0
+ && showAccessX && accessxCount > 0)
+ {
+ sticky->setGeometry (x, y, size, size);
+ sticky->show();
+ sticky->update();
+ item++; x+=dx; y+=dy;
+ accessxCount--;
+ }
+
+ if (showMouse && accessxCount > 0)
+ {
+ mouse->setGeometry (x, y, size, size);
+ mouse->show();
+ mouse->update();
+ item++; x+=dx; y+=dy;
+ accessxCount--;
+ }
+}
+
+void KbStateApplet::paletteChanged() {
+ for (int i = 0; i < 8; i++) {
+ if (icons[i])
+ icons[i]->updateImages();
+ }
+ mouse->update();
+ sticky->update();
+ slow->update();
+ bounce->update();
+}
+
+void KbStateApplet::initMasks() {
+ for (int i = 0; i < 8; i++) {
+ if (icons[i])
+ delete icons[i];
+ icons[i] = 0;
+ }
+ state = 0;
+
+ for (int i = 0; strcmp(modifierKeys[i].name, "") != 0; i++) {
+ int mask = modifierKeys[i].mask;
+ if (mask == 0)
+ if (modifierKeys[i].keysym != 0)
+ mask = XkbKeysymToModifiers (this->x11Display(), modifierKeys[i].keysym);
+ else if (!strcmp(modifierKeys[i].name, "Win"))
+ mask = KKeyNative::modX(KKey::WIN);
+ else
+ mask = XkbKeysymToModifiers (this->x11Display(), XK_Mode_switch)
+ | XkbKeysymToModifiers (this->x11Display(), XK_ISO_Level3_Shift)
+ | XkbKeysymToModifiers (this->x11Display(), XK_ISO_Level3_Latch)
+ | XkbKeysymToModifiers (this->x11Display(), XK_ISO_Level3_Lock);
+
+ int map = 0;
+ for (map = 0; map < 8; map++) {
+ if ((mask & (1 << map)) != 0)
+ break;
+ }
+ if ((map <= 7) && !(icons[map])) {
+ icons[map] = new KeyIcon (i, instance, this, modifierKeys[i].name);
+ QToolTip::add (icons[map], i18n (modifierKeys[i].name));
+ connect (icons[map], SIGNAL(stateChangeRequest (KeyIcon*,bool,bool)),
+ SLOT(stateChangeRequest (KeyIcon*,bool,bool)));
+ if (modifierKeys[i].isModifier)
+ modifiers.append(icons[map]);
+ else
+ lockkeys.append(icons[map]);
+ }
+ }
+}
+
+bool KbStateApplet::x11Event (XEvent *evt) {
+ if (evt->type == xkb_base_event_type + XkbEventCode) {
+ XkbEvent *kbevt = (XkbEvent *)evt;
+ switch (kbevt->any.xkb_type) {
+ case XkbStateNotify:
+ timerEvent (0);
+
+ mouse->setState (kbevt->state.ptr_buttons);
+ break;
+ case XkbAccessXNotify:
+ switch (kbevt->accessx.detail) {
+ case XkbAXN_SKPress:
+ slow->setGlyth(i18n("a (the first letter in the alphabet)", "a"));
+ slow->setImage("unlatched");
+ break;
+ case XkbAXN_SKAccept:
+ slow->setImage("keypressok");
+ break;
+ case XkbAXN_SKRelease:
+ slow->setGlyth(" ");
+ slow->setImage("kbstate_slowkeys");
+ break;
+ case XkbAXN_SKReject:
+ slow->setImage("keypressno", kbevt->accessx.sk_delay>150?kbevt->accessx.sk_delay:150);
+ break;
+ case XkbAXN_BKAccept:
+ slow->setGlyth(i18n("a (the first letter in the alphabet)", "a"));
+ bounce->setImage("keypressok", kbevt->accessx.sk_delay>150?kbevt->accessx.sk_delay:150);
+ break;
+ case XkbAXN_BKReject:
+ slow->setGlyth(i18n("a (the first letter in the alphabet)", "a"));
+ bounce->setImage("keypressno", kbevt->accessx.sk_delay>150?kbevt->accessx.sk_delay:150);
+ break;
+ }
+ break;
+ case XkbControlsNotify: {
+ XkbControlsNotifyEvent* event = (XkbControlsNotifyEvent*)evt;
+ accessxFeatures = event->enabled_ctrls;
+
+ if ((accessxFeatures & XkbMouseKeysMask) != 0) {
+ XkbGetControls (qt_xdisplay(), XkbMouseKeysMask, xkb);
+ if (xkb->ctrls->mk_dflt_btn < 1)
+ mouse->setActiveKey (1);
+ else if (xkb->ctrls->mk_dflt_btn > 3)
+ mouse->setActiveKey (1);
+ else
+ mouse->setActiveKey (xkb->ctrls->mk_dflt_btn);
+ }
+ else
+ mouse->setActiveKey (0);
+
+ layout();
+ updateGeometry();
+ emit updateLayout();
+ break;
+ }
+ case XkbExtensionDeviceNotify:
+ /* This is a hack around the fact that XFree86's XKB doesn't give AltGr notifications */
+ break;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+void KbStateApplet::timerEvent(QTimerEvent*) {
+ XkbStateRec state_return;
+ XkbGetState (this->x11Display(), XkbUseCoreKbd, &state_return);
+ unsigned char latched = XkbStateMods (&state_return);
+ unsigned char locked = XkbModLocks (&state_return);
+ int mods = ((int)latched)<<8 | locked;
+
+ if (state != mods) {
+ state = mods;
+ for (int i = 0; i < 8; i++) {
+ if (icons[i])
+ icons[i]->setState ((latched&(1<<i)) != 0, (locked&(1<<i)) != 0);
+ }
+ }
+}
+
+void KbStateApplet::stateChangeRequest (KeyIcon *source, bool latched, bool locked) {
+ for (int i = 0; i < 8; i++) {
+ if (icons[i] == source) {
+ if (locked)
+ XkbLockModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 1<<i);
+ else if (latched) {
+ XkbLockModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 0);
+ XkbLatchModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 1<<i);
+ }
+ else {
+ XkbLockModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 0);
+ XkbLatchModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 0);
+ }
+ }
+ }
+}
+
+
+void KbStateApplet::toggleModifier() {
+ showModifiers = !showModifiers;
+ updateMenu();
+ layout();
+ updateGeometry();
+ saveConfig();
+ emit updateLayout();
+}
+
+void KbStateApplet::toggleLockkeys() {
+ showLockkeys = !showLockkeys;
+ updateMenu();
+ layout();
+ updateGeometry();
+ saveConfig();
+ emit updateLayout();
+}
+
+void KbStateApplet::toggleMouse() {
+ showMouse = !showMouse;
+ updateMenu();
+ layout();
+ updateGeometry();
+ saveConfig();
+ emit updateLayout();
+}
+
+void KbStateApplet::toggleAccessX() {
+ showAccessX = !showAccessX;
+ updateMenu();
+ layout();
+ updateGeometry();
+ saveConfig();
+ emit updateLayout();
+}
+
+void KbStateApplet::configureAccessX() {
+ kapp->startServiceByDesktopName("kcmaccess");
+}
+
+void KbStateApplet::configureKeyboard() {
+ // The modulename "keyboard" is ambiguous on SuSE systems
+ // as there is also a YaST-module called "keyboard".
+ KProcess proc;
+ proc << "kcmshell";
+ proc << "kde/keyboard";
+ proc.start(KProcess::DontCare);
+ proc.detach();
+}
+
+void KbStateApplet::configureMouse() {
+ kapp->startServiceByDesktopName("mouse");
+}
+
+void KbStateApplet::about() {
+ KAboutData about("kbstateapplet", I18N_NOOP("Keyboard Status Applet"), "0.2",
+ I18N_NOOP("Panel applet that shows the state of the modifier keys"), KAboutData::License_GPL_V2, "(C) 2004 Gunnar Schmi Dt");
+ KAboutApplication a(&about, this);
+ a.exec();
+}
+
+void KbStateApplet::loadConfig()
+{
+ KConfig *c = config();
+ c->setGroup("General");
+ size = c->readNumEntry("IconDim", 20);
+ fillSpace = c->readBoolEntry("fill space", true);
+ showModifiers = c->readBoolEntry("Modifierkeys visible",true);
+ showLockkeys = c->readBoolEntry("Lockkeys visible",true);
+ showMouse = c->readBoolEntry("Mouse status visible",true);
+ showAccessX = c->readBoolEntry("Slowkeys status visible",true);
+ showAccessX = c->readBoolEntry("AccessX status visible",showAccessX);
+}
+
+void KbStateApplet::saveConfig()
+{
+ KConfig *c = config();
+ c->setGroup("General");
+ c->writeEntry("IconDim", size);
+ c->writeEntry("fill space", fillSpace);
+ c->writeEntry("Modifierkeys visible", showModifiers);
+ c->writeEntry("Lockkeys visible", showLockkeys);
+ c->writeEntry("Mouse status visible", showMouse);
+ c->writeEntry("AccessX status visible", showAccessX);
+ c->sync();
+}
+
+/********************************************************************/
+
+KeyIcon::KeyIcon (int keyId, KInstance *instance,
+ QWidget *parent, const char *name)
+ : StatusIcon (modifierKeys[keyId].name, parent, name) {
+ this->instance = instance;
+ this->keyId = keyId;
+ this->tristate = (modifierKeys[keyId].isModifier);
+ isLocked = false;
+ isLatched = false;
+ updateImages ();
+ connect (this, SIGNAL(clicked()), SLOT(clickedSlot()));
+}
+
+KeyIcon::~KeyIcon () {
+}
+
+void KeyIcon::setState (bool latched, bool locked) {
+ latched = latched | locked;
+
+ isLatched = latched;
+ isLocked = locked;
+ update();
+}
+
+void KeyIcon::clickedSlot () {
+ if (tristate)
+ emit stateChangeRequest (this, !isLocked, isLatched&!isLocked);
+ else
+ emit stateChangeRequest (this, false, !isLocked);
+}
+
+
+void KeyIcon::resizeEvent( QResizeEvent*e )
+{
+ QWidget::resizeEvent(e);
+ updateImages();
+}
+
+void KeyIcon::updateImages () {
+ int size = width()<height() ? width() : height();
+
+ locked = instance->iconLoader()->loadIcon("lock_overlay", KIcon::Panel, size-4);
+ if (strcmp(modifierKeys[keyId].icon, "")) {
+ latched = instance->iconLoader()->loadIcon(modifierKeys[keyId].icon, KIcon::NoGroup, size-4);
+ unlatched = instance->iconLoader()->loadIcon(modifierKeys[keyId].icon, KIcon::NoGroup, size-4);
+
+ QImage img = latched.convertToImage();
+ KIconEffect::colorize(img, KGlobalSettings::highlightedTextColor(), 1.0);
+ latched.convertFromImage (img);
+
+ img = unlatched.convertToImage();
+ KIconEffect::colorize(img, KGlobalSettings::textColor(), 1.0);
+ unlatched.convertFromImage (img);
+ }
+
+ update();
+}
+
+void KeyIcon::drawButton (QPainter *p) {
+ QColor black;
+
+ int x = (width()-locked.width())/2;
+ int y = (height()-locked.height())/2;
+ int o = 0;
+ if (isLocked || isLatched) {
+ qDrawShadePanel (p, 0, 0, width(), height(), colorGroup(), true, 1, NULL);
+ p->fillRect (1,1,width()-2,height()-2, KGlobalSettings::highlightColor());
+ if (strcmp(modifierKeys[keyId].icon, ""))
+ p->drawPixmap (x+1,y+1, latched);
+ black = KGlobalSettings::highlightedTextColor();
+ o = 1;
+ }
+ else {
+ qDrawShadePanel (p, 0, 0, width(), height(), colorGroup(), false, 1, NULL);
+ if (strcmp(modifierKeys[keyId].icon, ""))
+ p->drawPixmap (x,y, unlatched);
+ black = KGlobalSettings::textColor();
+ }
+
+ QString text = i18n(modifierKeys[keyId].text);
+ if (!text.isEmpty() && !text.isNull()) {
+ QFont font = KGlobalSettings::generalFont();
+ font.setWeight(QFont::Black);
+ QFontMetrics metrics(font);
+ QRect rect = metrics.boundingRect (text);
+ int size;
+ if (!strcmp(modifierKeys[keyId].name, "Alt Graph"))
+ size = rect.width()>rect.height()?rect.width():rect.height();
+ else
+ size = rect.width()>12*rect.height()/5?rect.width():12*rect.height()/5;
+
+ if (font.pixelSize() != -1)
+ font.setPixelSize (font.pixelSize()*width()*19/size/32);
+ else
+ font.setPointSizeFloat (font.pointSizeFloat()*width()*19/size/32);
+
+ p->setPen (black);
+ p->setFont (font);
+ if (!strcmp(modifierKeys[keyId].name, "Alt Graph"))
+ p->drawText (o,o, width(), height(), Qt::AlignCenter, text);
+ else
+ p->drawText (o,o, width(), height()*(251)/384, Qt::AlignCenter, text);
+ }
+ if (tristate && isLocked) {
+ p->drawPixmap(x+o,y+o, locked);
+ }
+}
+
+/********************************************************************/
+
+MouseIcon::MouseIcon (KInstance *instance, QWidget *parent, const char *name)
+ : StatusIcon ("", parent, name)
+{
+ this->instance = instance;
+ state = 0;
+ activekey = 0;
+ updateImages ();
+ connect (this, SIGNAL(clicked()), SLOT(clickedSlot()));
+}
+
+MouseIcon::~MouseIcon () {
+}
+
+void MouseIcon::setState (int state) {
+ this->state = state;
+
+ update();
+}
+
+void MouseIcon::setActiveKey (int activekey) {
+ this->activekey = activekey;
+
+ update();
+}
+
+void MouseIcon::resizeEvent( QResizeEvent*e )
+{
+ QWidget::resizeEvent(e);
+ updateImages();
+}
+
+QPixmap loadIcon(KInstance *instance, int size, QColor color, QString name) {
+ KIconLoader *loader = instance->iconLoader();
+ QPixmap result = loader->loadIcon(name, KIcon::NoGroup, size);
+
+ QImage img = result.convertToImage();
+ KIconEffect::colorize(img, color, 1.0);
+ result.convertFromImage (img);
+
+ return result;
+}
+
+void MouseIcon::updateImages () {
+ int size = width()<height() ? width() : height();
+
+ QColor textcolor = KGlobalSettings::textColor();
+ QColor basecolor = KGlobalSettings::baseColor();
+ mouse = loadIcon (instance, size, textcolor, "kbstate_mouse");
+ leftSelected = loadIcon (instance, size, textcolor,
+ "kbstate_mouse_left_selected");
+ middleSelected = loadIcon (instance, size, textcolor,
+ "kbstate_mouse_mid_selected");
+ rightSelected = loadIcon (instance, size, textcolor,
+ "kbstate_mouse_right_selected");
+ leftDot = loadIcon (instance, size, textcolor, "kbstate_mouse_left");
+ middleDot = loadIcon (instance, size, textcolor, "kbstate_mouse_mid");
+ rightDot = loadIcon (instance, size, textcolor, "kbstate_mouse_right");
+ leftDotSelected = loadIcon (instance, size, basecolor,
+ "kbstate_mouse_left");
+ middleDotSelected = loadIcon (instance, size, basecolor,
+ "kbstate_mouse_mid");
+ rightDotSelected = loadIcon (instance, size, basecolor,
+ "kbstate_mouse_right");
+
+ update();
+}
+
+void MouseIcon::drawButton (QPainter *p) {
+ p->drawPixmap(0,0, mouse);
+ if ((state & Button1Mask) != 0)
+ p->drawPixmap(0,0, leftSelected);
+ if ((state & Button2Mask) != 0)
+ p->drawPixmap(0,0, middleSelected);
+ if ((state & Button3Mask) != 0)
+ p->drawPixmap(0,0, rightSelected);
+ switch (activekey) {
+ case 0:
+ break;
+ case 1:
+ if ((state & Button1Mask) != 0)
+ p->drawPixmap(0,0, leftDotSelected);
+ else
+ p->drawPixmap(0,0, leftDot);
+ break;
+ case 2:
+ if ((state & Button2Mask) != 0)
+ p->drawPixmap(0,0, middleDotSelected);
+ else
+ p->drawPixmap(0,0, middleDot);
+ break;
+ case 3:
+ if ((state & Button3Mask) != 0)
+ p->drawPixmap(0,0, rightDotSelected);
+ else
+ p->drawPixmap(0,0, rightDot);
+ break;
+ }
+}
+
+/********************************************************************/
+
+TimeoutIcon::TimeoutIcon (KInstance *instance, const QString &text,
+ const QString &featurename,
+ QWidget *parent, const char *name)
+ : StatusIcon (text, parent, name) {
+ this->instance = instance;
+ this->featurename = featurename;
+ glyth = " ";
+ setImage (featurename);
+ connect (&timer, SIGNAL(timeout()), this, SLOT(timeout()));
+}
+
+TimeoutIcon::~TimeoutIcon () {
+}
+
+void TimeoutIcon::update () {
+ int size = width()<height() ? width() : height();
+ if (pixmap.width() != size)
+ pixmap = instance->iconLoader()->loadIcon(iconname, KIcon::NoGroup, size);
+
+ QImage img = pixmap.convertToImage();
+ KIconEffect::colorize(img, KGlobalSettings::textColor(), 1.0);
+ pixmap.convertFromImage (img);
+
+ image = pixmap;
+ QWidget::update();
+}
+
+void TimeoutIcon::setGlyth (const QString &glyth) {
+ timer.stop();
+ this->glyth = glyth;
+
+ QImage img = pixmap.convertToImage();
+ KIconEffect::colorize(img, KGlobalSettings::textColor(), 1.0);
+ pixmap.convertFromImage (img);
+
+ image = pixmap;
+ update();
+}
+
+void TimeoutIcon::setImage (const QString &name, int timeout) {
+ timer.stop();
+ iconname = name;
+ if (!name.isNull() && !name.isEmpty()) {
+ int size = width()<height() ? width() : height();
+ pixmap = instance->iconLoader()->loadIcon(iconname, KIcon::NoGroup, size);
+
+ QImage img = pixmap.convertToImage();
+ KIconEffect::colorize(img, KGlobalSettings::textColor(), 1.0);
+ pixmap.convertFromImage (img);
+
+ image = pixmap;
+ }
+ update();
+ if (timeout > 0)
+ timer.start (timeout, true);
+}
+
+void TimeoutIcon::timeout () {
+ setGlyth (" ");
+ setImage(featurename);
+}
+
+
+void TimeoutIcon::drawButton (QPainter *p) {
+ QString text = glyth;
+ int count = 1;
+ int factor = 19;
+
+ if (!iconname.isNull() && !iconname.isEmpty())
+ p->drawPixmap(0,0, image);
+ else if (glyth == " ") {
+ text = i18n("a (the first letter in the alphabet)", "a");
+ count = 3;
+ factor = 64;
+ }
+
+ QFont font = KGlobalSettings::generalFont();
+ font.setWeight(QFont::Black);
+ QFontMetrics metrics(font);
+ QRect rect = metrics.boundingRect (text);
+ int size = count*rect.width() > rect.height()
+ ? count*rect.width() : rect.height();
+ if (font.pixelSize() != -1)
+ font.setPixelSize (font.pixelSize()*width()*factor/size/64);
+ else
+ font.setPointSizeFloat (font.pointSizeFloat()*width()*factor/size/64);
+
+ p->setFont (font);
+ if (count == 1) {
+ p->setPen (KGlobalSettings::textColor());
+ p->drawText (0,0, width()/2, height()/2, Qt::AlignCenter, text);
+ }
+ else {
+ QColor t = KGlobalSettings::textColor();
+ QColor b = KGlobalSettings::baseColor();
+ p->setPen (QColor ((2*t.red()+3*b.red())/5,
+ (2*t.green()+3*b.green())/5,
+ (2*t.blue()+3*b.blue())/5));
+ p->drawText (width()/2,0, width()/2, height(), Qt::AlignCenter, text);
+ p->setPen (QColor ((2*t.red()+b.red())/3,
+ (2*t.green()+b.green())/3,
+ (2*t.blue()+b.blue())/3));
+ p->drawText (0,0, width(), height(), Qt::AlignCenter, text);
+ p->setPen (KGlobalSettings::textColor());
+ p->drawText (0,0, width()/2, height(), Qt::AlignCenter, text);
+ }
+}
+
+/********************************************************************/
+
+StatusIcon::StatusIcon (const QString &text, QWidget *parent, const char *name)
+ : QPushButton (text, parent, name) {
+ setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
+}
+
+StatusIcon::~StatusIcon () {
+}
+
+QSize StatusIcon::minimumSizeHint () const {
+ return QSize (0,0);
+}
diff --git a/kbstateapplet/kbstate.h b/kbstateapplet/kbstate.h
new file mode 100644
index 0000000..edcd3dc
--- /dev/null
+++ b/kbstateapplet/kbstate.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2004 Gunnar Schmi Dt <gunnar@schmi-dt.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ */
+
+#ifndef __kbstate_h__
+#define __kbstate_h__
+
+#include <kpanelapplet.h>
+#include <qpushbutton.h>
+#include <qptrlist.h>
+#include <qtimer.h>
+
+extern "C"
+{
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+}
+
+class QLabel;
+class QGridLayout;
+class KPopupMenu;
+
+class StatusIcon : public QPushButton {
+ Q_OBJECT
+public:
+ StatusIcon (const QString &text, QWidget *parent, const char *name=0);
+ ~StatusIcon ();
+
+ QSize minimumSizeHint () const;
+};
+typedef QPtrList<StatusIcon> IconList;
+
+class TimeoutIcon : public StatusIcon {
+ Q_OBJECT
+public:
+ TimeoutIcon (KInstance *instance, const QString &text,
+ const QString &featurename,
+ QWidget *parent, const char *name=0);
+ ~TimeoutIcon ();
+
+ void update ();
+ void setGlyth (const QString &glyth);
+ void setImage (const QString &name, int timeout = 0);
+
+ void drawButton (QPainter *p);
+
+private:
+ QString glyth;
+ QString iconname;
+ QString featurename;
+ QPixmap pixmap;
+ QPixmap image;
+ QTimer timer;
+ KInstance *instance;
+
+private slots:
+ void timeout ();
+};
+
+class KeyIcon : public StatusIcon {
+ Q_OBJECT
+public:
+ KeyIcon (int keyId, KInstance *instance,
+ QWidget *parent, const char *name=0);
+ ~KeyIcon ();
+ void setState (bool latched, bool locked);
+ void drawButton (QPainter *p);
+ void updateImages ();
+
+signals:
+ void stateChangeRequest (KeyIcon *source, bool latched, bool locked);
+
+protected:
+ void resizeEvent(QResizeEvent*);
+
+private slots:
+ void clickedSlot();
+
+private:
+ QPixmap locked;
+ QPixmap latched;
+ QPixmap unlatched;
+ bool isLatched;
+ bool isLocked;
+ bool tristate;
+ int keyId;
+ KInstance *instance;
+};
+
+class MouseIcon : public StatusIcon {
+ Q_OBJECT
+ public:
+ MouseIcon (KInstance *instance, QWidget *parent, const char *name=0);
+ ~MouseIcon ();
+ void setState (int state);
+ void setActiveKey (int activekey);
+ void drawButton (QPainter *p);
+ void updateImages ();
+
+ protected:
+ void resizeEvent(QResizeEvent*);
+
+ private:
+ QPixmap mouse;
+ QPixmap leftSelected;
+ QPixmap middleSelected;
+ QPixmap rightSelected;
+ QPixmap leftDot;
+ QPixmap middleDot;
+ QPixmap rightDot;
+ QPixmap leftDotSelected;
+ QPixmap middleDotSelected;
+ QPixmap rightDotSelected;
+ int state, activekey;
+ KInstance *instance;
+};
+
+class KbStateApplet : public KPanelApplet {
+ Q_OBJECT
+
+public:
+ KbStateApplet(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ ~KbStateApplet();
+
+ int widthForHeight(int height) const;
+ int heightForWidth(int width) const;
+
+protected:
+ void mousePressEvent(QMouseEvent *e);
+ void timerEvent(QTimerEvent*);
+ void resizeEvent(QResizeEvent*);
+ bool x11Event (XEvent *);
+
+public slots:
+ void about();
+ void configureAccessX();
+ void configureMouse();
+ void configureKeyboard();
+ void toggleModifier ();
+ void toggleLockkeys ();
+ void toggleMouse ();
+ void toggleAccessX ();
+ void paletteChanged();
+
+ void toggleFillSpace ();
+
+private slots:
+ void setIconDim (int size);
+ void stateChangeRequest (KeyIcon *source, bool latched, bool locked);
+
+private:
+ void loadConfig();
+ void saveConfig();
+ void layout();
+
+ int xkb_base_event_type;
+
+ KeyIcon *(icons[8]);
+ IconList modifiers;
+ IconList lockkeys;
+ TimeoutIcon *sticky;
+ TimeoutIcon *slow;
+ TimeoutIcon *bounce;
+ MouseIcon *mouse;
+
+ int state;
+ unsigned int accessxFeatures;
+ int size;
+
+ void initMasks();
+
+ void buildPopupMenu();
+ void updateMenu();
+ KPopupMenu *popup;
+ KPopupMenu *sizePopup;
+ KPopupMenu *showPopup;
+ int modifierItem, lockkeysItem, mouseItem, accessxItem;
+ int fillSpaceItem;
+ bool showModifiers, showLockkeys, showMouse, showAccessX;
+ bool fillSpace;
+
+ KInstance *instance;
+ XkbDescPtr xkb;
+};
+
+#endif // __kbstate_h__
diff --git a/kbstateapplet/kbstateapplet.desktop b/kbstateapplet/kbstateapplet.desktop
new file mode 100644
index 0000000..bf5231d
--- /dev/null
+++ b/kbstateapplet/kbstateapplet.desktop
@@ -0,0 +1,101 @@
+[Desktop Entry]
+Type=Plugin
+Name=Keyboard Status Applet
+Name[bg]=Състояние на клавиатурата
+Name[br]=Arloadig stad ar stokellaoueg
+Name[ca]=Applet d'estat del teclat
+Name[cs]=Applet ukazují stav klávesnice
+Name[da]=Tastaturstatus-applet
+Name[de]=Tastaturstatus
+Name[el]=Μικροεφαρμογή κατάστασης πληκτρολογίου
+Name[es]=Aplicación integrada en el panel con el estado del teclado
+Name[et]=Klaviatuuristaatuse aplett
+Name[eu]=Teklatuaren egoeraren applet-a
+Name[fa]=برنامک وضعیت صفحه کلید
+Name[fi]=Näppäimistötilan sovelma
+Name[fr]=Applet d'état du clavier
+Name[ga]=Feidhmchláirín Stádais an Mhéarchláir
+Name[gl]=Applet de Estado do Teclado
+Name[he]=יישומון מצב המקלדת
+Name[hi]=कुंजीपट स्थिति ऐप्लेट
+Name[hu]=Billentyűállapot-jelző
+Name[is]=Lyklaborðsstöðu smáforrit
+Name[it]=Applet per lo stato della tastiera
+Name[ja]=キーボード状態アプレット
+Name[ka]=კლავიატურის სტატუსის აპლეტი
+Name[km]= អាប់ភ្លេត​ស្ថានភាព​ក្ដារ​ចុច
+Name[lt]=Klaviatūros būklės įskiepis
+Name[mk]=Аплет за статус на тастатурата
+Name[ms]=Aplet Status Papan Kekunci
+Name[nb]=Miniprogram for tastaturstatus
+Name[nds]=Tastatuurstatus-Lüttprogramm
+Name[ne]=कुञ्जीपाटी वस्तुस्थिति एप्लेट
+Name[nl]=Toetsenbordstatus-applet
+Name[pa]=ਕੀ-ਬੋਰਡ ਸਥਿਤੀ ਐਪਲਿਟ
+Name[pl]=Aplet stanu klawiatury
+Name[pt]='Applet' de estado do teclado
+Name[pt_BR]=Mini-aplicativo de status do teclado
+Name[ru]=Аплет состояния клавиатуры
+Name[sk]=Applet Stav klávesnice
+Name[sl]=Vstavek za stanje tipkovnice
+Name[sr]=Аплет за статус тастатуре
+Name[sr@Latn]=Aplet za status tastature
+Name[sv]=Miniprogram för tangentbordsstatus
+Name[ta]=விசைப்பலகை நிலை குறுநிரல்
+Name[tg]=Апплети ҳолати радифи ҳарфҳо
+Name[th]=แอพเพล็ตสถานะแป้นพิมพ์
+Name[tr]=Klavye Durum Uygulaması
+Name[uk]=Аплет стану клавіатури
+Name[vi]=Tiểu dụng Trạng thái Bàn phím
+Name[zh_CN]=键盘状态小程序
+Name[zh_TW]=鍵盤狀態小程式
+Comment=Panel applet that shows the state of the modifier keys
+Comment[bg]=Аплет за системния панел, които показва състоянието на клавишите модификатори
+Comment[bs]=Panel applet koji pokazuje stanje modifikatorskih tipaka
+Comment[ca]=Applet del plafó que mostra l'estat de les tecles modificadores
+Comment[cs]=Applet, který zobrazuje stav klávesnice
+Comment[da]=Panelprogram der viser tilstanden for ændringstaster
+Comment[de]=Ein Miniprogramm für die Kontrollleiste, das den Status der Sondertasten anzeigt
+Comment[el]=Μικροεφαρμογή του πίνακα που εμφανίζει την κατάσταση των πλήκτρων τροποποίησης
+Comment[es]=Aplicación integrada en el panel que muestra el estado de las teclas modificadoras
+Comment[et]=Paneeliaplett, mis näitab muuteklahvide olekut
+Comment[eu]=Panelaren applet-ak tekla aldatzaileen egoera erakusten du
+Comment[fa]=برنامک تابلو که وضعیت کلیدهای تغییردهنده را نمایش می‌دهد
+Comment[fi]=Muunnosnäppäinten tilan näyttävä paneelisovelma
+Comment[fr]=Applet du tableau de bord affichant l'état des touches de modifications
+Comment[ga]=Feidhmchláirín painéil a thaispeánann staid na n-eochracha mionathraithe
+Comment[gl]=Applet do painel que mostra o estado das teclas modificadoras
+Comment[hi]=फलक ऐप्लेट जो कि परिवर्धक कुंजियों की स्थिति दिखाता है
+Comment[hu]=Panel-kisalkalmazás a módosítóbillentyűk állapotának kiírásához
+Comment[is]=Spjaldforrit sem sýnir stöðu breytilykla
+Comment[it]=Applet del pannello che mostra lo stato dei tasti modificatori
+Comment[ja]=修飾キーの状態を表示するパネルアプレット
+Comment[ka]=პანელის აპლეტი, რომელიც მოდიფიკატორ კლავიშთა მდგომარეობას ასახავს
+Comment[km]=​អាប់ភ្លេត​បន្ទះ​ដែល​បង្ហាញ​ស្ថានភាព​របស់​គ្រាប់ចុច​កែប្រែ
+Comment[lt]=Pulto įskiepis rodantis klaviatūros modifikuojančiųjų klavišų būseną
+Comment[mk]=Аплет на панелот што ја покажува состојбата на копчињата за менување
+Comment[ms]=Panel aplet yang menayangkan keadaan kekunci pengubah suai
+Comment[nb]=Panel-miniprogram som viser tilstanden for valgtastene
+Comment[nds]=Paneel-Lüttprogramm, dat den Tostand vun de Sünnertasten wiest
+Comment[ne]=परिमार्जक कुञ्जीको वस्तुस्थिति देखाउने प्यानल ऐप्लेट
+Comment[nl]=Een paneelapplet dat de status van de modificatietoetsen weergeeft
+Comment[pa]=ਸੋਧਕ ਸਵਿੱਚਾਂ ਦੀ ਹਾਲਤ ਵੇਖਾਉਣ ਨਾਲ ਤੁਸੀਂ ਪੈਨਲ ਐਪਲਿਟ ਵੇਖ ਸਕਦੇ ਹੋ
+Comment[pl]=Apleta panelu, który pokazuje stan klawiszy modyfikujących
+Comment[pt]='Applet' do painel que mostra o estado das teclas modificadoras
+Comment[pt_BR]=Ícone de painel que mostra o estado das teclas modificadoras
+Comment[ru]=Аплет, показывающий состояния специальных клавиш
+Comment[sk]=Applet panelu, ktorý zobrazí stav modifikačných kláves
+Comment[sl]=Pultni vstavek, ki prikazuje stanje modifikatorskih tipk (modifikatorjev)
+Comment[sr]=Панелни аплет који приказује стање модификаторских тастера
+Comment[sr@Latn]=Panelni aplet koji prikazuje stanje modifikatorskih tastera
+Comment[sv]=Panelminiprogram som visar tillståndet hos väljartangenter
+Comment[ta]=மாற்றி விசைகளின் நிலையைக் காட்டும் ஒரு பலக குறுநிரல்
+Comment[tg]=Апплети нишонмедодаи ҳолати махсуси тугмаҳо
+Comment[th]=ถาดแอพเพล็ตสำหรับแสดงสถานะของปุ่มพิมพ์ร่วม
+Comment[tr]=Değiştirici tuş alanını gösteren bir panel eklentisi
+Comment[uk]=Аплет панелі, який показує стан клавіш-модифікаторів
+Comment[vi]=Tiểu dụng bảng điều khiển hiển thị trạng thái phím bổ trợ
+Comment[zh_CN]=显示修饰键状态的面板小程序
+Comment[zh_TW]=一個顯示鍵盤狀態的面板小程式
+Icon=key_enter
+X-KDE-Library=kbstate_panelapplet
diff --git a/kbstateapplet/kdeexportfix.h b/kbstateapplet/kdeexportfix.h
new file mode 100644
index 0000000..172dd94
--- /dev/null
+++ b/kbstateapplet/kdeexportfix.h
@@ -0,0 +1,22 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ kdelibs < 3.3.2 had a bug in the KDE_EXPORT macro. This file fixes this
+ by undefining it.
+ -------------------
+ Copyright : (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <kdeversion.h>
+#if KDE_VERSION < KDE_MAKE_VERSION (3,3,2)
+#undef KDE_EXPORT
+#define KDE_EXPORT
+#endif
diff --git a/kdeaccessibility.lsm b/kdeaccessibility.lsm
new file mode 100644
index 0000000..76ed03a
--- /dev/null
+++ b/kdeaccessibility.lsm
@@ -0,0 +1,15 @@
+Begin3
+Title: kdeaccessibility
+Version: 3.5.10
+Entered-date: 2008-08-26
+Description: KDE Accessibility Aids:
+ kmag, a screen magnifier,
+ kmousetool, a program for people whom it hurts to click the mouse,
+ and KMouth, a program that allows people who have lost their
+ voice to let their computer speak for them.
+Keywords: KDE accessibility X11 desktop Qt
+Primary-site: http://www.kde.org/download/
+Home-page: http://accessibility.kde.org
+Platforms: Unix, Qt
+Copying-policy: GNU Public License
+End
diff --git a/kmag/AUTHORS b/kmag/AUTHORS
new file mode 100644
index 0000000..c3f200c
--- /dev/null
+++ b/kmag/AUTHORS
@@ -0,0 +1,9 @@
+Rewrite and Current Maintainers :
+Sarang Lakare <sarang@users.sourceforge.net>
+
+Contributors:
+Olaf Schmidt <ojschmidt@kde.org>
+
+Original Author and Idea :
+Michael Forster <forster@fmi.uni-passau.de>
+
diff --git a/kmag/COPYING b/kmag/COPYING
new file mode 100644
index 0000000..ffe677b
--- /dev/null
+++ b/kmag/COPYING
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/kmag/ChangeLog b/kmag/ChangeLog
new file mode 100644
index 0000000..6171356
--- /dev/null
+++ b/kmag/ChangeLog
@@ -0,0 +1,63 @@
+//$Id$
+
+ver 0.8
+-Mouse cursor is now visible
+-Complete reference manual
+-Fit-to-window for zoom view
+-ported to KDE3 (still works under KDE2)
+-Using bitBlt to reduce flicker even more
+-Proper centering of zoomed image
+-Some qt3 specific additions
+-Mouse cursor in printing
+-Smooth mouse movements inside zoom vew (very low CPU consumption)
+-Zero CPU usage when magnifier window is hidden/minimized
+-Using default key shortcuts for various actions
+-Checkbox to show/hide mouse cursor
+-Shortcut key binding configuration
+-Moved to XML GUI
+-New "Settings" menu in the toolbar
+-Toolbar configuration
+
+ver 0.7
+-Printing and compiling for KDE 2.x
+-Saving files to remote locations
+-BUG_FIX:Saved image used to get saved to home directory
+-BUG_FIX:Zoom selection window could go below the bottom edge of the screen
+
+ver 0.6
+-Printing support
+-Saving zoomed image to disk
+-Saving/Restoring settings to/from config file
+-New grab-and-move mode for moving zoom region
+-Magnification with mouse movement
+-Option to always show selected region
+-Ability to change refresh rate
+-Copy zoomed image to clipboard
+-More cleaner/bare minimal GUI
+-Tons of code cleanup
+
+ver 0.5
+-No more garbage when the grab window is taken outside the screen
+-Added a convenient drop down menu to select the zoom factor
+-A new refresh button to start/stop window refresh when needed
+-Added "tooltips" and "What's this" at lots of places
+-New install and install-user scripts for easy installation
+-Tons of code cleanup
+
+ver 0.4
+-No more flickering!
+
+ver 0.3
+-Fixed a slow-refresh bug.. making KMag 100% usable!
+-Made resizing grab window much more easier (esp. for laptops!)
+-GUI improvements.. got rid of sliders.. introduced zoom icons
+-Centered display of magnified contents
+-Now using Kdevelop 1.4b2..
+-Added documentation
+
+ver 0.2
+-First public release for the KDE2 port and rewrite
+-Feature enhancements : Easy moving and resizing of grab-window
+
+ver 0.1
+-First public release for KDE1
diff --git a/kmag/INSTALL b/kmag/INSTALL
new file mode 100644
index 0000000..cde242c
--- /dev/null
+++ b/kmag/INSTALL
@@ -0,0 +1,184 @@
+//$Id$
+
+Simple Install
+==============
+
+Login as root and type ./install-root in the directory to install.
+-or-
+If you do not have root access on the machine, run ./install-user in
+the directory.
+
+If you want to compile the program for KDE3, run ./configure with
+options similar to these:
+
+--prefix=/opt/kde3 --enable-mt --with-qt-dir=/usr/lib/qt3
+
+Then run make and make install (as root).
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 4. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/kmag/Makefile.am b/kmag/Makefile.am
new file mode 100644
index 0000000..29dd1a7
--- /dev/null
+++ b/kmag/Makefile.am
@@ -0,0 +1,40 @@
+bin_PROGRAMS = kmag
+
+## INCLUDES were found outside kdevelop specific part
+
+kmag_SOURCES = kmagzoomview.cpp kmagselrect.cpp kmag.cpp main.cpp
+kmag_LDADD = $(LIB_KDEPRINT)
+
+
+EXTRA_DIST = main.cpp version.h kmag.cpp kmag.h kmagui.rc kmag.desktop lo32-app-kmag.png lo16-app-kmag.png kmagselrect.cpp kmagselrect.h hi16-app-kmag.png kmagzoomview.cpp kmagzoomview.h
+
+uninstall-local:
+ -rm -f $(DESTDIR)$(kde_appsdir)/Applications/kmag.desktop
+
+KDE_ICON = kmag
+
+kmagdir = $(kde_appsdir)/Applications
+kmag_DATA = kmag.desktop
+
+kmagiconsdir = $(kde_datadir)/kmag/icons
+kmagicons_ICON = followmouse hidemouse window
+
+# set the include path for X, qt and KDE
+INCLUDES= $(all_includes)
+
+METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+# the library search path.
+kmag_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+rcdir = $(kde_datadir)/kmag
+rc_DATA = kmagui.rc
+
+messages: rc.cpp
+ LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) $$LIST -o $(podir)/kmag.pot; \
+ fi
+
diff --git a/kmag/README b/kmag/README
new file mode 100644
index 0000000..6ce1143
--- /dev/null
+++ b/kmag/README
@@ -0,0 +1,8 @@
+//$Id$
+
+No README available. A good KDE program should not need a README indeed!!
+Read the INSTALL file for installation tips and software requirements.
+
+In any case, check the web-site
+
+http://kmag.sourceforge.net
diff --git a/kmag/TODO b/kmag/TODO
new file mode 100644
index 0000000..f651880
--- /dev/null
+++ b/kmag/TODO
@@ -0,0 +1,57 @@
+$Id$
+
+Planned features:
+
+Version 1.0:
+- Mouse cursor type configuration
+- Right mouse menu
+- Configuration dialog
+- Translations
+- New Icon
+
+* show cursor
+* Put the toolbar at the bottom by default
+* Documentation
+* KDE3 port
+* Mouse cursor show/hide
+* Toolbar configuration
+* Shortcut configuration
+* Maximizing use of the zoomed image display area
+* zooming control on toolbar
+* on/off rectangle update
+* block "garbage" effect when rectangle is outside screen
+* Add "Pause" button to pause to the current view
+* More cleaner/bare minimal GUI
+* Grab window moving with the mouse
+* Code cleanup
+* New grab-and-move mode for moving zoom area
+* Add grabbing and saving of the currently selected area or zoomed area.
+* Saving of settings across different instances
+* Add printing support
+* Always show selected region
+* Allow setting of refresh rate
+* Copying zoomed image to clipboard on "copy"
+* Saving zoomed image to a remote file (via KIO slaves)
+* Compilable under KDE 2.x
+
+Bug Fixing for 1.0:
+@ When the zoom area is resized, the zoom display shows garbage outside
+ the zoomed region
+- Sometimes the selection window remains on the screen
+ => Use overlay to draw the selection window.
+
+* Zoom selection going out of screen at the bottom edge
+* Saved zoomed image always gets saved in home directory
+
+
+Version 2.0:
+- Show the exact cursor as on screen
+- Advanced view to control everything using spin-boxes
+- Block mirrror-to-mirror efect when zoom rectangle intersect KMag window
+- Different profiles : for vision-impared & regular users.
+
+Key:
+ - : todo
+ * : done
+ @ : done, but not released yet (download via CVS)
+ % : in progress
diff --git a/kmag/hi16-action-followmouse.png b/kmag/hi16-action-followmouse.png
new file mode 100644
index 0000000..b454deb
--- /dev/null
+++ b/kmag/hi16-action-followmouse.png
Binary files differ
diff --git a/kmag/hi16-action-hidemouse.png b/kmag/hi16-action-hidemouse.png
new file mode 100644
index 0000000..04415de
--- /dev/null
+++ b/kmag/hi16-action-hidemouse.png
Binary files differ
diff --git a/kmag/hi16-action-window.png b/kmag/hi16-action-window.png
new file mode 100644
index 0000000..ea02070
--- /dev/null
+++ b/kmag/hi16-action-window.png
Binary files differ
diff --git a/kmag/hi16-app-kmag.png b/kmag/hi16-app-kmag.png
new file mode 100644
index 0000000..3f8e96e
--- /dev/null
+++ b/kmag/hi16-app-kmag.png
Binary files differ
diff --git a/kmag/hi32-app-kmag.png b/kmag/hi32-app-kmag.png
new file mode 100644
index 0000000..bffa05d
--- /dev/null
+++ b/kmag/hi32-app-kmag.png
Binary files differ
diff --git a/kmag/kmag.cpp b/kmag/kmag.cpp
new file mode 100644
index 0000000..f385c13
--- /dev/null
+++ b/kmag/kmag.cpp
@@ -0,0 +1,958 @@
+/***************************************************************************
+ kmag.cpp - description
+ -------------------
+ begin : Mon Feb 12 23:45:41 EST 2001
+ copyright : (C) 2001-2003 by Sarang Lakare
+ email : sarang#users.sourceforge.net
+ copyright : (C) 2003-2004 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// include files for QT
+#include <qdir.h>
+#include <qprinter.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qclipboard.h>
+#include <qdragobject.h>
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+#include <qpopupmenu.h>
+
+#include <kdeversion.h>
+
+// include files for KDE
+#if KDE_VERSION > 300
+#include <kapplication.h>
+#else
+#include <kapp.h>
+#endif // KDE 3.x
+
+#include <kkeydialog.h>
+#include <kinputdialog.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <kmenubar.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kstdaction.h>
+#include <khelpmenu.h>
+#include <kimageio.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <ktempfile.h>
+#include <kpopupmenu.h>
+#include <kedittoolbar.h>
+#include <kwin.h>
+
+#if KDE_VERSION < 220
+#include <qprinter.h>
+#else
+#include <kprinter.h>
+#endif
+
+// application specific includes
+#include "kmag.moc"
+#include "kmagzoomview.h"
+#include "kmagselrect.h"
+
+
+#ifdef KDE_IS_VERSION
+#if KDE_IS_VERSION(3,2,90)
+ #define havesetCheckedState
+#endif
+#endif
+
+KmagApp::KmagApp(QWidget* , const char* name)
+ : KMainWindow(0, name, WStyle_MinMax | WType_TopLevel | WStyle_StaysOnTop | WDestructiveClose | WStyle_ContextHelp),
+ m_defaultMouseCursorType(2)
+{
+ config=kapp->config();
+
+ zoomArrayString << "5:1" << "2:1" << "1:1" << "1:1.5" << "1:2" << "1:3" << "1:4" << "1:5"
+ << "1:6" << "1:7" << "1:8" << "1:12" << "1:16" << "1:20";
+
+ // Is there a better way to initialize a vector array?
+ zoomArray.push_back(0.2); zoomArray.push_back(0.5); zoomArray.push_back(1.0);
+ zoomArray.push_back(1.5); zoomArray.push_back(2.0); zoomArray.push_back(3.0);
+ zoomArray.push_back(4.0); zoomArray.push_back(5.0); zoomArray.push_back(6.0); zoomArray.push_back(7.0);
+ zoomArray.push_back(8.0); zoomArray.push_back(12.0); zoomArray.push_back(16.0); zoomArray.push_back(20.0);
+
+ fpsArrayString << i18n("&Very Low") << i18n("&Low") << i18n("&Medium") << i18n("&High") << i18n("V&ery High");
+
+ fpsArray.push_back(2); // very low
+ fpsArray.push_back(6); // low
+ fpsArray.push_back(10); // medium
+ fpsArray.push_back(15); // high
+ fpsArray.push_back(25); // very high
+
+ rotationArrayString << i18n("&No Rotation (0 Degrees)") << i18n("&Left (90 Degrees)") << i18n("&Upside Down (180 Degrees)") << i18n("&Right (270 Degrees)");
+
+ rotationArray.push_back(0); // no rotation
+ rotationArray.push_back(90); // left
+ rotationArray.push_back(180); // upside down
+ rotationArray.push_back(270); // right
+
+ // call inits to invoke all other construction parts
+ initView();
+ initActions();
+ initConnections();
+
+ // Register all KIO image formats - to be used when saving image.
+ KImageIO::registerFormats();
+
+ // read options from config file
+ readOptions();
+}
+
+/**
+ * Default destructor.
+ */
+KmagApp::~KmagApp()
+{
+ m_zoomView->showSelRect(false);
+}
+
+void KmagApp::initActions()
+{
+ fileNewWindow = new KAction(i18n("New &Window"), "window_new", KStdAccel::openNew(), this,
+ SLOT(slotFileNewWindow()), actionCollection(),"new_window");
+ fileNewWindow->setToolTip(i18n("Open a new KMagnifier window"));
+
+ refreshSwitch = new KAction(i18n("&Stop"), "stop", KStdAccel::reload(), this,
+ SLOT(slotToggleRefresh()), actionCollection(), "start_stop_refresh");
+ refreshSwitch->setToolTip(i18n("Click to stop window refresh"));
+ refreshSwitch->setWhatsThis(i18n("Clicking on this icon will <b>start</b> / <b>stop</b>\
+ updating of the display. Stopping the update will zero the processing power\
+ required (CPU usage)"));
+
+ m_pSnapshot = new KAction(i18n("&Save Snapshot As..."), "ksnapshot", KStdAccel::save(), this,
+ SLOT(saveZoomPixmap()), actionCollection(),"snapshot");
+ m_pSnapshot->setWhatsThis(i18n("Saves the zoomed view to an image file."));
+ m_pSnapshot->setToolTip(i18n("Save image to a file"));
+
+ m_pPrint = KStdAction::print(this, SLOT(slotFilePrint()), actionCollection(), "print");
+ m_pPrint->setWhatsThis(i18n("Click on this button to print the current zoomed view."));
+
+ m_pQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection(), "quit");
+ m_pQuit->setStatusText(i18n("Quits the application"));
+ m_pQuit->setWhatsThis (i18n("Quits the application"));
+
+ m_pCopy = KStdAction::copy(this, SLOT(copyToClipBoard()), actionCollection(), "copy");
+ m_pCopy->setWhatsThis(i18n("Click on this button to copy the current zoomed view to the clipboard which you can paste in other applications."));
+ m_pCopy->setToolTip(i18n("Copy zoomed image to clipboard"));
+
+ m_pShowMenu = new KToggleAction(i18n("Show &Menu"), "showmenu", CTRL+Key_M, this,
+ SLOT(slotShowMenu()), actionCollection(),"show_menu");
+ #ifdef havesetCheckedState
+ m_pShowMenu->setCheckedState(i18n("Hide &Menu"));
+ #endif
+ m_pShowMainToolBar = new KToggleAction(i18n("Show Main &Toolbar"), 0, 0, this,
+ SLOT(slotShowMainToolBar()), actionCollection(),"show_mainToolBar");
+ #ifdef havesetCheckedState
+ m_pShowMainToolBar->setCheckedState(i18n("Hide Main &Toolbar"));
+ #endif
+ m_pShowViewToolBar = new KToggleAction(i18n("Show &View Toolbar"), 0, 0, this,
+ SLOT(slotShowViewToolBar()), actionCollection(),"show_viewToolBar");
+ #ifdef havesetCheckedState
+ m_pShowViewToolBar->setCheckedState(i18n("Hide &View Toolbar"));
+ #endif
+ m_pShowSettingsToolBar = new KToggleAction(i18n("Show &Settings Toolbar"), 0, 0, this,
+ SLOT(slotShowSettingsToolBar()), actionCollection(),"show_settingsToolBar");
+ #ifdef havesetCheckedState
+ m_pShowSettingsToolBar->setCheckedState(i18n("Hide &Settings Toolbar"));
+ #endif
+
+ m_modeFollowMouse = new KRadioAction(i18n("&Follow Mouse Mode"), "followmouse", Key_F1, this,
+ SLOT(slotModeFollowMouse()), actionCollection(), "mode_followmouse");
+ m_modeFollowMouse->setToolTip(i18n("Magnify mouse area into window"));
+ m_modeFollowMouse->setWhatsThis(i18n("In this mode the area around the mouse cursor is shown in a normal window."));
+
+ m_modeSelWin = new KRadioAction(i18n("S&election Window Mode"), "window", Key_F2, this,
+ SLOT(slotModeSelWin()), actionCollection(), "mode_selectionwindow");
+ m_modeSelWin->setToolTip(i18n("Magnify selected area into window"));
+ m_modeSelWin->setWhatsThis(i18n("In this mode a selection window is opened. The selected area is shown in a normal window."));
+
+ m_modeEdgeTop = new KRadioAction(i18n("&Top Screen Edge Mode"), 0, 0, this,
+ SLOT(slotModeEdgeTop()), actionCollection(),"mode_edgetop");
+ m_modeEdgeTop->setToolTip(i18n("Magnify mouse area to top screen edge"));
+ m_modeEdgeTop->setWhatsThis(i18n("In this mode the area around the mouse is magnified to the top screen edge."));
+
+ m_modeEdgeLeft = new KRadioAction(i18n("&Left Screen Edge Mode"), 0, 0, this,
+ SLOT(slotModeEdgeLeft()), actionCollection(),"mode_edgeleft");
+ m_modeEdgeLeft->setToolTip(i18n("Magnify mouse area to left screen edge"));
+ m_modeEdgeLeft->setWhatsThis(i18n("In this mode the area around the mouse is magnified to the left screen edge."));
+
+ m_modeEdgeRight = new KRadioAction(i18n("&Right Screen Edge Mode"), 0, 0, this,
+ SLOT(slotModeEdgeRight()), actionCollection(),"mode_edgeright");
+ m_modeEdgeRight->setToolTip(i18n("Magnify mouse area to right screen edge"));
+ m_modeEdgeRight->setWhatsThis(i18n("In this mode the area around the mouse is magnified to the right screen edge."));
+
+ m_modeEdgeBottom = new KRadioAction(i18n("&Bottom Screen Edge Mode"), 0, 0, this,
+ SLOT(slotModeEdgeBottom()), actionCollection(),"mode_edgebottom");
+ m_modeEdgeBottom->setToolTip(i18n("Magnify mouse area to bottom screen edge"));
+ m_modeEdgeBottom->setWhatsThis(i18n("In this mode the area around the mouse is magnified to the bottom screen edge."));
+
+ m_hideCursor = new KToggleAction(i18n("Hide Mouse &Cursor"), "hidemouse", Key_F4, this,
+ SLOT(slotToggleHideCursor()), actionCollection(), "hidecursor");
+ #ifdef havesetCheckedState
+ m_hideCursor->setCheckedState(i18n("Show Mouse &Cursor"));
+ #endif
+ m_hideCursor->setToolTip(i18n("Hide the mouse cursor"));
+
+ m_pZoomIn = KStdAction::zoomIn(this, SLOT(zoomIn()), actionCollection(), "zoom_in");
+ m_pZoomIn->setWhatsThis(i18n("Click on this button to <b>zoom-in</b> on the selected region."));
+
+ m_pZoomBox = new KSelectAction(i18n("&Zoom"),0,actionCollection(),"zoom");
+ m_pZoomBox->setItems(zoomArrayString);
+ m_pZoomBox->setWhatsThis(i18n("Select the zoom factor."));
+ m_pZoomBox->setToolTip(i18n("Zoom factor"));
+
+ m_pZoomOut = KStdAction::zoomOut(this, SLOT(zoomOut()), actionCollection(), "zoom_out");
+ m_pZoomOut->setWhatsThis(i18n("Click on this button to <b>zoom-out</b> on the selected region."));
+
+ m_pInvert = new KToggleAction(i18n("&Invert Colors"), 0, Key_F6, this,
+ SLOT(slotToggleInvert()), actionCollection(), "invert");
+
+ m_pRotationBox = new KSelectAction(i18n("&Rotation"),0,actionCollection(),"rotation");
+ m_pRotationBox->setItems(rotationArrayString);
+ m_pRotationBox->setWhatsThis(i18n("Select the rotation degree."));
+ m_pRotationBox->setToolTip(i18n("Rotation degree"));
+
+ // KHelpMenu *newHelpMenu = new KHelpMenu(this, KGlobal::instance()->aboutData());
+
+ m_keyConf = KStdAction::keyBindings( this, SLOT( slotConfKeys() ), actionCollection(), "key_conf");
+ m_toolConf = KStdAction::configureToolbars( this, SLOT( slotEditToolbars() ),
+ actionCollection(), "toolbar_conf");
+
+ m_pFPSBox = new KSelectAction(i18n("Re&fresh"),0,actionCollection(),"fps_selector");
+ m_pFPSBox->setItems(fpsArrayString);
+ m_pFPSBox->setWhatsThis(i18n("Select the refresh rate. The higher the rate, the more computing power (CPU) will be needed."));
+ m_pFPSBox->setToolTip(i18n("Refresh rate"));
+
+ createGUI();
+}
+
+void KmagApp::initView()
+{
+ m_zoomView = new KMagZoomView( this, "ZoomView" );
+ m_zoomView->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, m_zoomView->sizePolicy().hasHeightForWidth() ) );
+ m_zoomView->setFrameShape( QFrame::StyledPanel );
+ m_zoomView->setFrameShadow( QFrame::Raised );
+
+ setCentralWidget(m_zoomView);
+}
+
+/**
+ * Initialize all connections.
+ */
+void KmagApp::initConnections()
+{
+ // change in zoom value -> update the view
+ connect(this, SIGNAL(updateZoomValue(float)), m_zoomView, SLOT(setZoom(float)));
+ connect(this, SIGNAL(updateRotationValue(int)), m_zoomView, SLOT(setRotation(int)));
+ connect(this, SIGNAL(updateFPSValue(float)), m_zoomView, SLOT(setRefreshRate(float)));
+
+ // change in zoom index -> update the selector
+ connect(this, SIGNAL(updateZoomIndex(int)), m_pZoomBox, SLOT(setCurrentItem(int)));
+ connect(this, SIGNAL(updateRotationIndex(int)), m_pRotationBox, SLOT(setCurrentItem(int)));
+ connect(this, SIGNAL(updateFPSIndex(int)), m_pFPSBox, SLOT(setCurrentItem(int)));
+
+ // selector selects a zoom index -> set the zoom index
+ connect(m_pZoomBox, SIGNAL(activated(int)), this, SLOT(setZoomIndex(int)));
+ connect(m_pRotationBox, SIGNAL(activated(int)), this, SLOT(setRotationIndex(int)));
+ connect(m_pFPSBox, SIGNAL(activated(int)), this, SLOT(setFPSIndex(int)));
+
+ connect(m_zoomView, SIGNAL(contextMenu(QPoint)), this, SLOT(contextMenu(QPoint)));
+}
+
+/**
+ * Save options to config file.
+ */
+void KmagApp::saveOptions()
+{
+ config->setGroup("General Options");
+ config->writeEntry("Geometry", size());
+ config->writeEntry("ZoomIndex", m_zoomIndex);
+ config->writeEntry("Invertation", m_pInvert->isChecked());
+ config->writeEntry("RotationIndex", m_rotationIndex);
+ config->writeEntry("FPSIndex", m_fpsIndex);
+ config->writeEntry("SelRect", m_zoomView->getSelRectPos());
+ config->writeEntry("ShowMouse", m_zoomView->getShowMouseType());
+
+ if (m_modeFollowMouse->isChecked())
+ config->writeEntry("Mode", "followmouse");
+ else if (m_modeSelWin->isChecked())
+ config->writeEntry("Mode", "selectionwindow");
+ else if (m_modeEdgeTop->isChecked())
+ config->writeEntry("Mode", "edgetop");
+ else if (m_modeEdgeLeft->isChecked())
+ config->writeEntry("Mode", "edgeleft");
+ else if (m_modeEdgeRight->isChecked())
+ config->writeEntry("Mode", "edgeright");
+ else if (m_modeEdgeBottom->isChecked())
+ config->writeEntry("Mode", "edgebottom");
+
+ config->writeEntry ("EdgeSize", edgesize);
+
+ config->writeEntry("ShowMenu", m_pShowMenu->isChecked());
+ config->writeEntry("ShowMainToolBar", m_pShowMainToolBar->isChecked());
+ config->writeEntry("ShowViewToolBar", m_pShowViewToolBar->isChecked());
+ config->writeEntry("ShowSettingsToolBar", m_pShowSettingsToolBar->isChecked());
+
+ toolBar("mainToolBar")->saveSettings(config,"Main ToolBar");
+ toolBar("viewToolBar")->saveSettings(config,"View ToolBar");
+ toolBar("settingsToolBar")->saveSettings(config,"Settings ToolBar");
+}
+
+
+/**
+ * Read settings from config file.
+ */
+void KmagApp::readOptions()
+{
+ QColor blue (0,0,128);
+ QColor yellow (255,255,0);
+ QColor white (255,255,255);
+
+ config->setGroup ("WM");
+ setTitleColors (
+ config->readColorEntry("inactiveBackground", &blue),
+ config->readColorEntry("inactiveForeground", &white),
+ config->readColorEntry("inactiveTitleBtnBg", &yellow));
+
+ config->setGroup("General Options");
+
+ QSize defSize(460,390);
+ QSize size=config->readSizeEntry("Geometry", &defSize);
+ if(!size.isEmpty())
+ {
+ resize(size);
+ }
+
+ // set zoom - defaults to 2x
+ unsigned int zoomIndex = config->readUnsignedNumEntry("ZoomIndex", 4);
+ setZoomIndex(zoomIndex);
+ emit updateZoomIndex(m_zoomIndex);
+
+ m_pInvert->setChecked (config->readBoolEntry("Invertation", false));
+ slotToggleInvert();
+
+ unsigned int rotationIndex = config->readUnsignedNumEntry("RotationIndex", 0);
+ setRotationIndex(rotationIndex);
+ emit updateRotationIndex(m_rotationIndex);
+
+ unsigned int fpsIndex = config->readUnsignedNumEntry("FPSIndex", 2);
+ setFPSIndex(fpsIndex);
+ emit updateFPSIndex(m_fpsIndex);
+
+ QRect defaultRect(0,0,211,164);
+ m_zoomView->setSelRectPos(config->readRectEntry("SelRect", &defaultRect));
+
+ m_mouseCursorType = config->readUnsignedNumEntry("ShowMouse", m_defaultMouseCursorType);
+ m_zoomView->showMouse(m_mouseCursorType);
+ if(m_mouseCursorType)
+ m_hideCursor->setChecked(false);
+ else
+ m_hideCursor->setChecked(true);
+
+ if(config->hasGroup("Settings ToolBar"))
+ toolBar("settingsToolBar")->applySettings(config,"Settings ToolBar");
+
+ if(config->hasGroup("Main ToolBar"))
+ toolBar("mainToolBar")->applySettings(config,"Main ToolBar");
+
+ if(config->hasGroup("View ToolBar"))
+ toolBar("viewToolBar")->applySettings(config,"View ToolBar");
+
+ m_pShowMenu->setChecked(config->readBoolEntry("ShowMenu", true));
+ slotShowMenu();
+
+ m_pShowMainToolBar->setChecked(config->readBoolEntry("ShowMainToolBar", false));
+ slotShowMainToolBar();
+
+ m_pShowViewToolBar->setChecked(config->readBoolEntry("ShowViewToolBar", true));
+ slotShowViewToolBar();
+
+ m_pShowSettingsToolBar->setChecked(config->readBoolEntry("ShowSettingsToolBar", true));
+ slotShowSettingsToolBar();
+
+ config->setGroup("General Options");
+
+ edgesize = config->readNumEntry("EdgeSize", 0);
+ QString mode = config->readEntry("Mode", "followmouse");
+ if (mode == "selectionwindow")
+ slotModeSelWin();
+ else if (mode == "edgetop")
+ setEdgeMode (m_modeEdgeTop);
+ else if (mode == "edgeleft")
+ setEdgeMode (m_modeEdgeLeft);
+ else if (mode == "edgeright")
+ setEdgeMode (m_modeEdgeRight);
+ else if (mode == "edgebottom")
+ setEdgeMode (m_modeEdgeBottom);
+ else
+ slotModeFollowMouse();
+}
+
+bool KmagApp::queryClose()
+{
+ return (true);
+}
+
+bool KmagApp::queryExit()
+{
+ saveOptions();
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// SLOT IMPLEMENTATION
+/////////////////////////////////////////////////////////////////////
+
+/**
+ * Shows/hides the mouse cursor
+ */
+void KmagApp::showMouseCursor(bool show)
+{
+ if(show) {
+ if(m_mouseCursorType == 0)
+ m_mouseCursorType = m_defaultMouseCursorType;
+ m_zoomView->showMouse(m_mouseCursorType);
+ } else {
+ m_zoomView->showMouse(0);
+ }
+}
+
+/**
+ * Zoom in.
+ */
+void KmagApp::zoomIn()
+{
+ // set the new index .. checking will done inside setZoom
+ setZoomIndex(m_zoomIndex+1);
+ // signal change in zoom index
+ emit updateZoomIndex((int)m_zoomIndex);
+}
+
+/**
+ * Zoom out.
+ */
+void KmagApp::zoomOut()
+{
+ // set the new index .. checking will done inside setZoom
+ setZoomIndex(m_zoomIndex-1);
+ // signal change in zoom index
+ emit updateZoomIndex((int)m_zoomIndex);
+}
+/**
+ * Sets the zoom index to index
+ */
+void KmagApp::setZoomIndex(int index)
+{
+ if(index < 0 || index >= (int)zoomArray.size()) {
+ // the index is invalid
+ kdWarning() << "Invalid index!" << endl;
+ return;
+ } else if((int)m_zoomIndex == index) {
+ // do nothing!
+ return;
+ } else {
+ m_zoomIndex = index;
+ }
+
+ if(m_zoomIndex == 0) {
+ // meaning that no more zooming-out is possible
+ // -> disable zoom-out icon
+ m_pZoomOut->setEnabled(false);
+ } else { // enable the icon
+ m_pZoomOut->setEnabled(true);
+ }
+
+ if(m_zoomIndex == zoomArray.size()-1) {
+ // meaning that no more zooming-in is possible
+ // -> disable zoom-in icon
+ m_pZoomIn->setEnabled(false);
+ } else { // enable the icon
+ m_pZoomIn->setEnabled(true);
+ }
+
+ // signal change in zoom value
+ emit updateZoomValue(zoomArray[m_zoomIndex]);
+}
+
+/**
+ * Shows/hides the mouse cursor
+ */
+void KmagApp::slotToggleInvert ()
+{
+ m_zoomView->setInvertation (m_pInvert->isChecked());
+}
+
+/**
+ * Sets the rotation index to index
+ */
+void KmagApp::setRotationIndex(int index)
+{
+ if(index < 0 || index >= (int)rotationArray.size()) {
+ // the index is invalid
+ kdWarning() << "Invalid index!" << endl;
+ return;
+ } else if((int)m_rotationIndex == index) {
+ // do nothing!
+ return;
+ } else {
+ m_rotationIndex = index;
+ }
+
+ // signal change in zoom value
+ emit updateRotationValue(rotationArray[m_rotationIndex]);
+}
+
+/**
+ * Sets the fps index to index
+ */
+void KmagApp::setFPSIndex(int index)
+{
+ if(index < 0 || index >= (int)fpsArray.size()) {
+ // the index is invalid
+ kdWarning() << "Invalid index!" << endl;
+ return;
+ } else if((int)m_fpsIndex == index) {
+ // do nothing!
+ return;
+ } else {
+ m_fpsIndex = index;
+ }
+
+ // signal change in fps value
+ emit updateFPSValue(fpsArray[m_fpsIndex]);
+}
+
+
+/**
+ * Save the zoomed image
+ */
+void KmagApp::saveZoomPixmap()
+{
+ bool toggled(false);
+
+ // stop refresh temporarily
+ if (m_zoomView->getRefreshStatus()) {
+ slotToggleRefresh();
+ toggled = true;
+ }
+
+ KURL url = KFileDialog::getSaveURL(QString::null,
+ KImageIO::pattern(KImageIO::Writing),
+ 0,i18n("Save Snapshot As"));
+
+ if(!url.filename().isEmpty()) {
+ if(!url.isLocalFile()) {
+ // create a temp file.. save image to it.. copy over the n/w and then delete the temp file.
+ KTempFile tempFile;
+ if(!m_zoomView->getPixmap().save(tempFile.name(), KImageIO::type(url.fileName()).latin1())) {
+ KMessageBox::error(0, i18n("Unable to save temporary file (before uploading to the network file you specified)."),
+ i18n("Error Writing File"));
+ } else {
+ if(!KIO::NetAccess::upload(tempFile.name(), url, this)) {
+ KMessageBox::error(0, i18n("Unable to upload file over the network."),
+ i18n("Error Writing File"));
+ } else {
+ KMessageBox::information(0, i18n("Current zoomed image saved to\n%1").arg(url.prettyURL()),
+ i18n("Information"), "save_confirm");
+ }
+ }
+ // remove the temporary file
+ tempFile.unlink();
+
+ } else {
+ if(!m_zoomView->getPixmap().save(url.path(), KImageIO::type(url.fileName()).latin1())) {
+ KMessageBox::error(0, i18n("Unable to save file. Please check if you have permission to write to the directory."),
+ i18n("Error Writing File"));
+ } else {
+ KMessageBox::information(0, i18n("Current zoomed image saved to\n%1").arg(url.prettyURL()),
+ i18n("Information"), "save_confirm");
+ }
+ }
+ }
+ if(toggled) {
+ slotToggleRefresh();
+ }
+}
+
+
+void KmagApp::slotToggleRefresh()
+{
+ m_zoomView->toggleRefresh();
+ if(m_zoomView->getRefreshStatus()) {
+ refreshSwitch->setIcon("stop.png");
+ refreshSwitch->setText(i18n("Stop"));
+ refreshSwitch->setToolTip(i18n("Click to stop window update"));
+ } else {
+ refreshSwitch->setIcon("reload.png");
+ refreshSwitch->setText(i18n("Start"));
+ refreshSwitch->setToolTip(i18n("Click to start window update"));
+ }
+}
+
+
+void KmagApp::slotModeSelWin()
+{
+ unsetEdgeMode(m_modeSelWin);
+
+ m_zoomView->fitToWindow();
+ m_zoomView->setFitToWindow (false);
+ m_zoomView->followMouse(false);
+ m_zoomView->showSelRect(true);
+}
+
+
+void KmagApp::slotModeFollowMouse()
+{
+ unsetEdgeMode(m_modeFollowMouse);
+
+ m_zoomView->setFitToWindow (true);
+ m_zoomView->followMouse(true);
+ m_zoomView->showSelRect(false);
+}
+
+
+void KmagApp::slotModeEdgeTop()
+{
+ // ask for edgesize
+ int newedgesize; bool ok;
+ newedgesize = KInputDialog::getInteger (i18n ("Magnify to Screen Edge - Select Size"),
+ i18n ("Size:"), edgesize > 0 ? edgesize : 300, 200,
+ QApplication::desktop()->screenGeometry( this ).height()/2,
+ 25, 10, &ok, 0, "getedgesize");
+
+ if (ok) {
+ edgesize = newedgesize;
+ setEdgeMode(m_modeEdgeTop);
+ }
+}
+
+
+void KmagApp::slotModeEdgeLeft()
+{
+ // ask for edgesize
+ int newedgesize; bool ok;
+ newedgesize = KInputDialog::getInteger (i18n ("Magnify to Left Screen Edge - Select Size"),
+ i18n ("Size:"), edgesize > 0 ? edgesize : 300, 200,
+ QApplication::desktop()->screenGeometry( this ).width()/2,
+ 25, 10, &ok, 0, "getedgesize");
+
+ if (ok) {
+ edgesize = newedgesize;
+ setEdgeMode(m_modeEdgeLeft);
+ }
+}
+
+
+void KmagApp::slotModeEdgeRight()
+{
+ // ask for edgesize
+ int newedgesize; bool ok;
+ newedgesize = KInputDialog::getInteger (i18n ("Magnify to Right Screen Edge - Select Size"),
+ i18n ("Size:"), edgesize > 0 ? edgesize : 300, 200,
+ QApplication::desktop()->screenGeometry( this ).width()/2,
+ 25, 10, &ok, 0, "getedgesize");
+
+ if (ok) {
+ edgesize = newedgesize;
+ setEdgeMode(m_modeEdgeRight);
+ }
+}
+
+
+void KmagApp::slotModeEdgeBottom()
+{
+ // ask for edgesize
+ int newedgesize; bool ok;
+ newedgesize = KInputDialog::getInteger (i18n ("Magnify to Bottom Screen Edge - Select Size"),
+ i18n ("Size:"), edgesize > 0 ? edgesize : 300, 200,
+ QApplication::desktop()->screenGeometry( this ).height()/2,
+ 25, 10, &ok, 0, "getedgesize");
+
+ if (ok) {
+ edgesize = newedgesize;
+ setEdgeMode(m_modeEdgeBottom);
+ }
+}
+
+
+void KmagApp::setEdgeMode (KToggleAction *mode)
+{
+ if (m_modeEdgeLeft || mode == m_modeEdgeRight) {
+ if (edgesize < 200 || edgesize > QApplication::desktop()->screenGeometry( this ).width()/2)
+ edgesize = QApplication::desktop()->screenGeometry( this ).width()/4;
+ } else {
+ if (edgesize < 200 || edgesize > QApplication::desktop()->screenGeometry( this ).height()/2)
+ edgesize = QApplication::desktop()->screenGeometry( this ).height()/4;
+ }
+
+ m_modeFollowMouse->setChecked(false);
+ m_modeSelWin->setChecked(false);
+ m_modeEdgeTop->setChecked(false);
+ m_modeEdgeLeft->setChecked(false);
+ m_modeEdgeRight->setChecked(false);
+ m_modeEdgeBottom->setChecked(false);
+ mode->setChecked (true);
+
+ m_zoomView->setFitToWindow (true);
+ m_zoomView->followMouse(true);
+ m_zoomView->showSelRect(false);
+
+ m_zoomView->reparent (0, QPoint(), false);
+ KWin::setType(m_zoomView->winId(), NET::Dock);
+ KWin::setState(m_zoomView->winId(), NET::Sticky | NET::KeepBelow | NET::SkipTaskbar | NET::SkipPager);
+ KWin::setOnAllDesktops(m_zoomView->winId(), true);
+
+ m_pShowMenu->setEnabled (false);
+ m_pShowMainToolBar->setEnabled (false);
+ m_pShowViewToolBar->setEnabled (false);
+ m_pShowSettingsToolBar->setEnabled (false);
+
+ hide();
+
+ if (mode == m_modeEdgeTop) {
+ QRect r = QApplication::desktop()->screenGeometry( this );
+ r.setBottom( r.top() + edgesize );
+ m_zoomView->setGeometry ( r );
+ KWin::setExtendedStrut (m_zoomView->winId(), 0, 0, 0, 0, 0, 0,
+ edgesize, r.left(), r.right(), 0, 0, 0);
+ } else if (mode == m_modeEdgeLeft) {
+ QRect r = QApplication::desktop()->screenGeometry( this );
+ r.setRight( r.left() + edgesize );
+ m_zoomView->setGeometry ( r );
+ KWin::setExtendedStrut (m_zoomView->winId(),
+ edgesize, r.top(), r.bottom(),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ } else if (mode == m_modeEdgeRight) {
+ QRect r = QApplication::desktop()->screenGeometry( this );
+ r.setLeft( r.right() - edgesize );
+ m_zoomView->setGeometry ( r );
+ KWin::setExtendedStrut (m_zoomView->winId(), 0, 0, 0,
+ edgesize, r.top(), r.bottom(),
+ 0, 0, 0, 0, 0, 0);
+ } else {
+ QRect r = QApplication::desktop()->screenGeometry( this );
+ r.setTop( r.bottom() - edgesize );
+ m_zoomView->setGeometry ( r );
+ KWin::setExtendedStrut (m_zoomView->winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ edgesize, r.left(), r.right());
+ }
+ m_zoomView->show();
+}
+
+
+void KmagApp::unsetEdgeMode (KToggleAction *mode)
+{
+ edgesize = 0;
+
+ m_modeFollowMouse->setChecked(false);
+ m_modeSelWin->setChecked(false);
+ m_modeEdgeTop->setChecked(false);
+ m_modeEdgeLeft->setChecked(false);
+ m_modeEdgeRight->setChecked(false);
+ m_modeEdgeBottom->setChecked(false);
+ mode->setChecked (true);
+
+ m_zoomView->reparent (this, QPoint(), true);
+ setCentralWidget(m_zoomView);
+ KWin::setExtendedStrut (winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ m_pShowMenu->setEnabled (true);
+ m_pShowMainToolBar->setEnabled (true);
+ m_pShowViewToolBar->setEnabled (true);
+ m_pShowSettingsToolBar->setEnabled (true);
+
+ show();
+}
+
+
+void KmagApp::slotToggleHideCursor()
+{
+ showMouseCursor(!m_hideCursor->isChecked());
+}
+
+
+void KmagApp::slotFileNewWindow()
+{
+ KmagApp *new_window= new KmagApp();
+ new_window->show();
+}
+
+
+void KmagApp::slotFilePrint()
+{
+#ifndef QT_NO_PRINTER
+
+ bool toggled(false);
+
+#if KDE_VERSION < 220
+ QPrinter printer;
+#else
+ KPrinter printer;
+#endif
+
+ // stop refresh temporarily
+ if (m_zoomView->getRefreshStatus()) {
+ slotToggleRefresh();
+ toggled = true;
+ }
+
+ const QPixmap pixmap(m_zoomView->getPixmap());
+
+#if KDE_VERSION >= 220
+ // use some AI to get the best orientation
+ if(pixmap.width() > pixmap.height()) {
+ printer.setOrientation(KPrinter::Landscape);
+ } else {
+ printer.setOrientation(KPrinter::Portrait);
+ }
+#endif
+
+ if (printer.setup(this)) {
+ QPainter paint;
+
+ if(!paint.begin(&printer))
+ return;
+ // draw the pixmap
+ paint.drawPixmap(0, 0, pixmap);
+ // end the painting
+ paint.end();
+ }
+
+ if(toggled) {
+ slotToggleRefresh();
+ }
+#endif // QT_NO_PRINTER
+}
+
+void KmagApp::slotFileQuit()
+{
+ saveOptions();
+ // close the first window, the list makes the next one the first again.
+ // This ensures that queryClose() is called on each window to ask for closing
+ KMainWindow* w;
+ if (memberList)
+ {
+ for(w=memberList->first(); w!=0; w=memberList->first())
+ {
+ // only close the window if the closeEvent is accepted. If the user presses Cancel on the saveModified() dialog,
+ // the window and the application stay open.
+ if(!w->close())
+ break;
+ memberList->removeRef(w);
+ }
+ }
+}
+
+void KmagApp::copyToClipBoard()
+{
+ QClipboard *cb=KApplication::clipboard();
+ cb->setPixmap(m_zoomView->getPixmap());
+}
+
+void KmagApp::slotShowMenu()
+{
+ ///////////////////////////////////////////////////////////////////
+ // turn Menu on or off
+ if(!m_pShowMenu->isChecked())
+ {
+ menuBar()->hide();
+ }
+ else
+ {
+ menuBar()->show();
+ }
+
+
+}
+
+void KmagApp::slotShowMainToolBar()
+{
+ ///////////////////////////////////////////////////////////////////
+ // turn mainToolbar on or off
+ if(!m_pShowMainToolBar->isChecked())
+ {
+ toolBar("mainToolBar")->hide();
+ }
+ else
+ {
+ toolBar("mainToolBar")->show();
+ }
+}
+
+void KmagApp::slotShowViewToolBar()
+{
+ ///////////////////////////////////////////////////////////////////
+ // turn viewToolbar on or off
+ if(!m_pShowViewToolBar->isChecked())
+ {
+ toolBar("viewToolBar")->hide();
+ }
+ else
+ {
+ toolBar("viewToolBar")->show();
+ }
+}
+
+void KmagApp::slotShowSettingsToolBar()
+{
+ ///////////////////////////////////////////////////////////////////
+ // turn viewToolbar on or off
+ if(!m_pShowSettingsToolBar->isChecked() || edgesize > 0)
+ {
+ toolBar("settingsToolBar")->hide();
+ }
+ else
+ {
+ toolBar("settingsToolBar")->show();
+ }
+}
+
+void KmagApp::slotConfKeys()
+{
+ KKeyDialog::configure( actionCollection() );
+}
+
+void KmagApp::slotEditToolbars()
+{
+ saveMainWindowSettings( KGlobal::config(), "MainWindow" );
+ KEditToolbar dlg( actionCollection() );
+ connect( &dlg, SIGNAL( newToolbarConfig() ), this, SLOT( slotNewToolbarConfig() ) );
+ if ( dlg.exec() )
+ createGUI();
+}
+
+
+void KmagApp::contextMenu (QPoint pos)
+{
+ // show popup
+ KXMLGUIFactory *factory = this->factory();
+ QPopupMenu *popup = (QPopupMenu *)factory->container("mainPopUp",this);
+ if (popup != 0)
+ popup->popup(pos, 0);
+}
+
+
+void KmagApp::slotNewToolbarConfig()
+{
+ applyMainWindowSettings( KGlobal::config(), "MainWindow" );
+ createGUI();
+}
diff --git a/kmag/kmag.desktop b/kmag/kmag.desktop
new file mode 100644
index 0000000..703101f
--- /dev/null
+++ b/kmag/kmag.desktop
@@ -0,0 +1,76 @@
+# KDE Config File
+[Desktop Entry]
+Type=Application
+Exec=kmag -caption "%c" %i %m
+Icon=kmag
+DocPath=kmag/index.html
+Comment=
+Comment[ro]=Un utilitar de mărit zone ale ecranului
+Terminal=false
+Name=KMag
+Name[el]=K μεγεθυντικός φακός
+Name[ne]=केडीई म्याग
+Name[sk]=KLupa
+Name[sv]=Kmag
+Name[tg]=KMag
+Name[th]=แว่นขยาย - K
+Name[tr]=Kmag
+Name[vi]=Kính lúp K
+Name[zh_TW]=K-放大鏡
+GenericName=Screen Magnifier
+GenericName[ar]=مكبَر الشاشة
+GenericName[bg]=Лупа за екрана
+GenericName[bs]=Povećalo za ekran
+GenericName[ca]=Lupa de la pantalla
+GenericName[cs]=Lupa obrazovky
+GenericName[cy]=KChwyddwr
+GenericName[da]=Skærmforstørrer
+GenericName[de]=Bildschirmlupe
+GenericName[el]=Μεγεθυντικός φακός οθόνης
+GenericName[eo]=Ekrano-pligrandigilo
+GenericName[es]=Aumenta la pantalla
+GenericName[et]=Ekraani suurendaja
+GenericName[eu]=Pantailaren lupa
+GenericName[fa]=درشت‌نمای پرده
+GenericName[fi]=Suurennuslasi
+GenericName[fr]=Loupe d'écran
+GenericName[ga]=Formhéadaitheoir Scáileáin
+GenericName[gl]=Ampliación da pantalla
+GenericName[he]=זכוכית מגדלת
+GenericName[hi]=स्क्रीन का आकार बढ़ाने वाला
+GenericName[hu]=Nagyító
+GenericName[is]=Skjástækkunargler
+GenericName[it]=Lente di ingrandimento per lo schermo
+GenericName[ja]=画面拡大鏡
+GenericName[ka]=ეკრანის გამდიდებელი
+GenericName[km]= កម្មវិធី​ពង្រីក​អេក្រង់​
+GenericName[lt]=Ekrano didintojas
+GenericName[mk]=Зголемувач за екранот
+GenericName[ms]=Pembesar Skrin
+GenericName[nb]=Skjermforstørrer
+GenericName[nds]=Schirmluup
+GenericName[ne]=पर्दा अभिवर्धक
+GenericName[nl]=Schermvergroter
+GenericName[nn]=Skjermforstørrar
+GenericName[pa]=ਪਰਦਾ ਵੱਡਦਰਸ਼ੀ
+GenericName[pl]=Powiększanie fragmentów ekranu
+GenericName[pt]=Lupa
+GenericName[pt_BR]=Amplificador de Tela
+GenericName[ro]=Lupă de ecran
+GenericName[ru]=Экранная лупа
+GenericName[sk]=Lupa obrazovky
+GenericName[sl]=Povečevalnik zaslona
+GenericName[sr]=Екрански увеличавач
+GenericName[sr@Latn]=Ekranski uveličavač
+GenericName[sv]=Förstoringsglas
+GenericName[ta]=திரை பெரிதாக்கி
+GenericName[tg]=Калон кардани экран
+GenericName[th]=แว่นขยายหน้าจอ
+GenericName[tr]=Ekran Büyüteci
+GenericName[uk]=Збільшувач екрана
+GenericName[uz]=Ekranni kattalashtiruvchi
+GenericName[uz@cyrillic]=Экранни катталаштирувчи
+GenericName[vi]=Kính lúp Màn hình
+GenericName[zh_CN]=屏幕放大镜
+GenericName[zh_TW]=螢幕放大鏡
+Categories=Qt;KDE;Utility;Accessibility;
diff --git a/kmag/kmag.h b/kmag/kmag.h
new file mode 100644
index 0000000..bfd2e31
--- /dev/null
+++ b/kmag/kmag.h
@@ -0,0 +1,237 @@
+/***************************************************************************
+ kmag.h - description
+ -------------------
+ begin : Mon Feb 12 23:45:41 EST 2001
+ copyright : (C) 2001 by Sarang Lakare
+ email : sarang@users.sourceforge.net
+ copyright : (C) 2003-2004 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KMAG_H
+#define KMAG_H
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "kmagzoomview.h"
+
+#include <vector>
+// include files for Qt
+#include <qstringlist.h>
+
+// include files for KDE
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <kdockwidget.h>
+#include <kaction.h>
+#include <kaccel.h>
+#include <knuminput.h>
+
+/**
+ * The base class for Kmag application windows. It sets up the main
+ * window and reads the config file as well as providing a menubar, toolbar
+ * and statusbar. An instance of KmagView creates your center view, which is connected
+ * to the window's Doc object.
+ * KmagApp reimplements the methods that KMainWindow provides for main window handling and supports
+ * full session management as well as using KActions.
+ * @see KMainWindow
+ * @see KApplication
+ * @see KConfig
+ *
+ * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team.
+ * @version KDevelop version 1.2 code generation
+ */
+class KmagApp : public KMainWindow
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Construtor of KmagApp, calls all init functions to create the application.
+ */
+ KmagApp(QWidget* parent=0, const char* name=0);
+
+ /// Default destructor
+ ~KmagApp();
+
+
+
+ protected:
+ /** save general Options like all bar positions and status as well as the geometry and the recent file list to the configuration
+ * file
+ */
+ void saveOptions();
+ /** read general Options again and initialize all variables like the recent file list
+ */
+ void readOptions();
+ /** initializes the KActions of the application */
+ void initActions();
+
+ /** creates the centerwidget of the KTMainWindow instance and sets it as the view
+ */
+ void initView();
+
+ /// Initialize all connections
+ void initConnections();
+
+ virtual bool queryClose();
+
+ /** queryExit is called by KTMainWindow when the last window of the application is going to be closed during the closeEvent().
+ * Against the default implementation that just returns true, this calls saveOptions() to save the settings of the last window's
+ * properties.
+ * @see KTMainWindow#queryExit
+ * @see KTMainWindow#closeEvent
+ */
+ virtual bool queryExit();
+
+ public slots:
+ /** open a new application window by creating a new instance of KmagApp */
+ void slotFileNewWindow();
+
+ /** print the actual file */
+ void slotFilePrint();
+
+ void slotFileQuit();
+
+ /** put the marked text/object into the clipboard
+ */
+ void copyToClipBoard();
+
+ /// Toggle the refreshing of the window
+ void slotToggleRefresh();
+
+ void slotModeFollowMouse();
+ void slotModeSelWin();
+ void slotModeEdgeTop();
+ void slotModeEdgeLeft();
+ void slotModeEdgeRight();
+ void slotModeEdgeBottom();
+
+ /// Zooms in
+ void zoomIn();
+
+ /// Zooms out
+ void zoomOut();
+
+ /// Save the zoomed image
+ void saveZoomPixmap();
+
+ /// Sets the zoom index to index
+ void setZoomIndex(int index);
+
+ /// Sets the invertation mode
+ void slotToggleInvert();
+
+ /// Sets the rotation index to index
+ void setRotationIndex(int index);
+
+ /// Sets the fps index to index
+ void setFPSIndex(int index);
+
+ /// Shows/hides the mouse cursor
+ void showMouseCursor(bool show);
+
+ void slotShowMenu();
+ void slotShowMainToolBar();
+ void slotShowViewToolBar();
+ void slotShowSettingsToolBar();
+
+ void slotToggleHideCursor();
+
+ /// Opens shortcut key configuration dialogue
+ void slotConfKeys();
+
+ /// Called when toolbar config is updated
+ void slotNewToolbarConfig();
+
+ /// Called when "configure toolbar" is clicked
+ void slotEditToolbars();
+
+ void contextMenu(QPoint pos);
+
+ signals:
+ /// This signal is raised whenever the index into the zoom array is changed
+ void updateZoomIndex(int);
+
+ /// This signal is raised whenever the zoom value changes
+ void updateZoomValue(float);
+
+ /// This signal is raised whenever the index into the rotation array is changed
+ void updateRotationIndex(int);
+
+ /// This signal is raised whenever the rotation value changes
+ void updateRotationValue(int);
+
+ /// This signal is raised whenever the index into the fps array is changed
+ void updateFPSIndex(int);
+
+ /// This signal is raised whenever the fps value changes
+ void updateFPSValue(float);
+
+ private:
+
+ void setEdgeMode (KToggleAction *mode);
+ void unsetEdgeMode (KToggleAction *mode);
+
+ int edgesize;
+
+ /// the configuration object of the application
+ KConfig *config;
+
+ // KAction pointers to enable/disable actions
+ KAction *fileNewWindow, *m_pSnapshot, *m_pCopy, *m_keyConf, *m_toolConf;
+ KAction *m_pPrint;
+ KAction *m_pZoomIn;
+ KAction *m_pZoomOut;
+ KAction *m_pQuit;
+ KAction *refreshSwitch;
+ KToggleAction *m_pInvert, *m_pShowMenu, *m_pShowMainToolBar, *m_pShowViewToolBar, *m_pShowSettingsToolBar;
+ KSelectAction *m_pZoomBox, *m_pRotationBox, *m_pFPSBox;
+
+ /// zoom slider
+ KIntNumInput *m_zoomSlider;
+
+ /// Current index into the zoomArray
+ unsigned int m_zoomIndex;
+
+ /// Current index into the rotationArray
+ unsigned int m_rotationIndex;
+
+ /// Current index into the fpsArray
+ unsigned int m_fpsIndex;
+
+ QStringList zoomArrayString;
+ std::vector<float> zoomArray;
+
+ QStringList rotationArrayString;
+ std::vector<int> rotationArray;
+
+ QStringList fpsArrayString;
+ std::vector<float> fpsArray;
+
+ KMagZoomView* m_zoomView;
+ KToggleAction *m_hideCursor;
+ KRadioAction *m_modeFollowMouse, *m_modeSelWin;
+ KRadioAction *m_modeEdgeTop, *m_modeEdgeLeft, *m_modeEdgeRight, *m_modeEdgeBottom;
+
+ /// Stores the non-zero cursor type to be used
+ unsigned int m_mouseCursorType;
+
+ unsigned int m_defaultMouseCursorType;
+};
+
+
+#endif // KMAG_H
diff --git a/kmag/kmag.kdevprj b/kmag/kmag.kdevprj
new file mode 100644
index 0000000..63d167f
--- /dev/null
+++ b/kmag/kmag.kdevprj
@@ -0,0 +1,230 @@
+[AUTHORS]
+dist=true
+install=true
+install_location=/usr/share/doc/kmag
+type=DATA
+
+[COPYING]
+dist=true
+install=true
+install_location=/usr/share/doc/kmag
+type=DATA
+
+[ChangeLog]
+dist=true
+install=true
+install_location=/usr/share/doc/kmag
+type=DATA
+
+[Config for BinMakefileAm]
+addcxxflags=
+bin_program=kmag
+cflags=
+cppflags=
+cxxflags=\s-O3
+ldadd=-lkdeprint $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+ldflags=\s \s
+
+[General]
+AMChanged=false
+author=Sarang Lakare
+configure_args=--prefix=/usr\s
+email=sarang@users.sourceforge.net
+kdevprj_version=1.3
+lfv_open_groups=GNU,Headers,Others,Sources,User Interface
+make_options=\s-j1
+makefiles=Makefile.am,kmag/Makefile.am,doc/Makefile.am,doc/en/Makefile.am,po/Makefile.am,doc/en/images/Makefile.am
+modifyMakefiles=true
+project_name=Kmag
+project_type=normal_kde2
+sgml_file=
+short_info=
+sub_dir=kmag/
+version=0.8
+version_control=CVS
+workspace=1
+
+[INSTALL]
+dist=true
+install=false
+install_location=/usr/share/doc/kmag
+type=DATA
+
+[KPP]
+kpp_appgrp=Multimedia
+kpp_bldroot=/usr/
+kpp_icon=0
+kpp_license=5
+kpp_summary=Magnifies a part of the screen!
+kpp_url=http://kmag.sourceforge.net
+kpp_version=0.6
+
+[LFV Groups]
+GNU=AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,NEWS
+Headers=*.h,*.hh,*.hxx,*.hpp,*.H
+Others=*
+Sources=*.cpp,*.c,*.cc,*.C,*.cxx,*.ec,*.ecpp,*.lxx,*.l++,*.ll,*.l
+Translations=*.po
+User Interface=*.kdevdlg,*.ui,*.rc
+groups=Headers,Sources,User Interface,Translations,GNU,Others
+
+[Makefile.am]
+files=kmag.kdevprj,AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,kmag.lsm,kmag.spec,install-user,install-root
+sub_dirs=kmag,po,doc
+type=normal
+
+[README]
+dist=true
+install=false
+install_location=/usr/share/doc/kmag
+type=DATA
+
+[TODO]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[Workspace_1]
+browser_file=
+cpp_file=
+header_file=
+openfiles=
+show_outputview=true
+show_treeview=true
+
+[doc/Makefile.am]
+sub_dirs=en
+type=normal
+
+[doc/en/Makefile.am]
+files=doc/en/index.docbook
+sub_dirs=images
+type=normal
+
+[doc/en/images/Makefile.am]
+files=doc/en/images/screenshot.png
+sub_dirs=
+type=normal
+
+[doc/en/images/screenshot.png]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/kmag/images/screenshot.png
+type=DATA
+
+[doc/en/index.docbook]
+dist=true
+install=true
+install_location=$$(kde_htmldir)/en/kmag/index.docbook
+type=DATA
+
+[install-root]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[install-user]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[kmag.kdevprj]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[kmag.lsm]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[kmag.spec]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[kmag/Makefile.am]
+files=kmag/main.cpp,kmag/kmag.cpp,kmag/kmag.h,kmag/kmagui.rc,kmag/kmag.desktop,kmag/lo32-app-kmag.png,kmag/lo16-app-kmag.png,kmag/kmagselrect.cpp,kmag/kmagselrect.h,kmag/hi16-app-kmag.png,kmag/kmagzoomview.cpp,kmag/kmagzoomview.h
+type=prog_main
+
+[kmag/hi16-app-kmag.png]
+dist=true
+install=true
+install_location=$$(kde_icondir)/hicolor/16x16/apps/kmag.png
+type=DATA
+
+[kmag/kmag.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[kmag/kmag.desktop]
+dist=true
+install=true
+install_location=$$(kde_appsdir)/Applications/Accessibility/kmag.desktop
+type=DATA
+
+[kmag/kmag.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[kmag/kmagselrect.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[kmag/kmagselrect.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[kmag/kmagui.rc]
+dist=true
+install=false
+install_location=
+type=DATA
+
+[kmag/kmagzoomview.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[kmag/kmagzoomview.h]
+dist=true
+install=false
+install_location=
+type=HEADER
+
+[kmag/lo16-app-kmag.png]
+dist=true
+install=true
+install_location=$$(kde_icondir)/locolor/16x16/apps/kmag.png
+type=DATA
+
+[kmag/lo32-app-kmag.png]
+dist=true
+install=true
+install_location=$$(kde_icondir)/locolor/32x32/apps/kmag.png
+type=DATA
+
+[kmag/main.cpp]
+dist=true
+install=false
+install_location=
+type=SOURCE
+
+[po/Makefile.am]
+sub_dirs=
+type=po
diff --git a/kmag/kmag.lsm b/kmag/kmag.lsm
new file mode 100644
index 0000000..6747d64
--- /dev/null
+++ b/kmag/kmag.lsm
@@ -0,0 +1,14 @@
+Begin3
+Title: Kmag
+Version: 0.3
+Entered-date:
+Description:
+Keywords:
+Author: Sarang Lakare <sarang@users.sourceforge.net>
+Maintained-by: Sarang Lakare <sarang@users.sourceforge.net>
+Primary-site:
+Home-page: http://kmag.sourceforge.net
+Original-site:
+Platforms: Linux and other Unices
+Copying-policy: GNU Public License
+End
diff --git a/kmag/kmag.mdk.spec b/kmag/kmag.mdk.spec
new file mode 100644
index 0000000..983bf83
--- /dev/null
+++ b/kmag/kmag.mdk.spec
@@ -0,0 +1,108 @@
+%define name kmag
+%define version 0.8
+%define release 1
+
+Name: %{name}
+Version: %{version}
+Release: %{release}
+Summary: KDE Screen Magnifier
+Group: Graphical desktop/KDE
+License: GPL
+Source: %{name}-%{version}.tar.gz
+URL: http://kmag.sourceforge.net
+Packager: Sarang Lakare <sarang@users.sf.net>
+Buildroot: %_tmppath/%{name}-%{version}-buildroot
+BuildRequires: gcc-cpp db3 readline pam popt libtermcap2 zlib1 XFree86-devel XFree86-libs Mesa-common
+BuildRequires: automake arts autoconf diffutils kdelibs file
+BuildRequires: m4 texinfo gettext libjpeg62-devel kdelibs-devel gcc-c++ libbinutils2 libbzip2_1
+BuildRequires: db1 freetype2 libjpeg62 libmng1 libpng libqt2 libqt2-devel rpm-build
+
+
+%description
+KMagnifier is a screen magnifier for KDE. It is useful for
+people with bad sight or others needing to magnify a part of the screen.
+
+%prep
+rm -rf $RPM_BUILD_ROOT
+
+%setup -n %{name}-%{version}
+
+%build
+CFLAGS="%optflags" CXXFLAGS="%optflags" \
+ ./configure --prefix=%_prefix \
+ --disable-rpath \
+ --disable-debug
+
+%make
+
+%install
+make DESTDIR=%buildroot install
+
+install -d $RPM_BUILD_ROOT%_menudir
+
+kdedesktop2mdkmenu.pl kmag "Applications/Accessibility" %buildroot/%_datadir/applnk/Applications/Accessibility/kmag.desktop %buildroot/%_menudir/kmag
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+%update_menus
+
+%postun
+%clean_menus
+
+%files
+%defattr(-,root,root)
+%_bindir/*
+%_menudir/*
+#
+%_datadir/icons/locolor/16x16/apps/*.png
+%_datadir/icons/locolor/32x32/apps/*.png
+%_datadir/icons/hicolor/16x16/apps/*.png
+#
+%_datadir/applnk/Applications/Accessibility/*.desktop
+#
+%dir %_datadir/apps/kmag/
+%_datadir/apps/kmag/*.rc
+#
+#%doc README COPYING AUTHORS
+#%doc %_docdir/HTML/en/*.docbook
+%doc %_docdir/HTML/en/kmag/*.docbook
+%doc %_docdir/HTML/en/kmag/images/*.png
+#%doc %_docdir/HTML/en/kmag/common
+
+%changelog
+* Sun Apr 21 2002 Sarang Lakare <sarang@users.sf.net> 0.8-1mdk
+- Rebuilding ver 0.8 for LM8.2/LM8.1
+- Added KDE documentation and removed GNU documentation
+
+* Tue Nov 20 2001 Sarang Lakare <sarang@users.sf.net> 0.6-1mdk
+- Rebuilding ver 0.6 for LM8.0
+
+* Sat Oct 20 2001 Laurent MONTEL <lmontel@mandrakesoft.com> 0.5-2mdk
+- Rebuild against libpng3
+
+* Wed Sep 19 2001 Laurent MONTEL <lmontel@mandrakesoft.com> 0.5-1mdk
+- update code (0.5)
+
+* Wed Aug 08 2001 Lenny Cartier <lenny@mandrakesoft.com> 0.3-6mdk
+- rebuild
+
+* Tue Apr 10 2001 David BAUDENS <baudens@mandrakesoft.com> 0.3-5mdk
+- Move KDE menu entriy in %%_datadir/applnk
+- Fix and use optimizations
+- Fix BuildRequires for non %%ix86 architectures
+- Rebuild against latest GCC
+
+* Fri Mar 30 2001 Laurent MONTEL <lmontel@mandrakesoft.com> 0.3-4mdk
+- Fix typo in menu entry
+
+* Wed Mar 28 2001 Laurent MONTEL <lmontel@mandrakesoft.com> 0.3-3mdk
+- Add build requires
+
+* Tue Mar 13 2001 Laurent MONTEL <lmontel@mandrakesoft.com> 0.3-2mdk
+- REbuild with qt-2.3
+
+* Sat Feb 24 2001 Daouda Lo <daouda@mandrakesoft.com> 0.3-1mdk
+- first mdk package
diff --git a/kmag/kmagselrect.cpp b/kmag/kmagselrect.cpp
new file mode 100644
index 0000000..4347d96
--- /dev/null
+++ b/kmag/kmagselrect.cpp
@@ -0,0 +1,385 @@
+/***************************************************************************
+ kmagselrect.cpp - description
+ -------------------
+ begin : Mon Feb 12 23:45:41 EST 2001
+ copyright : (C) 2001-2003 by Sarang Lakare
+ email : sarang#users.sf.net
+ copyright : (C) 2003-2004 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kmagselrect.h"
+#include "kmagselrect.moc"
+
+#include <qapplication.h>
+#include <qcursor.h>
+#include <qdesktopwidget.h>
+#include <qpixmap.h>
+#include <qbitmap.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+
+static uchar line_bits[] = {0x2d, 0x96, 0x4b, 0xa5, 0xd2, 0x69, 0xb4, 0x5a};
+
+static QColor titleColor = QColor (0,0,128);
+static QColor titleBtnColor = QColor (255,255,0);
+static QColor textColor = QColor (255,255,255);
+
+static int frameSize = 10;
+static int titleSize = 24;
+
+void setTitleColors (QColor title, QColor text, QColor titleBtn)
+{
+ titleColor = title;
+ titleBtnColor = titleBtn;
+ textColor = text;
+}
+
+void setFrameSize (int size)
+{
+ frameSize = size;
+}
+
+void setTitleSize (int size)
+{
+ titleSize = size;
+}
+
+QColor getTitleColor ()
+{
+ return titleColor;
+}
+
+QColor getTitleBtnColor ()
+{
+ return titleBtnColor;
+}
+
+QColor getTextColor ()
+{
+ return textColor;
+}
+
+int getFrameSize ()
+{
+ return frameSize;
+}
+
+int getTitleSize ()
+{
+ if (titleSize > frameSize)
+ return titleSize;
+ else
+ return frameSize;
+}
+
+//--------------------------------------------------------------------------
+// Construction
+//--------------------------------------------------------------------------
+
+KMagSelRect::KMagSelRect(QWidget *parent) :
+ QRect()
+{
+ init(parent);
+}
+
+KMagSelRect::KMagSelRect(const QPoint &topLeft, const QPoint &bottomRight,
+ QWidget *parent) :
+QRect(topLeft, bottomRight)
+{
+ init(parent);
+}
+
+KMagSelRect::KMagSelRect(const QPoint &topLeft, const QSize &size,
+ QWidget *parent) :
+QRect(topLeft, size)
+{
+ init(parent);
+}
+
+KMagSelRect::KMagSelRect(int left, int top, int width, int height,
+ QWidget *parent) :
+QRect(left, top, width, height)
+{
+ init(parent);
+}
+
+void KMagSelRect::init(QWidget *parent)
+{
+ // Make sure parent is the window itself, not a widget within the window
+ if (parent != 0)
+ while (parent->parentWidget (true) != 0)
+ parent=parent->parentWidget (true);
+
+ selectionwindow = 0;
+ selWindowParent = parent;
+
+ m_alwaysVisible = false;
+}
+
+KMagSelRect::~KMagSelRect()
+{
+}
+
+//--------------------------------------------------------------------------
+//
+//--------------------------------------------------------------------------
+
+WId KMagSelRect::winId()
+{
+ if (selectionwindow)
+ return selectionwindow->winId();
+ else
+ return 0;
+}
+
+bool KMagSelRect::visible()
+{
+ return (selectionwindow != 0);
+}
+
+void KMagSelRect::alwaysVisible(bool visible)
+{
+ m_alwaysVisible = visible;
+}
+
+
+//--------------------------------------------------------------------------
+// Slots
+//--------------------------------------------------------------------------
+
+void KMagSelRect::show()
+{
+ if (selectionwindow == 0) {
+ selectionwindow = new KMagSelWin (selWindowParent, "selectionwindow");
+ connect (selectionwindow, SIGNAL (resized ()), this, SLOT (selWinResized ()));
+
+ update();
+ selectionwindow->show();
+ selWindowParent->setActiveWindow();
+ }
+}
+
+void KMagSelRect::hide()
+{
+ if(m_alwaysVisible)
+ return;
+ if (selectionwindow != 0) {
+ selectionwindow->hide();
+ delete selectionwindow;
+ selectionwindow = 0;
+ }
+}
+
+void KMagSelRect::update()
+{
+ // make sure the selection window does not go outside of the display
+ if (height() > QApplication::desktop()->geometry().height())
+ setHeight (QApplication::desktop()->geometry().height());
+ if (width() > QApplication::desktop()->geometry().width())
+ setWidth (QApplication::desktop()->geometry().width());
+
+ if (top() < 0)
+ moveTop (0);
+ if (left() < 0)
+ moveLeft (0);
+ if (bottom() > QApplication::desktop()->geometry().bottom())
+ moveBottom (QApplication::desktop()->geometry().bottom());
+ if (right() > QApplication::desktop()->geometry().right())
+ moveRight (QApplication::desktop()->geometry().right());
+
+ if (selectionwindow != 0)
+ selectionwindow->setSelRect (QRect (topLeft(), bottomRight()));
+}
+
+void KMagSelRect::selWinResized()
+{
+ if (selectionwindow != 0)
+ {
+ QRect newRect = selectionwindow->getSelRect();
+ setRect (newRect.x(), newRect.y(), newRect.width(), newRect.height());
+ }
+}
+
+//--------------------------------------------------------------------------
+// KMagSelWin
+//--------------------------------------------------------------------------
+
+KMagSelWin::KMagSelWin ( QWidget * parent, const char * name, WFlags ) :
+ QWidget (parent, name, WStyle_Customize | WStyle_NoBorder | WStyle_StaysOnTop | WType_TopLevel | WX11BypassWM)
+{
+ QBitmap line (8, 8, line_bits, true);
+ setPaletteBackgroundPixmap (line);
+ setBackgroundOrigin (QWidget::WindowOrigin);
+
+ titleBar = new KMagSelWinCorner (this, "titlebar");
+ titleBar->setPaletteBackgroundColor (getTitleColor ());
+ titleBar->setPaletteForegroundColor (getTextColor ());
+ titleBar->setText(i18n("Selection Window")+" - "+i18n("KMagnifier"));
+ connect (titleBar, SIGNAL (startResizing ()), this, SLOT (startResizing ()));
+ connect (titleBar, SIGNAL (resized (QPoint)), this, SLOT (titleMoved (QPoint)));
+
+ topLeftCorner = new KMagSelWinCorner (this, "topleft");
+ topLeftCorner->setCursor (Qt::SizeFDiagCursor);
+ topLeftCorner->setPaletteBackgroundColor (getTitleBtnColor ());
+ connect (topLeftCorner, SIGNAL (startResizing ()), this, SLOT (startResizing ()));
+ connect (topLeftCorner, SIGNAL (resized (QPoint)), this, SLOT (topLeftResized (QPoint)));
+
+ topRightCorner = new KMagSelWinCorner (this, "topright");
+ topRightCorner->setCursor (Qt::SizeBDiagCursor);
+ topRightCorner->setPaletteBackgroundColor (getTitleBtnColor ());
+ connect (topRightCorner, SIGNAL (startResizing ()), this, SLOT (startResizing ()));
+ connect (topRightCorner, SIGNAL (resized (QPoint)), this, SLOT (topRightResized (QPoint)));
+
+ bottomLeftCorner = new KMagSelWinCorner (this, "bottomleft");
+ bottomLeftCorner->setCursor (Qt::SizeBDiagCursor);
+ bottomLeftCorner->setPaletteBackgroundColor (getTitleBtnColor ());
+ connect (bottomLeftCorner, SIGNAL (startResizing ()), this, SLOT (startResizing ()));
+ connect (bottomLeftCorner, SIGNAL (resized (QPoint)), this, SLOT (bottomLeftResized (QPoint)));
+
+ bottomRightCorner = new KMagSelWinCorner (this, "bottomright");
+ bottomRightCorner->setCursor (Qt::SizeFDiagCursor);
+ bottomRightCorner->setPaletteBackgroundColor (getTitleBtnColor ());
+ connect (bottomRightCorner, SIGNAL (startResizing ()), this, SLOT (startResizing ()));
+ connect (bottomRightCorner, SIGNAL (resized (QPoint)), this, SLOT (bottomRightResized (QPoint)));
+}
+
+KMagSelWin::~KMagSelWin()
+{
+ delete titleBar;
+ delete topLeftCorner;
+ delete topRightCorner;
+ delete bottomLeftCorner;
+ delete bottomRightCorner;
+}
+
+void KMagSelWin::setSelRect (QRect selRect)
+{
+ selRect = selRect.normalize();
+
+ if (selRect.left() < 0)
+ selRect.setLeft (0);
+ if (selRect.top() < 0)
+ selRect.setTop (0);
+ if (selRect.right() > QApplication::desktop()->width())
+ selRect.setRight (QApplication::desktop()->width());
+ if (selRect.bottom() > QApplication::desktop()->height())
+ selRect.setBottom (QApplication::desktop()->height());
+
+ setGeometry (
+ selRect.left() - getFrameSize(),
+ selRect.top() - getTitleSize() - 2,
+ selRect.width() + getFrameSize() + getFrameSize(),
+ selRect.height() + getFrameSize() + getTitleSize()+2);
+
+ int w = getFrameSize();
+ if (selRect.width() < w+w)
+ w = static_cast<int>(selRect.width()/2);
+
+ int h = getFrameSize();
+ if (selRect.height() < h+h)
+ h = static_cast<int>(selRect.height()/2);
+
+ setMask (QRegion (QRect (0, 0, width(), height ()))
+ - QRegion (QRect (getFrameSize(), getTitleSize()+2, selRect.width(), selRect.height()))
+ - QRegion (QRect (0, 0, getFrameSize()+w, getTitleSize()+2-getFrameSize()))
+ - QRegion (QRect (width()-getFrameSize()-w, 0, getFrameSize()+w, getTitleSize()+2-getFrameSize()))
+ - QRegion (QRect (0, getTitleSize()+2+h, getFrameSize()-2, selRect.height()-h-h))
+ - QRegion (QRect (width()-getFrameSize()+2, getTitleSize()+2+h, getFrameSize()-2, selRect.height()-h-h))
+ - QRegion (QRect (getFrameSize()+w, height()-getFrameSize()+2, selRect.width()-w-w, getFrameSize()-2)));
+
+ titleBar->setGeometry (getFrameSize()+w, 0, selRect.width()-h-h, getTitleSize());
+ topLeftCorner->setGeometry (0, getTitleSize()+2-getFrameSize(), getFrameSize()+w, getFrameSize()+h);
+ topRightCorner->setGeometry (width()-getFrameSize()-w, getTitleSize()+2-getFrameSize(), getFrameSize()+w, getFrameSize()+h);
+ bottomLeftCorner->setGeometry (0, height()-getFrameSize()-h, getFrameSize()+w, getFrameSize()+h);
+ bottomRightCorner->setGeometry (width()-getFrameSize()-w, height()-getFrameSize()-h, getFrameSize()+w, getFrameSize()+h);
+}
+
+QRect KMagSelWin::getSelRect ()
+{
+ return QRect (
+ x() + getFrameSize(),
+ y() + getTitleSize()+2,
+ width() - getFrameSize() - getFrameSize(),
+ height() - getFrameSize() - getTitleSize()-2);
+}
+
+void KMagSelWin::startResizing ()
+{
+ oldSelRect = getSelRect();
+}
+
+void KMagSelWin::titleMoved ( QPoint offset )
+{
+ QRect selRect = oldSelRect;
+ selRect.moveBy (offset.x(), offset.y());
+ setSelRect (selRect);
+ emit resized ();
+}
+
+void KMagSelWin::topLeftResized ( QPoint offset )
+{
+ setSelRect (QRect(oldSelRect.topLeft() + offset, oldSelRect.bottomRight ()));
+ emit resized();
+}
+
+void KMagSelWin::topRightResized ( QPoint offset )
+{
+ setSelRect (QRect(oldSelRect.topRight() + offset, oldSelRect.bottomLeft ()));
+ emit resized();
+}
+
+void KMagSelWin::bottomLeftResized ( QPoint offset )
+{
+ setSelRect (QRect(oldSelRect.bottomLeft() + offset, oldSelRect.topRight ()));
+ emit resized();
+}
+
+void KMagSelWin::bottomRightResized ( QPoint offset )
+{
+ setSelRect (QRect(oldSelRect.bottomRight() + offset, oldSelRect.topLeft()));
+ emit resized();
+}
+
+
+//--------------------------------------------------------------------------
+// KMagSelWinCorner
+//--------------------------------------------------------------------------
+
+KMagSelWinCorner::KMagSelWinCorner ( QWidget * parent, const char * name, WFlags f ) :
+ QLabel (parent, name, f)
+{
+ setFrameStyle (QFrame::WinPanel | QFrame::Raised);
+ setLineWidth (1);
+}
+
+KMagSelWinCorner::~KMagSelWinCorner()
+{
+}
+
+void KMagSelWinCorner::mousePressEvent ( QMouseEvent * e )
+{
+ oldPos = e->globalPos ();
+ emit startResizing ();
+}
+
+void KMagSelWinCorner::mouseReleaseEvent ( QMouseEvent * e )
+{
+ setFrameShadow (QFrame::Raised);
+ emit resized (e->globalPos () - oldPos);
+}
+
+void KMagSelWinCorner::mouseMoveEvent ( QMouseEvent * e )
+{
+ emit resized (e->globalPos () - oldPos);
+}
diff --git a/kmag/kmagselrect.h b/kmag/kmagselrect.h
new file mode 100644
index 0000000..675954c
--- /dev/null
+++ b/kmag/kmagselrect.h
@@ -0,0 +1,146 @@
+/***************************************************************************
+ kmagselrect.h - description
+ -------------------
+ begin : Mon Feb 12 23:45:41 EST 2001
+ copyright : (C) 2001-2003 by Sarang Lakare
+ email : sarang#users.sf.net
+ copyright : (C) 2003-2004 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KMAGSELRECT_H
+#define KMAGSELRECT_H
+
+#include <stdlib.h>
+
+// Qt includes
+#include <qrect.h>
+#include <qwidget.h>
+#include <qlabel.h>
+
+class KMagSelWinCorner : public QLabel
+{
+ Q_OBJECT
+
+public:
+
+ KMagSelWinCorner ( QWidget * parent = 0, const char * name = 0, WFlags f = 0 );
+
+ virtual ~KMagSelWinCorner();
+
+signals:
+
+ void startResizing ();
+ void resized ( QPoint offset );
+
+protected:
+
+ QPoint oldPos;
+
+ virtual void mousePressEvent ( QMouseEvent * e );
+ virtual void mouseReleaseEvent ( QMouseEvent * e );
+ virtual void mouseMoveEvent ( QMouseEvent * e );
+};
+
+class KMagSelWin : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ KMagSelWin ( QWidget * parent = 0, const char * name = 0, WFlags f = 0 );
+
+ virtual ~KMagSelWin();
+
+ void setSelRect ( QRect selRect );
+ QRect getSelRect ();
+
+public slots:
+
+ void startResizing ();
+ void titleMoved ( QPoint offset );
+ void topLeftResized ( QPoint offset );
+ void topRightResized ( QPoint offset );
+ void bottomLeftResized ( QPoint offset );
+ void bottomRightResized ( QPoint offset );
+
+signals:
+
+ void resized();
+
+protected:
+
+ QRect oldSelRect;
+
+ KMagSelWinCorner *titleBar;
+ KMagSelWinCorner *topLeftCorner;
+ KMagSelWinCorner *topRightCorner;
+ KMagSelWinCorner *bottomLeftCorner;
+ KMagSelWinCorner *bottomRightCorner;
+};
+
+/**
+ * This class stores the selected rectangular area for grabbing. It also displays the
+ * rectangular area on demand.
+ *
+ * @author Original : Michael Forster
+ * @author Current : Sarang Lakare
+ */
+class KMagSelRect : public QObject, public QRect
+{
+ Q_OBJECT
+
+public:
+ KMagSelRect(QWidget *parent=0);
+ KMagSelRect(const QPoint &topLeft, const QPoint &bottomRight,
+ QWidget *parent=0);
+ KMagSelRect(const QPoint &topLeft, const QSize &size,
+ QWidget *parent=0);
+ KMagSelRect(int left, int top, int width, int height,
+ QWidget *selWindowParent=0);
+
+ virtual ~KMagSelRect();
+
+ WId winId();
+
+ bool visible();
+
+ /// Makes the rectangle always visible
+ void alwaysVisible(bool visible=true);
+
+ /// Returns true if always visible is set
+ bool getAlwaysVisible() const {
+ return (m_alwaysVisible);
+ };
+
+public slots:
+
+ void show();
+ void hide();
+ void update();
+
+ void selWinResized();
+
+protected:
+
+ void init(QWidget *);
+
+ QWidget *selWindowParent;
+ KMagSelWin *selectionwindow;
+ bool m_alwaysVisible;
+
+};
+
+void setTitleColors (QColor title, QColor text, QColor titleBtn);
+void setFrameSize (int size);
+
+#endif // KMAGSELRECT_H
diff --git a/kmag/kmagui.rc b/kmag/kmagui.rc
new file mode 100644
index 0000000..d30ce37
--- /dev/null
+++ b/kmag/kmagui.rc
@@ -0,0 +1,109 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="kmag" version="11">
+ <ToolBar noMerge="1" name="mainToolBar">
+ <Action name="new_window"/>
+ <Separator />
+ <Action name="snapshot"/>
+ <Action name="print"/>
+ <Action name="copy"/>
+ </ToolBar>
+
+ <ToolBar noMerge="1" name="viewToolBar">
+ <Action name="start_stop_refresh"/>
+ <Separator />
+ <Action name="zoom_in"/>
+ <Action name="zoom"/>
+ <Action name="zoom_out"/>
+ <Separator />
+ <Action name="fps_selector"/>
+ </ToolBar>
+
+ <ToolBar noMerge="1" name="settingsToolBar">
+ <Action name="mode_followmouse"/>
+ <Action name="mode_selectionwindow"/>
+ <Separator />
+ <Action name="hidecursor"/>
+ </ToolBar>
+
+ <MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="new_window"/>
+ <Action name="snapshot"/>
+ <Action name="print"/>
+ <Separator />
+ <Action name="quit"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="copy"/>
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="start_stop_refresh"/>
+ <Separator />
+ <Action name="zoom"/>
+ <Action name="zoom_out"/>
+ <Action name="zoom_in"/>
+ <Separator />
+ <Action name="invert"/>
+ <Action name="rotation"/>
+ <Action name="fps_selector"/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Action name="show_menu"/>
+ <Action name="show_mainToolBar"/>
+ <Action name="show_viewToolBar"/>
+ <Action name="show_settingsToolBar"/>
+ <Separator />
+ <Action name="mode_followmouse"/>
+ <Action name="mode_selectionwindow"/>
+ <Action name="mode_edgetop"/>
+ <Action name="mode_edgeleft"/>
+ <Action name="mode_edgeright"/>
+ <Action name="mode_edgebottom"/>
+ <Separator />
+ <Action name="hidecursor"/>
+ <Separator />
+ <Action name="key_conf"/>
+ <Action name="toolbar_conf"/>
+ </Menu>
+ </MenuBar>
+
+ <Menu name="mainPopUp">
+ <Action name="new_window"/>
+ <Separator />
+ <Action name="copy"/>
+ <Separator />
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="start_stop_refresh"/>
+ <Separator />
+ <Action name="zoom"/>
+ <Action name="zoom_out"/>
+ <Action name="zoom_in"/>
+ <Separator />
+ <Action name="invert"/>
+ <Action name="rotation"/>
+ <Action name="fps_selector"/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Action name="show_menu"/>
+ <Action name="show_mainToolBar"/>
+ <Action name="show_viewToolBar"/>
+ <Action name="show_settingsToolBar"/>
+ <Separator />
+ <Action name="mode_followmouse"/>
+ <Action name="mode_selectionwindow"/>
+ <Action name="mode_edgetop"/>
+ <Action name="mode_edgeleft"/>
+ <Action name="mode_edgeright"/>
+ <Action name="mode_edgebottom"/>
+ <Separator />
+ <Action name="hidecursor"/>
+ <Separator />
+ <Action name="key_conf"/>
+ <Action name="toolbar_conf"/>
+ </Menu>
+ <Separator />
+ <Action name="snapshot"/>
+ <Action name="print"/>
+ <Action name="quit"/>
+ </Menu>
+</kpartgui>
diff --git a/kmag/kmagzoomview.cpp b/kmag/kmagzoomview.cpp
new file mode 100644
index 0000000..a38c21c
--- /dev/null
+++ b/kmag/kmagzoomview.cpp
@@ -0,0 +1,927 @@
+/***************************************************************************
+ kmagview.cpp - description
+ -------------------
+ begin : Mon Feb 12 23:45:41 EST 2001
+ copyright : (C) 2001-2003 by Sarang Lakare
+ email : sarang#users.sourceforge.net
+ copyright : (C) 2003-2005 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+// application specific includes
+#include "kmagzoomview.h"
+#include "kmagzoomview.moc"
+
+// include files for Qt
+#include <qbitmap.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qcursor.h>
+#include <qglobal.h>
+#include <qpainter.h>
+#include <qwhatsthis.h>
+#include <qwidget.h>
+
+// include files for KDE
+#include <kapplication.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+// include bitmaps for cursors
+static uchar left_ptr_bits[] = {
+ 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00,
+ 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01,
+ 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00};
+
+static uchar left_ptrmsk_bits[] = {
+ 0x0c, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01,
+ 0xfc, 0x03, 0xfc, 0x07, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x01, 0xdc, 0x03,
+ 0xcc, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x03};
+
+static uchar phand_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
+ 0x7e, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00,
+ 0x08, 0x08, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x08, 0x22, 0x00, 0x00,
+ 0x30, 0x41, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00,
+ 0x80, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static uchar phandm_bits[] = {
+ 0xfe, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00,
+ 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00,
+ 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00,
+ 0xf8, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00,
+ 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+
+
+static bool obscuredRegion (QRegion &region, Window winId, Window ignoreId, Window start = 0, int level = -1) {
+ Window root, parent, *children; uint nchildren;
+ if (0 == start)
+ start = qt_xrootwin();
+
+ bool winIdFound = false;
+ if (0 != XQueryTree (qt_xdisplay(), start, &root, &parent, &children, &nchildren)) {
+ for (uint i=0; i < nchildren; ++i) {
+ if (winIdFound) {
+ if (ignoreId != children [i]) {
+ XWindowAttributes atts;
+ XGetWindowAttributes (qt_xdisplay(), children [i], &atts);
+ if (atts.map_state == IsViewable)
+ region -= QRegion (atts.x, atts.y, atts.width, atts.height, QRegion::Rectangle);
+ }
+ }
+ else if (winId == children [i])
+ winIdFound = true;
+
+ // According to tests, my own window ID is either on toplevel or two levels below.
+ // To avoid unneccessary recursion, we limit the search to two recursion levels,
+ // then to five recursion levels, and make a full recursive search only if that
+ // was unsuccessful.
+ else if (level > 1)
+ winIdFound = obscuredRegion (region, winId, ignoreId, children [i], level-1);
+ else if (level == -1)
+ if (! (winIdFound = obscuredRegion (region, winId, ignoreId, children [i], 0)))
+ if (! (winIdFound = obscuredRegion (region, winId, ignoreId, children [i], 1)))
+ winIdFound = obscuredRegion (region, winId, ignoreId, children [i], -1);
+ }
+
+ if (children != NULL)
+ XFree (children);
+ }
+
+ return winIdFound;
+}
+
+
+
+
+KMagZoomView::KMagZoomView(QWidget *parent, const char *name)
+ : QScrollView(parent, name),
+ m_selRect(0, 0, 128, 128, this),
+ m_grabTimer(0),
+ m_mouseViewTimer(0),
+ m_latestCursorPos(0,0),
+ m_followMouse(false),
+ m_showMouse(1),
+ m_zoom(1.0),
+ m_rotation(0),
+ m_invert(false),
+ m_fitToWindow(true)
+{
+ KApplication::setGlobalMouseTracking(TRUE);
+ viewport()->setMouseTracking(TRUE);
+ viewport()->setBackgroundMode (NoBackground);
+ viewport()->setFocusPolicy(QWidget::StrongFocus);
+
+ m_ctrlKeyPressed = false;
+ m_shiftKeyPressed = false;
+ m_refreshSwitch = true;
+ m_refreshSwitchStateOnHide = m_refreshSwitch;
+
+ // set the refresh rate
+ setRefreshRate(10);
+
+ // connect it to grabFrame()
+ connect(&m_grabTimer, SIGNAL(timeout()), SLOT(grabFrame()));
+ // start the grabTimer
+ m_grabTimer.start(static_cast<int>(1000.0/m_fps));
+
+ // connect it to updateMouseView()
+ connect(&m_mouseViewTimer, SIGNAL(timeout()), SLOT(updateMouseView()));
+ // start the grabTimer @ 25 frames per second!
+ m_mouseViewTimer.start(25);
+
+ QWhatsThis::add(this, i18n("This is the main window which shows the contents of the\
+ selected region. The contents will be magnified according to the zoom level that is set."));
+
+ // different ways to show the cursor.
+ m_showMouseTypes << "Hidden" << "Box" << "Arrow" << "Actual";
+
+ updateMatrix();
+}
+
+KMagZoomView::~KMagZoomView()
+{
+ KApplication::setGlobalMouseTracking(FALSE);
+}
+
+/**
+ * This function will set/reset mouse following of grab window.
+ */
+void KMagZoomView::followMouse(bool follow)
+{
+ if(follow) {
+ m_followMouse = true;
+ m_mouseMode = Normal;
+ setVScrollBarMode (QScrollView::AlwaysOff);
+ setHScrollBarMode (QScrollView::AlwaysOff);
+ } else {
+ m_followMouse = false;
+ m_mouseMode = Normal;
+ setVScrollBarMode (QScrollView::AlwaysOn);
+ setHScrollBarMode (QScrollView::AlwaysOn);
+ }
+}
+
+/**
+ * Called when the widget is hidden. Stop refresh when this happens.
+ */
+void KMagZoomView::hideEvent( QHideEvent* )
+{
+ // Save the state of the refresh switch.. the state will be restored
+ // when showEvent is called
+ m_refreshSwitchStateOnHide = m_refreshSwitch;
+
+ // Check if refresh is ON
+ if(m_refreshSwitch) {
+ toggleRefresh();
+ }
+}
+
+
+/**
+ * Called when the widget is shown. Start refresh when this happens.
+ */
+void KMagZoomView::showEvent( QShowEvent* )
+{
+ // Check if refresh switch was ON when hide was called and if currently it is OFF
+ if(m_refreshSwitchStateOnHide && !m_refreshSwitch) {
+ // start the refresh in that case
+ toggleRefresh();
+ }
+}
+
+/**
+ * Called when the widget is resized. Check if fitToWindow is active when this happens.
+ */
+void KMagZoomView::resizeEvent( QResizeEvent * e )
+{
+ QScrollView::resizeEvent (e);
+ if(m_fitToWindow)
+ fitToWindow();
+}
+
+/**
+ * Called when the widget is to be repainted
+ *
+ * @param p
+ */
+void KMagZoomView::drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph )
+{
+ if(m_grabbedPixmap.isNull())
+ return;
+
+ // A pixmap which will be eventually displayed
+ QRect areaToPaint = m_invertedMatrix.mapRect (QRect(clipx, clipy, clipw, cliph));
+ QPixmap clippedPixmap (areaToPaint.size());
+ clippedPixmap.fill (QColor (128, 128, 128));
+ areaToPaint &= QRect (QPoint (0,0), m_selRect.size());
+ bitBlt(&clippedPixmap, QPoint (0,0), &m_grabbedPixmap, areaToPaint);
+
+ // show the pixel under mouse cursor
+ if(m_showMouse) {
+ // paint the mouse cursor
+ paintMouseCursor(&clippedPixmap, calcMousePos (m_refreshSwitch)-QPoint (areaToPaint.x(), areaToPaint.y()));
+ }
+
+ QPixmap zoomedPixmap;
+ zoomedPixmap = clippedPixmap.xForm (m_zoomMatrix);
+
+ if (m_invert) {
+ QImage zoomedImage;
+ zoomedImage = zoomedPixmap.convertToImage();
+ zoomedImage.invertPixels (false);
+ p->drawImage (QPoint (clipx-contentsX(), clipy-contentsY()), zoomedImage, zoomedImage.rect(),
+ Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::AvoidDither);
+ } else {
+ p->drawPixmap (QPoint (clipx, clipy), zoomedPixmap, zoomedPixmap.rect());
+ }
+}
+
+/**
+ * Draws the mouse cursor according to the current selection of the type of
+ * mouse cursor to draw.
+ */
+void KMagZoomView::paintMouseCursor(QPaintDevice *dev, QPoint mousePos)
+{
+ if(!dev)
+ return;
+
+ QPainter pz(dev);
+
+ if(m_latestCursorPos.x() >= 0 && m_latestCursorPos.x() < m_selRect.width() &&
+ m_latestCursorPos.y() >= 0 && m_latestCursorPos.y() < m_selRect.height() ) {
+ // mouse position is indeed inside the selRect
+
+ // How to show the mouse :
+
+ switch(m_showMouse) {
+ case 1:
+ // 1. Square around the pixel
+ pz.setPen(Qt::white);
+ pz.setRasterOp(Qt::XorROP);
+ pz.drawRect(mousePos.x()-1, mousePos.y()-1, 3, 3);
+ break;
+
+ case 2:
+ {
+ // 2. Arrow cursor
+ pz.setPen(Qt::black);
+ pz.setBackgroundColor(Qt::white);
+
+ QBitmap sCursor( 16, 16, left_ptr_bits, TRUE );
+ QBitmap mask( 16, 16, left_ptrmsk_bits, TRUE );
+ sCursor.setMask(mask);
+
+ // since hot spot is at 3,1
+ pz.drawPixmap(mousePos.x()-3, mousePos.y()-1, sCursor);
+ }
+ break;
+
+ case 3:
+ {
+ // 3. Actual cursor
+ // Get the current cursor type
+ QWidget *dummy = KApplication::widgetAt(QCursor::pos(), FALSE);
+ if(!dummy)
+ break;
+ kdDebug() << ">" << dummy->name() << ":" << dummy->cursor().shape() << "-" << endl;
+ switch(this->cursor().shape()) {
+ case ArrowCursor :
+ {
+ // 2. Arrow cursor
+ pz.setPen(Qt::black);
+ pz.setBackgroundColor(Qt::white);
+
+ QBitmap sCursor( 16, 16, left_ptr_bits, TRUE );
+ QBitmap mask( 16, 16, left_ptrmsk_bits, TRUE );
+ sCursor.setMask(mask);
+
+ // since hot spot is at 3,1
+ pz.drawPixmap(mousePos.x()-3, mousePos.y()-1, sCursor);
+ }
+ break;
+ default:
+ QBitmap sCursor( 32, 32, phand_bits, TRUE );
+ QBitmap mask( 32, 32, phandm_bits, TRUE );
+ sCursor.setMask(mask);
+
+ pz.drawPixmap(mousePos.x(), mousePos.y(), sCursor);
+ break;
+ } // switch(cursor)
+
+
+ }
+ break;
+
+ default:
+ // do not show anything
+ break;
+ } // switch(m_showMouse)
+ }
+}
+
+
+QPoint KMagZoomView::calcMousePos(bool updateMousePos)
+{
+ // get position of mouse wrt selRect
+ if(updateMousePos) { // get a new position only if asked
+ m_latestCursorPos = QCursor::pos();
+ m_latestCursorPos -= QPoint(m_selRect.x(), m_selRect.y());
+ }
+
+ // get coordinates of the pixel w.r.t. the pixmap
+ return QPoint (m_latestCursorPos.x(), m_latestCursorPos.y());
+}
+
+
+// MOUSE ACTIONS
+
+/**
+ * Called when mouse is clicked inside the window
+ *
+ * @param e
+ */
+void KMagZoomView::mousePressEvent(QMouseEvent *e)
+{
+ switch(e->button()) {
+ case QMouseEvent::LeftButton :
+ if(m_ctrlKeyPressed) {
+ // check if currently in resize mode
+ // don't do anything if fitToWindow is enabled
+ if ((m_mouseMode != ResizeSelection) && !m_fitToWindow) {
+ // set the mode to ResizeSelection
+ m_mouseMode = ResizeSelection;
+
+ // set mouse cursor to "resize all direction"
+ setCursor(sizeAllCursor);
+
+ // backup the old position
+ m_oldMousePos.setX(e->globalX());
+ m_oldMousePos.setY(e->globalY());
+
+ // set the cursor position to the bottom-right of the selected region
+ QCursor::setPos(m_selRect.bottomRight());
+
+ // show the selection rectangle
+ m_selRect.show();
+ }
+ else {
+ #if QT_VERSION >= 300
+ // ignore this button press.. so it goes to the parent
+ e->ignore();
+ #endif
+ }
+ } else if(m_shiftKeyPressed) {
+ // check if currently in move mode
+ // don't do anything if follow mouse is enabled
+ if ((m_mouseMode != MoveSelection) && !m_followMouse) {
+ m_mouseMode = MoveSelection;
+
+ // set mouse cursor to cross hair
+ setCursor(crossCursor);
+
+ // backup the old position
+ m_oldMousePos.setX(e->globalX());
+ m_oldMousePos.setY(e->globalY());
+
+ // set the cursor position to the center of the selected region
+ QCursor::setPos(m_selRect.center());
+
+ // show the selected rectangle
+ m_selRect.show();
+ }
+ else {
+ #if QT_VERSION >= 300
+ // ignore this button press.. so it goes to the parent
+ e->ignore();
+ #endif
+ }
+ } else {
+ // check if currently in move mode
+ // don't do anything if follow mouse is enabled
+ if ((m_mouseMode != GrabSelection) && !m_followMouse) {
+ m_mouseMode = GrabSelection;
+
+ // set mouse cursor to hand
+ setCursor(KCursor::handCursor());
+
+ // store the old position
+ m_oldMousePos.setX(e->globalX());
+ m_oldMousePos.setY(e->globalY());
+
+ m_oldCenter = m_selRect.center();
+
+ // show the selected rectangle
+ m_selRect.show();
+ }
+ else {
+ #if QT_VERSION >= 300
+ // ignore this button press.. so it goes to the parent
+ e->ignore();
+ #endif
+ }
+ }
+ break;
+
+ case QMouseEvent::MidButton :
+ // check if currently in move mode
+ // don't do anything if follow mouse is enabled
+ if ((m_mouseMode != MoveSelection) && !m_followMouse) {
+ m_mouseMode = MoveSelection;
+
+ // set mouse cursor to cross hair
+ setCursor(crossCursor);
+
+ // backup the old position
+ m_oldMousePos.setX(e->globalX());
+ m_oldMousePos.setY(e->globalY());
+
+ // set the cursor position to the center of the selected region
+ QCursor::setPos(m_selRect.center());
+
+ // show the selected rectangle
+ m_selRect.show();
+ }
+ else {
+ #if QT_VERSION >= 300
+ // ignore this button press.. so it goes to the parent
+ e->ignore();
+ #endif
+ }
+ break;
+ // do nothing
+ default:
+#if QT_VERSION >= 300
+ // ignore this button press.. so it goes to the parent
+ e->ignore();
+#endif
+ break;
+ }
+}
+
+
+/**
+ * Called when a mouse button is released
+ *
+ * @param e
+ */
+void KMagZoomView::mouseReleaseEvent(QMouseEvent *e)
+{
+ switch(e->button()) {
+ case QMouseEvent::LeftButton :
+ case QMouseEvent::MidButton :
+ // check if currently in move mode
+ if(m_mouseMode == MoveSelection) {
+ // hide the selection window
+ m_selRect.hide();
+ // set the mouse mode to normal
+ m_mouseMode = Normal;
+
+ // restore the cursor shape
+ setCursor(arrowCursor);
+
+ // restore the cursor position
+ QCursor::setPos(m_oldMousePos);
+ } else if(m_mouseMode == ResizeSelection) {
+ // hide the selection window
+ m_selRect.hide();
+ // set the mouse mode to normal
+ m_mouseMode = Normal;
+
+ // restore the cursor shape
+ setCursor(arrowCursor);
+
+ // restore the cursor position
+ QCursor::setPos(m_oldMousePos);
+ } else if(m_mouseMode == GrabSelection) {
+ // hide the selection window
+ m_selRect.hide();
+
+ // set the mouse mode to normal
+ m_mouseMode = Normal;
+
+ // restore the cursor shape
+ setCursor(arrowCursor);
+ }
+ break;
+
+ case QMouseEvent::RightButton :
+ break;
+ case QMouseEvent::NoButton :
+ break;
+
+ // do nothing
+ default:
+ ;
+ }
+}
+
+
+/**
+ * Called when mouse is moved inside the window
+ *
+ * @param e
+ */
+void KMagZoomView::mouseMoveEvent(QMouseEvent *e)
+{
+ if(m_mouseMode == ResizeSelection) {
+ // In resize selection mode
+ // set the current mouse position as the bottom, right corner
+ m_selRect.setRight(e->globalX());
+ m_selRect.setBottom(e->globalY());
+ m_selRect.update();
+
+ grabFrame();
+ } else if(m_mouseMode == MoveSelection) {
+ QPoint newCenter;
+
+ // set new center to be the current mouse position
+ m_selRect.moveCenter(e->globalPos());
+ m_selRect.update();
+
+ grabFrame();
+ } else if(m_mouseMode == GrabSelection) {
+ QPoint newPos;
+
+ // get new position
+ newPos = e->globalPos();
+ QPoint delta = (newPos - m_oldMousePos)/m_zoom;
+ m_selRect.moveCenter(m_oldCenter-delta);
+ m_selRect.update();
+
+ grabFrame();
+ }
+}
+
+void KMagZoomView::keyPressEvent(QKeyEvent *e)
+{
+ int offset = 16;
+ if (e->state() & QKeyEvent::ShiftButton)
+ offset = 1;
+
+ if (e->key() == QKeyEvent::Key_Control)
+ m_ctrlKeyPressed = true;
+ else if (e->key() == QKeyEvent::Key_Shift)
+ m_shiftKeyPressed = true;
+ else if (e->key() == QKeyEvent::Key_Left)
+ {
+ if (e->state() & QKeyEvent::ControlButton)
+ {
+ if (offset >= m_selRect.width())
+ m_selRect.setWidth (1);
+ else
+ m_selRect.setWidth (m_selRect.width()-offset);
+ }
+ else if (contentsX() > 0)
+ {
+ offset = (int)(offset*m_zoom);
+ if (contentsX() > offset)
+ setContentsPos (contentsX()-offset, contentsY());
+ else
+ setContentsPos (0, contentsY());
+ }
+ else if (m_followMouse == false)
+ {
+ if (offset > m_selRect.x())
+ m_selRect.setX (0);
+ else
+ m_selRect.moveBy (-offset,0);
+ }
+ m_selRect.update();
+ }
+ else if (e->key() == QKeyEvent::Key_Right)
+ {
+ if (e->state() & QKeyEvent::ControlButton)
+ m_selRect.setRight (m_selRect.right()+offset);
+ else if (contentsX() < contentsWidth()-visibleWidth())
+ {
+ offset = (int)(offset*m_zoom);
+ if (contentsX()+offset < contentsWidth()-visibleWidth())
+ setContentsPos (contentsX()+offset, contentsY());
+ else
+ setContentsPos (contentsWidth()-visibleWidth(), contentsY());
+ }
+ else if (m_followMouse == false)
+ m_selRect.moveBy (offset,0);
+
+ m_selRect.update();
+ }
+ else if (e->key() == QKeyEvent::Key_Up)
+ {
+ if (e->state() & QKeyEvent::ControlButton)
+ {
+ if (offset >= m_selRect.height())
+ m_selRect.setHeight (1);
+ else
+ m_selRect.setHeight (m_selRect.height()-offset);
+ }
+ else if (contentsY() > 0)
+ {
+ offset = (int)(offset*m_zoom);
+ if (contentsY() > offset)
+ setContentsPos (contentsX(), contentsY()-offset);
+ else
+ setContentsPos (contentsX(), 0);
+ }
+ else if (m_followMouse == false)
+ {
+ if (offset > m_selRect.y())
+ m_selRect.setY (0);
+ else
+ m_selRect.moveBy (0, -offset);
+ }
+ m_selRect.update();
+ }
+ else if (e->key() == QKeyEvent::Key_Down)
+ {
+ if (e->state() & QKeyEvent::ControlButton)
+ m_selRect.setBottom (m_selRect.bottom()+offset);
+ else if (contentsY() < contentsHeight()-visibleHeight())
+ {
+ offset = (int)(offset*m_zoom);
+ if (contentsY()+offset < contentsHeight()-visibleHeight())
+ setContentsPos (contentsX(), contentsY()+offset);
+ else
+ setContentsPos (contentsX(), contentsHeight()-visibleHeight());
+ }
+ else if (m_followMouse == false)
+ m_selRect.moveBy (0, offset);
+ m_selRect.update();
+ }
+ else
+ e->ignore();
+}
+
+void KMagZoomView::keyReleaseEvent(QKeyEvent *e)
+{
+ if (e->key() == QKeyEvent::Key_Control)
+ m_ctrlKeyPressed = false;
+ else if (e->key() == QKeyEvent::Key_Shift)
+ m_shiftKeyPressed = false;
+ else
+ e->ignore();
+}
+
+void KMagZoomView::contextMenuEvent (QContextMenuEvent *e)
+{
+ emit contextMenu(e->globalPos());
+ e->accept();
+}
+
+void KMagZoomView::focusOutEvent(QFocusEvent *e)
+{
+ if(e->lostFocus() == TRUE) {
+ m_ctrlKeyPressed = false;
+ m_shiftKeyPressed = false;
+ }
+}
+
+// SLOTS
+
+/**
+ * This will fit the zoom view to the view window, thus using the maximum
+ * possible space in the window.
+ */
+void KMagZoomView::fitToWindow()
+{
+ QPoint currCenter = m_selRect.center();
+ QRect newRect = m_invertedMatrix.mapRect (QRect(0, 0, visibleWidth(), visibleHeight()));
+ m_selRect.setSize (newRect.size());
+ m_selRect.moveCenter(currCenter);
+ m_selRect.update();
+
+ viewport()->repaint(false);
+}
+
+void KMagZoomView::setFitToWindow(bool fit)
+{
+ m_fitToWindow = fit;
+ if (fit)
+ fitToWindow();
+}
+
+
+/**
+ * Grabs frame from X
+ */
+void KMagZoomView::grabFrame()
+{
+ // check refresh status
+ if (!m_refreshSwitch)
+ return;
+
+ // check if follow-mouse is enabled
+ if(m_followMouse && (m_mouseMode != ResizeSelection)) {
+ // in this case grab w.r.t the current mouse position
+ QPoint newCenter;
+
+ // set new center to be the current mouse position
+ m_selRect.moveCenter(QCursor::pos());
+ m_selRect.update();
+ }
+
+ //QRect r = pixmapRect();
+
+ // define a normalized rectangle
+ QRect selRect = m_selRect.normalize();
+
+ // grab screenshot from the screen and put it in the pixmap
+ m_grabbedPixmap = QPixmap::grabWindow(QApplication::desktop()->winId(), selRect.x(), selRect.y(),
+ selRect.width(), selRect.height());
+
+ // If the KMag window itself is in the screenshot, then it need to be filled with gray to avoid recursion
+ QPoint globalPos = viewport()->mapToGlobal (viewport()->rect().topLeft());
+ QRegion intersection (globalPos.x(), globalPos.y(), viewport()->width(), viewport()->height(), QRegion::Rectangle);
+ intersection &= QRegion (selRect, QRegion::Rectangle);
+
+ // We don't want to overpaint other windows that happen to be on top
+ obscuredRegion (intersection, topLevelWidget()->winId(), m_selRect.winId());
+ intersection.translate (-selRect.x(), -selRect.y());
+
+ QPainter painter (&m_grabbedPixmap, true);
+ QMemArray<QRect> rects (intersection.rects());
+ for (uint i = 0; i < rects.size(); i++)
+ painter.fillRect (rects[i], QBrush (QColor (128, 128, 128)));
+
+ // call repaint to display the newly grabbed image
+ QRect newSize = m_zoomMatrix.mapRect (m_grabbedPixmap.rect());
+ resizeContents (newSize.width(), newSize.height());
+ viewport()->repaint(false);
+}
+
+
+/**
+ * Updates the mouse cursor in the zoom view
+ */
+void KMagZoomView::updateMouseView()
+{
+ QPoint pos(QCursor::pos());
+ if(m_selRect.left() <= pos.x() && pos.x() <= m_selRect.right() &&
+ m_selRect.top() <= pos.y() && pos.y() <= m_selRect.bottom() &&
+ m_refreshSwitch)
+ viewport()->repaint(false);
+}
+
+/**
+ * Toggles the state of refreshing.
+ */
+void KMagZoomView::toggleRefresh()
+{
+ if(m_refreshSwitch) {
+ m_refreshSwitch = false;
+ m_grabTimer.stop();
+ m_mouseViewTimer.stop();
+ } else {
+ m_refreshSwitch = true;
+ m_grabTimer.start(1000/m_fps);
+ m_mouseViewTimer.start(40);
+ }
+}
+
+/**
+ * This function sets the zoom value to be used.
+ */
+void KMagZoomView::setZoom(float zoom)
+{
+ m_zoom = zoom;
+ updateMatrix();
+ viewport()->repaint();
+}
+
+/**
+ * This function sets the rotation value to be used.
+ */
+void KMagZoomView::setRotation(int rotation)
+{
+ m_rotation = rotation;
+ updateMatrix();
+ viewport()->repaint();
+}
+
+/**
+ * This function sets whether the magnified image is shown inverted
+ */
+void KMagZoomView::setInvertation(bool invert)
+{
+ m_invert = invert;
+ viewport()->repaint();
+}
+
+/**
+ * Set a new refresh rate.
+ */
+void KMagZoomView::setRefreshRate(float fps)
+{
+ if(fps < 0.1)
+ return;
+ m_fps = static_cast<unsigned int>(fps);
+
+ if(m_grabTimer.isActive())
+ m_grabTimer.changeInterval(static_cast<int>(1000.0/m_fps));
+}
+
+void KMagZoomView::showSelRect(bool show)
+{
+ m_selRect.alwaysVisible(show);
+ if(show) {
+ m_selRect.show();
+ } else if(m_mouseMode == Normal) {
+ m_selRect.hide();
+ }
+}
+
+/**
+ * Sets the selection rectangle to the given position.
+ */
+void KMagZoomView::setSelRectPos(const QRect & rect)
+{
+ m_selRect.setRect(rect.x(), rect.y(), rect.width(), rect.height());
+ m_selRect.update();
+ grabFrame();
+}
+
+bool KMagZoomView::showMouse(unsigned int type)
+{
+ if(type > m_showMouseTypes.count()-1)
+ return (false);
+ else
+ m_showMouse = type;
+
+ return(true);
+}
+
+unsigned int KMagZoomView::getShowMouseType() const
+{
+ return (m_showMouse);
+}
+
+QStringList KMagZoomView::getShowMouseStringList() const
+{
+ return (m_showMouseTypes);
+}
+
+
+/**
+ * Returns the image which is being displayed. Its again drawn by adding
+ * the mouse cursor if needed.
+ */
+QPixmap KMagZoomView::getPixmap()
+{
+ // show the pixel under mouse cursor
+ if(m_showMouse && !m_grabbedPixmap.isNull()) {
+ // Pixmap which will have the pixmap + mouse
+ QPixmap mousePixmap(m_grabbedPixmap);
+
+ // paint the mouse cursor w/o updating to a newer position
+ paintMouseCursor(&mousePixmap, calcMousePos(false));
+
+ return(mousePixmap);
+ } else { // no mouse cursor
+ return(m_grabbedPixmap);
+ }
+}
+
+/**
+ * Update the magnification matrix
+ */
+void KMagZoomView::updateMatrix()
+{
+ // update selection window size if necessary
+ if (m_fitToWindow)
+ fitToWindow();
+
+ // recompute the zoom matrix
+ m_zoomMatrix.reset();
+ m_zoomMatrix.scale(m_zoom, m_zoom);
+ m_zoomMatrix.rotate(m_rotation);
+
+ bool inverted;
+ m_invertedMatrix = m_zoomMatrix.invert (&inverted);
+
+}
diff --git a/kmag/kmagzoomview.h b/kmag/kmagzoomview.h
new file mode 100644
index 0000000..a863ad6
--- /dev/null
+++ b/kmag/kmagzoomview.h
@@ -0,0 +1,249 @@
+/***************************************************************************
+ kmagview.h - description
+ -------------------
+ begin : Mon Feb 12 23:45:41 EST 2001
+ copyright : (C) 2001-2003 by Sarang Lakare
+ email : sarang#users.sf.net
+ copyright : (C) 2003-2005 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KMagZoomView_h_
+#define KMagZoomView_h_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// include files for Qt
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+#include <qscrollview.h>
+#include <qstringlist.h>
+#include <qrect.h>
+#include <qcursor.h>
+
+//class KMagSelRect;
+#include "kmagselrect.h"
+
+/**
+ * The KMagZoomView class provides the view widget for the KmagApp instance.
+ *
+ * @author Olaf Schmikt <ojschmidt@kde.org>
+ * @author Sarang Lakare <sarang#users.sourceforge.net>
+ */
+class KMagZoomView : public QScrollView
+{
+ Q_OBJECT
+ public:
+ /// Constructor for the main view
+ KMagZoomView(QWidget *parent = 0, const char *name=0);
+
+ /// Destructor for the main view
+ ~KMagZoomView();
+
+ /// Toggles the refreshing of the window
+ void toggleRefresh();
+
+ /// Returns the currently displayed zoomed view
+ QPixmap getPixmap();
+
+ /// Returns the state of the refresh switch
+ bool getRefreshStatus() const { return m_refreshSwitch; };
+
+ /// Returns teh status of followMouse
+ bool getFollowMouse() const { return m_followMouse; };
+
+ /// Get the status of "show rect. always"
+ bool getShowSelRect() const { return (m_selRect.getAlwaysVisible()); };
+
+ /// Get the coordinates of the selection rectangle
+ QRect getSelRectPos() const { return static_cast<QRect>(m_selRect); };
+
+ /// Returns the current state of show mouse
+ unsigned int getShowMouseType() const;
+
+ /// Returns the different ways of showing mouse cursor
+ QStringList getShowMouseStringList() const;
+
+ /// Returns the status of "fit to window" option
+ bool getFitToWindow() const { return (m_fitToWindow); };
+
+ public slots:
+
+ /// Sets zoom to the given value
+ void setZoom(float zoom = 0.0);
+
+ /// Sets the rotation to the given value
+ void setRotation(int rotation = 0);
+
+ /// Sets whether the magnified image is shown inverted
+ void setInvertation(bool invert);
+
+ /// Grabs a frame from the given portion of the display
+ void grabFrame();
+
+ /// Update the mouse cursor in the zoom view
+ void updateMouseView();
+
+ /// Set grab-window-follows-mouse mode
+ void followMouse(bool follow = true);
+
+ /// Shows/Hides the selection marker
+ void showSelRect(bool show=true);
+
+ /// Set the position of the selection region to the given pos
+ void setSelRectPos(const QRect & rect);
+
+ /// Set the refresh rate in fps (frames per second)
+ void setRefreshRate(float fps);
+
+ /// Shows/Hides mouse cursor in the zoomed view
+ bool showMouse(unsigned int type);
+
+ /// Set the status of "fit to window" option
+ void setFitToWindow (bool fit=true);
+
+ /// Fits the zoom view to the zoom view window
+ void fitToWindow();
+
+ signals:
+ void contextMenu(QPoint pos);
+
+ protected:
+ /// Called when the widget is hidden
+ void hideEvent( QHideEvent * e);
+
+ /// Called when the widget is shown
+ void showEvent( QShowEvent * e);
+
+ /// Called when the widget has been resized
+ void resizeEvent(QResizeEvent *e);
+
+ /// Called when the widget is to be repainted
+ void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph );
+
+ /// This function calculates the mouse position relative to the image
+ QPoint calcMousePos(bool updateMousePos=true);
+
+ /// This function draws the mouse cursor
+ void paintMouseCursor(QPaintDevice *dev, QPoint mousePos);
+
+ /// Called when mouse click is detected
+ void mousePressEvent (QMouseEvent *e);
+
+ /// Called when mouse is moved
+ void mouseMoveEvent(QMouseEvent *e);
+
+ /// Mouse button release event handler
+ void mouseReleaseEvent(QMouseEvent *e);
+
+ /// Mouse button release event handler
+ void keyPressEvent(QKeyEvent *e);
+
+ /// Mouse button release event handler
+ void keyReleaseEvent(QKeyEvent *e);
+
+ /// Catch context menu events
+ void contextMenuEvent (QContextMenuEvent *e);
+
+ /// Mouse button release event handler
+ void focusOutEvent(QFocusEvent *e);
+
+ /// Returns the rectangle where the pixmap will be drawn
+ QRect pixmapRect();
+
+ private:
+ /// Stores the pixmap grabbed from the screen - to be zoomed
+ QPixmap m_grabbedPixmap;
+
+ /// The selected rectangle which is to be grabbed
+ KMagSelRect m_selRect;
+
+ /// Grabs a window when the timer goes off
+ QTimer m_grabTimer;
+
+ /// Updates the mouse view
+ QTimer m_mouseViewTimer;
+
+ /// Zoom matrix
+ QWMatrix m_zoomMatrix;
+
+ /// Inverted zoom matrix
+ QWMatrix m_invertedMatrix;
+
+ /// Saves the mouse position when a button is clicked and b4 the cursor is moved to new position
+ QPoint m_oldMousePos;
+
+ /// Saves the center of the grab window
+ QPoint m_oldCenter;
+
+ /// Possible modes for the mouse to be in
+ enum KMagMouseMode {
+ Normal,
+ StartSelect,
+ ResizeSelection,
+ MoveSelection,
+ GrabSelection
+ };
+
+ /// The current mode which the mouse is
+ KMagMouseMode m_mouseMode;
+
+ /// stores the state of the Ctrl key
+ bool m_ctrlKeyPressed;
+
+ /// stores the state of the Shift key
+ bool m_shiftKeyPressed;
+
+ /// Store the more recent updated cursor position
+ QPoint m_latestCursorPos;
+
+ /// Various ways of showing mouse cursor
+ QStringList m_showMouseTypes;
+
+ // configuration options:
+
+ /// To follow mouse motion or not when no key is pressed
+ bool m_followMouse;
+
+ /// State of refreshing - on or off
+ bool m_refreshSwitch;
+
+ /// Stores the state of the refresh switch on hide event
+ bool m_refreshSwitchStateOnHide;
+
+ /// Show mouse cursor type - 0 : do not show, non zero: show
+ unsigned int m_showMouse;
+
+ /// Frames per second for refresh
+ unsigned int m_fps;
+
+ /// Stores the amount to zoom the pixmap
+ float m_zoom;
+
+ /// Stores the degrees to rotate the pixmap
+ int m_rotation;
+
+ /// Whether the magnified image is to be shown inverted
+ int m_invert;
+
+ /// Fit the zoom view to the zoom window
+ bool m_fitToWindow;
+
+ /// Update the magnification matrix
+ void updateMatrix();
+};
+
+#endif // KMagZoomView_h_
diff --git a/kmag/lo16-app-kmag.png b/kmag/lo16-app-kmag.png
new file mode 100644
index 0000000..91a27a6
--- /dev/null
+++ b/kmag/lo16-app-kmag.png
Binary files differ
diff --git a/kmag/lo32-app-kmag.png b/kmag/lo32-app-kmag.png
new file mode 100644
index 0000000..bffa05d
--- /dev/null
+++ b/kmag/lo32-app-kmag.png
Binary files differ
diff --git a/kmag/main.cpp b/kmag/main.cpp
new file mode 100644
index 0000000..f0d0c31
--- /dev/null
+++ b/kmag/main.cpp
@@ -0,0 +1,81 @@
+/***************************************************************************
+ main.cpp - description
+ -------------------
+ begin : Mon Feb 12 23:45:41 EST 2001
+ copyright : (C) 2001-2003 by Sarang Lakare
+ email : sarang#users.sf.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+
+#include "kmag.h"
+
+#include "version.h"
+
+KmagApp *kmagapp;
+
+// Not needed, not used.
+//static const char description[] =
+// I18N_NOOP("Kmag");
+// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE
+
+
+static KCmdLineOptions options[] =
+{
+ { "+[File]", I18N_NOOP("File to open"), 0 },
+ KCmdLineLastOption
+ // INSERT YOUR COMMANDLINE OPTIONS HERE
+};
+
+int main(int argc, char *argv[])
+{
+ // about the application
+ KAboutData *aboutData = new KAboutData("kmag", I18N_NOOP("KMagnifier"), KMAG_VERSION,
+ I18N_NOOP("Screen magnifier for the K Desktop Environment (KDE)"),
+ KAboutData::License_GPL,
+ "(C) 2001-2003, Sarang Lakare","",
+ "http://kmag.sourceforge.net");
+
+ // about the authors
+ aboutData->addAuthor("Sarang Lakare",
+ I18N_NOOP("Rewrite and current maintainer"),"sarang@users.sf.net",
+ "http://www.cs.sunysb.edu/~lsarang/linux");
+ aboutData->addAuthor("Michael Forster",
+ I18N_NOOP("Original idea and author (KDE1)"), "forster@fmi.uni-passau.de");
+
+ aboutData->addCredit("Olaf Schmidt", I18N_NOOP("Rework of the user interface, improved selection window, speed optimisation, rotation, bug fixes"), "ojschmidt@kde.org");
+ aboutData->addCredit("Claudiu Costin", I18N_NOOP("Some tips"), "claudiuc@work.ro",
+ "http://www.ro.kde.org");
+
+ KCmdLineArgs::init( argc, argv, aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+
+ KApplication app;
+
+ if (app.isRestored())
+ {
+ RESTORE(KmagApp);
+ }
+ else
+ {
+ kmagapp = new KmagApp();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ args->clear();
+ }
+
+ return app.exec();
+}
diff --git a/kmag/version.h b/kmag/version.h
new file mode 100644
index 0000000..cc1a9ce
--- /dev/null
+++ b/kmag/version.h
@@ -0,0 +1,8 @@
+// KMag Version Information
+//
+#ifndef kmag_version_h
+#define kmag_version_h
+
+#define KMAG_VERSION "1.0"
+
+#endif /*version_h*/
diff --git a/kmousetool/AUTHORS b/kmousetool/AUTHORS
new file mode 100644
index 0000000..9b681c6
--- /dev/null
+++ b/kmousetool/AUTHORS
@@ -0,0 +1,24 @@
+Current maintainer:
+Gunnar Schmidt <gunnar@schmi-dt.de>, 2003
+
+Contributor:
+Olaf Schmidt <ojschmidt@kde.org>, 2003
+
+
+KMouseTool was created by Jeff Roush <jeff@mousetool.com>, 2002
+Documentation initally written by Jeff Roush <jeff@mousetool.com>, 2002
+
+The clever Smart Drag idea was suggested by Joe Betts. Thanks, Joe!
+
+The idea for MouseTool came to me when I was thinking about
+head-tracking systems that allow you to move a cursor using
+your head orientation, and then send clicks when you pause.
+As far as I know, I was the first person to use this technique
+with an ordinary mouse, but it is possible that I am wrong about that.
+There are now other programs available for Windows and Macs that
+do this; I know that some were developed after MouseTool, but
+it is likely others came before.
+
+Other ideas in MouseTool for Windows that I hope to port to KDE were
+either suggested by MouseTool users or came out of email discussions
+with users.
diff --git a/kmousetool/COPYING b/kmousetool/COPYING
new file mode 100644
index 0000000..c13faf0
--- /dev/null
+++ b/kmousetool/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/kmousetool/ChangeLog b/kmousetool/ChangeLog
new file mode 100644
index 0000000..86bfeaa
--- /dev/null
+++ b/kmousetool/ChangeLog
@@ -0,0 +1,9 @@
+1-16-03
+Version 1.11: Stroke handling, several bug fixes. Uploaded to KDE CVS.
+6-27-02
+Version 1.05: Added doc/ directory back to project. No other change in source.
+6-21-02
+Version 1.01: increased maximum allowable value for Drag Time --
+now it is equal to the Dwell Time.
+5-22-02
+Initial release, version 1.0
diff --git a/kmousetool/INSTALL b/kmousetool/INSTALL
new file mode 100644
index 0000000..02a4a07
--- /dev/null
+++ b/kmousetool/INSTALL
@@ -0,0 +1,167 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 4. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/kmousetool/Makefile.am b/kmousetool/Makefile.am
new file mode 100644
index 0000000..c1dbee1
--- /dev/null
+++ b/kmousetool/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = kmousetool
diff --git a/kmousetool/README b/kmousetool/README
new file mode 100644
index 0000000..c1863ac
--- /dev/null
+++ b/kmousetool/README
@@ -0,0 +1,83 @@
+MouseTool is a program that clicks the mouse for you.
+
+I designed it to help relieve the pain that clicking mouse buttons can cause.
+
+For more information, see www.mousetool.com
+
+
+How To Use MouseTool
+
+1 It's simple: MouseTool watches as you move the mouse. When you stop, it clicks.
+
+2 Practice with this. When you are comfortable with it, move on to Smart Drag.
+
+3 When Smart Drag is enabled, MouseTool pauses after it clicks down. If you
+ move the mouse, it waits until you stop moving before it clicks up.
+ This takes more practice, but if I can learn to do it without thinking, so can you.
+
+4 KMouseTool 1.1 supports strokes. When you enable strokes, a slow move to the
+ right and back, followed by a pause, will generate a right-click. A slow move
+ left and back will generate a double click. (Strokes are specified in
+ ~/.kde3/share/config/kmousetool_strokes.txt. This file is generated by KMouseTool
+ the first time it is run, but can be modified afterwards.)
+
+MouseTool Options:
+
+* Checkboxes:
+ Smart Drag -- enables or disables Smart Drag. Disabled is easier, so this is default.
+ Audible Click -- plays a sound when MouseTool clicks down. This helps, especially
+ with Smart Drag, but as of version 0.8, the latency is too high.
+ By the time you hear the click, you're doing something else.
+ This will be fixed in the next version.
+ Start with KDE -- When this is enabled, MouseTool will start each time KDE starts.
+ Enable Strokes -- When this is enabled, you can generate right- or double-clicks
+ using mouse strokes.
+
+* Times
+ Dwell Time -- The time you have to pause before MouseTool clicks.
+ Drag Time -- (When Smart Drag is enabled) the time MouseTool waits, after it clicks
+ down, before it clicks back up if you don't move the mouse.
+ Apply Times Button -- After changing either time, you must click this button.
+
+* Start Button -- Starts MouseTool. (Well, duh.)
+ When it says "stop", clicking it will stop MouseTool. (Duh, again.)
+
+* command line -- MouseTool has no command line options.
+ It does remembers its state when it is restarted, though.
+
+* Hotkeys -- None yet (as of version 1.1). They are very useful, though, and may be added.
+
+
+Credit:
+
+The idea for MouseTool came to me when I was thinking about head-tracking
+systems that allow you to move a cursor using your head orientation, and then
+send clicks when you pause. As far as I know, I was the first person to use
+this technique with an ordinary mouse, but it is quite possible that I am wrong
+about that. There are now other programs available for Windows and Macs that
+do this; I know that some were developed after MouseTool, but it is likely
+others came before.
+
+If you know of another Linux- or Unix-based program that does this, please let
+me know (at jeff@mousetool.com)
+
+The clever idea for Smart Drag was suggested by Joe Betts. Thanks, Joe!
+
+Other ideas in MouseTool for Windows that I hope to port to KDE were either
+suggested by MouseTool users or came out of email discussions with users.
+
+
+
+Bugs and issues:
+Emacs - Smart Drag and Emacs menus don't mix well; the menus don't stay visible
+ long enough to use. XEmacs seems to work fine. Gvim also works well.
+
+Taskbar - When you drag the taskbar using Smart Drag in KDE 2.x, kmousetool won't release
+ the drag. This can be scary if you're not expecting it, but simply clicking
+ the mouse button manually fixes the problem. KDE 3.x does not have this problem.
+
+ This seems to be an issue with the internals of KDE or QT code, and similar
+ things happen in Windows. I haven't looked into it much under KDE, but on
+ Windows it happens when mousetool's timer stops while Windows waits for an
+ upclick, and the upclick never happens because the timer is stopped;
+ I'm sure the same thing is happening under KDE.
diff --git a/kmousetool/TODO b/kmousetool/TODO
new file mode 100644
index 0000000..7ec2ccc
--- /dev/null
+++ b/kmousetool/TODO
@@ -0,0 +1,10 @@
+Currently version 1.11
+
+For version 2.0:
+Use mcop sound.
+Context awareness
+Visual click aid
+Place on taskbar, remove window in desktop area
+Hotkeys
+Improve stroke handling
+
diff --git a/kmousetool/kmousetool.lsm b/kmousetool/kmousetool.lsm
new file mode 100644
index 0000000..361c325
--- /dev/null
+++ b/kmousetool/kmousetool.lsm
@@ -0,0 +1,14 @@
+Begin3
+Title: KMouseTool
+Version: 1.11
+Entered-date: 1/16/03
+Description: Clicks the mouse for you, reducing hand pain
+Keywords: ergonomic, mouse, tendonitis, carpal tunnel syndrome
+Author: Jeff Roush <jeff@mousetool.com>
+Maintained-by: Jeff Roush <jeff@mousetool.com>
+Primary-site: http://www.mousetool.com
+Home-page: http://www.mousetool.com
+Original-site: http://www.mousetool.com
+Platforms: Linux and other Unices
+Copying-policy: GNU Public License
+End
diff --git a/kmousetool/kmousetool/Makefile.am b/kmousetool/kmousetool/Makefile.am
new file mode 100644
index 0000000..72c6a08
--- /dev/null
+++ b/kmousetool/kmousetool/Makefile.am
@@ -0,0 +1,29 @@
+bin_PROGRAMS = kmousetool
+
+kmousetool_SOURCES = kmousetoolui.ui mtstroke.cpp kmousetool.cpp main.cpp
+kmousetool_LDADD = -lXtst $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) -lXext -lX11 $(LIBSOCKET)
+
+SUBDIRS = pics
+
+EXTRA_DIST = main.cpp version.h kmousetool.cpp kmousetool.h kmousetool.desktop mtstroke.cpp mtstroke.h mousetool_tap.wav
+
+kmousetooldir = $(kde_appsdir)/Applications
+kmousetool_DATA = kmousetool.desktop
+
+sounddatadir = $(kde_datadir)/kmousetool/sounds
+sounddata_DATA = mousetool_tap.wav
+
+# set the include path for X, qt and KDE
+INCLUDES= $(all_includes)
+
+METASOURCES = AUTO
+
+# the library search path.
+kmousetool_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+messages: rc.cpp
+ LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) $$LIST -o $(podir)/kmousetool.pot; \
+ fi
+
diff --git a/kmousetool/kmousetool/Xmd_kmousetool.h b/kmousetool/kmousetool/Xmd_kmousetool.h
new file mode 100644
index 0000000..2a35eb8
--- /dev/null
+++ b/kmousetool/kmousetool/Xmd_kmousetool.h
@@ -0,0 +1,201 @@
+/* $XFree86: xc/include/Xmd.h,v 3.9 2001/01/17 17:53:11 dawes Exp $ */
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+#ifndef XMD_H
+#define XMD_H 1
+/* $Xorg: Xmd.h,v 1.3 2000/08/18 04:05:44 coskrey Exp $ */
+/*
+ * Xmd.h: MACHINE DEPENDENT DECLARATIONS.
+ */
+
+/*
+ * Special per-machine configuration flags.
+ */
+#ifdef CRAY
+#define WORD64 /* 64-bit architecture */
+#endif
+#if defined(__alpha) || defined(__alpha__) || \
+ defined(__ia64__) || defined(ia64)
+#define LONG64 /* 32/64-bit architecture */
+#endif
+#ifdef __sgi
+#if (_MIPS_SZLONG == 64)
+#define LONG64
+#endif
+#endif
+
+/*
+ * Stuff to handle large architecture machines; the constants were generated
+ * on a 32-bit machine and must coorespond to the protocol.
+ */
+#ifdef WORD64
+#define MUSTCOPY
+#endif /* WORD64 */
+
+
+/*
+ * Definition of macro used to set constants for size of network structures;
+ * machines with preprocessors that can't handle all of the sz_ symbols
+ * can define this macro to be sizeof(x) if and only if their compiler doesn't
+ * pad out structures (esp. the xTextElt structure which contains only two
+ * one-byte fields). Network structures should always define sz_symbols.
+ *
+ * The sz_ prefix is used instead of something more descriptive so that the
+ * symbols are no more than 32 characters long (which causes problems for some
+ * compilers and preprocessors).
+ *
+ * The extra indirection in the __STDC__ case is to get macro arguments to
+ * expand correctly before the concatenation, rather than afterward.
+ */
+#if ((defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define _SIZEOF(x) sz_##x
+#define SIZEOF(x) _SIZEOF(x)
+#else
+#define SIZEOF(x) sz_/**/x
+#endif /* if ANSI C compiler else not */
+
+/*
+ * Bitfield suffixes for the protocol structure elements, if you
+ * need them. Note that bitfields are not guarranteed to be signed
+ * (or even unsigned) according to ANSI C.
+ */
+#ifdef WORD64
+typedef long INT64;
+typedef unsigned long CARD64;
+#define B32 :32
+#define B16 :16
+#ifdef UNSIGNEDBITFIELDS
+typedef unsigned int INT32;
+typedef unsigned int INT16;
+#else
+#ifdef __STDC__
+typedef signed int INT32;
+typedef signed int INT16;
+#else
+typedef int INT32;
+typedef int INT16;
+#endif
+#endif
+#else
+#define B32
+#define B16
+#ifdef LONG64
+//typedef long INT64;
+typedef int INT32;
+#else
+//typedef long INT32;
+#endif
+typedef short INT16;
+#endif
+
+#if defined(__STDC__) || defined(sgi) || defined(AIXV3)
+typedef signed char INT8;
+#else
+typedef char INT8;
+#endif
+
+#ifdef LONG64
+typedef unsigned long CARD64;
+typedef unsigned int CARD32;
+#else
+typedef unsigned long CARD32;
+#endif
+typedef unsigned short CARD16;
+typedef unsigned char CARD8;
+
+typedef CARD32 BITS32;
+typedef CARD16 BITS16;
+
+#ifndef __EMX__
+typedef CARD8 BYTE;
+typedef CARD8 BOOL;
+#else /* __EMX__ */
+/*
+ * This is bad style, but the central include file <os2.h> declares them
+ * as well
+ */
+#define BYTE CARD8
+#define BOOL CARD8
+#endif /* __EMX__ */
+
+/*
+ * definitions for sign-extending bitfields on 64-bit architectures
+ */
+#if defined(WORD64) && defined(UNSIGNEDBITFIELDS)
+#define cvtINT8toInt(val) (((val) & 0x00000080) ? ((val) | 0xffffffffffffff00) : (val))
+#define cvtINT16toInt(val) (((val) & 0x00008000) ? ((val) | 0xffffffffffff0000) : (val))
+#define cvtINT32toInt(val) (((val) & 0x80000000) ? ((val) | 0xffffffff00000000) : (val))
+#define cvtINT8toShort(val) cvtINT8toInt(val)
+#define cvtINT16toShort(val) cvtINT16toInt(val)
+#define cvtINT32toShort(val) cvtINT32toInt(val)
+#define cvtINT8toLong(val) cvtINT8toInt(val)
+#define cvtINT16toLong(val) cvtINT16toInt(val)
+#define cvtINT32toLong(val) cvtINT32toInt(val)
+#else
+#define cvtINT8toInt(val) (val)
+#define cvtINT16toInt(val) (val)
+#define cvtINT32toInt(val) (val)
+#define cvtINT8toShort(val) (val)
+#define cvtINT16toShort(val) (val)
+#define cvtINT32toShort(val) (val)
+#define cvtINT8toLong(val) (val)
+#define cvtINT16toLong(val) (val)
+#define cvtINT32toLong(val) (val)
+#endif /* WORD64 and UNSIGNEDBITFIELDS */
+
+
+
+#ifdef MUSTCOPY
+/*
+ * This macro must not cast or else pointers will get aligned and be wrong
+ */
+#define NEXTPTR(p,t) (((char *) p) + SIZEOF(t))
+#else /* else not MUSTCOPY, this is used for 32-bit machines */
+/*
+ * this version should leave result of type (t *), but that should only be
+ * used when not in MUSTCOPY
+ */
+#define NEXTPTR(p,t) (((t *)(p)) + 1)
+#endif /* MUSTCOPY - used machines whose C structs don't line up with proto */
+
+#endif /* XMD_H */
diff --git a/kmousetool/kmousetool/kmousetool.cpp b/kmousetool/kmousetool/kmousetool.cpp
new file mode 100644
index 0000000..ee27ba4
--- /dev/null
+++ b/kmousetool/kmousetool/kmousetool.cpp
@@ -0,0 +1,641 @@
+/***************************************************************************
+ kmousetool.cpp - description
+ -------------------
+ begin : Sun Jan 20 23:27:58 PST 2002
+ copyright : (C) 2002-2003 by Jeff Roush
+ email : jeff@mousetool.com
+ copyright : (C) 2003 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ copyright : (C) 2003 by Gunnar Schmi Dt
+ email : gunnar@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include "Xmd_kmousetool.h"
+#include "kmousetool.h"
+#include "kmousetool.moc"
+#include <kconfig.h>
+#include <X11/Intrinsic.h> /* Intrinsics Definitions*/
+#include <X11/StringDefs.h> /* Standard Name-String definitions*/
+#include <X11/extensions/xtestext1.h> /* Standard Name-String definitions*/
+#include <X11/extensions/XTest.h> /* Standard Name-String definitions*/
+#include <kdialog.h>
+#include <klocale.h>
+#include <qpushbutton.h>
+#include <qpoint.h>
+#include <qnamespace.h>
+#include <kmessagebox.h>
+#include <kaudioplayer.h>
+#include <kstandarddirs.h>
+#include <qsound.h>
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <ksystemtray.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+#include <knuminput.h>
+#include <kpopupmenu.h>
+#include <kaboutapplication.h>
+
+//#include <arts/soundserver.h>
+#include <netwm.h>
+
+#include <iostream>
+
+#include "mtstroke.h"
+
+//using namespace Arts;
+
+int currentXPosition;
+int currentYPosition;
+
+//using namespace std;
+
+#undef long
+
+/**
+* Gnarly X functions
+*/
+void queryPointer(Window *pidRoot, int *pnRx, int *pnRy, int *pnX, int *pnY, unsigned int *puMask);
+int CursorHasMoved(int minMovement);
+void LeftClick();
+void RightClick();
+void DoubleClick();
+void LeftDn();
+void LeftUp();
+
+// Declarations
+Display *display;
+
+//SimpleSoundServer sound_server(Reference("global:Arts_SimpleSoundServer"));
+
+
+void KMouseTool::init_vars()
+{
+ continue_timer = 1;
+ tick_count = 0;
+ max_ticks = dwell_time+1;
+ mouse_is_down = FALSE;
+
+ loadOptions();
+
+ // If the ~/.mousetool directory doesn't exist, create it
+// mSoundFileName = QDir::homeDirPath();
+ mSoundFileName = locate("appdata", "sounds/mousetool_tap.wav");
+ mplayer = new KAudioPlayer(mSoundFileName);
+
+
+ // find application file
+ appfilename = locate("exe", "kmousetool");
+
+ // find the user's autostart directory
+ autostartdirname = KGlobalSettings::autostartPath();
+
+ // SimpleSoundServer server(Reference("global:Arts_SimpleSoundServer"));
+// sound_server(Reference("global:Arts_SimpleSoundServer"));
+
+ QDesktopWidget *d = QApplication::desktop();
+ int w = d->width();
+ int h = d->height();
+ MTStroke::setUpperLeft(0,0);
+ MTStroke::setUpperRight(w-1,0);
+ MTStroke::setLowerLeft(0,h-1);
+ MTStroke::setLowerRight(w-1,h-1);
+}
+
+void KMouseTool::resetSettings()
+{
+ cbDrag ->setChecked(smart_drag_on);
+ cbStart->setChecked(isAutostart());
+ cbClick->setChecked(playSound);
+ cbStroke->setChecked(strokesEnabled);
+ movementEdit->setValue(min_movement);
+ dwellTimeEdit->setValue(dwell_time);
+ dragTimeEdit->setValue(drag_time);
+ settingsChanged();
+}
+
+void KMouseTool::setDefaultSettings()
+{
+ cbDrag ->setChecked(false);
+ cbStart->setChecked(false);
+ cbClick->setChecked(false);
+ cbStroke->setChecked(false);
+ movementEdit->setValue(5);
+ dwellTimeEdit->setValue(5);
+ dragTimeEdit->setValue(3);
+ settingsChanged();
+}
+
+
+void KMouseTool::timerEvent( QTimerEvent * )
+{
+ if (!mousetool_is_running)
+ return;
+
+ if (!continue_timer) {
+ killTimers();
+ return;
+ }
+
+ max_ticks = dwell_time + drag_time;
+ stroke.addPt(currentXPosition, currentYPosition);
+
+ moving = moving?CursorHasMoved(1):CursorHasMoved(min_movement);
+ if (moving) {
+ if (mousetool_just_started) {
+ mousetool_just_started = false;
+ tick_count = max_ticks;
+ }
+ else
+ tick_count = 0;
+ return;
+ }
+
+ if (tick_count<max_ticks)
+ tick_count++;
+
+
+ // If the mouse has paused ...
+ if (tick_count==dwell_time) {
+ int strokeType = stroke.getStrokeType();
+
+ // if we're dragging the mouse, ignore stroke type
+ if (mouse_is_down) {
+ normalClick();
+ return;
+ }
+
+ if (!strokesEnabled) {
+ normalClick();
+ return;
+ }
+ if (strokeType == MTStroke::DontClick)
+ return;
+ if (strokeType==MTStroke::bumped_mouse)
+ return;
+
+ if (strokeType==MTStroke::RightClick || strokeType==MTStroke::UpperRightStroke)
+ RightClick();
+ else if (strokeType==MTStroke::DoubleClick || strokeType==MTStroke::LowerLeftStroke)
+ DoubleClick();
+ else
+ normalClick();
+ }
+}
+
+void KMouseTool::normalClick()
+{
+ if (smart_drag_on) {
+ if (!mouse_is_down) {
+ LeftDn();
+ mouse_is_down = TRUE;
+ tick_count = 0;
+ playTickSound();
+ }
+ else if (mouse_is_down) {
+ LeftUp();
+ mouse_is_down = FALSE;
+ tick_count = max_ticks;
+ }
+ }
+ else {
+ // not smart_drag_on
+ LeftClick();
+ playTickSound();
+ }
+}
+
+// This function isn't happy yet.
+void KMouseTool::playTickSound()
+{
+ if (!playSound)
+ return;
+
+ mplayer->play();
+ // This is a bit slow.
+// KAudioPlayer::play(mSoundFileName);
+ return;
+
+ // the solution seems to be to use MCOP,
+ // but SimpleSoundServer is not cooperating
+
+ // When using the following code, make sure to link with
+ // Put " -lsoundserver_idl" in the linker options in KDevelop.
+
+// SimpleSoundServer server = SimpleSoundServer::_fromString("global:Arts_SimpleSoundServer");
+// SimpleSoundServer *ss = new SimpleSoundServer(Reference("global:Arts_SimpleSoundServer"));
+// SimpleSoundServer sound_server2(Reference("global:Arts_SimpleSoundServer"));
+
+// if(sound_server.isNull())
+// return;
+// sound_server.play(mSoundFileName.latin1());
+
+ // Another approach is to try using QSound.
+ // QSound depends on Network Audio Server, which doesn't seem to work on my Debian Woody system.
+ // I haven't spent much time working on it, though.
+// QSound::play(mSoundFileName);
+}
+
+KMouseTool::KMouseTool(QWidget *parent, const char *name) : KMouseToolUI(parent, name)
+{
+ init_vars();
+ resetSettings();
+
+ connect(movementEdit, SIGNAL(valueChanged(int)), this, SLOT(settingsChanged()));
+ connect(dwellTimeEdit, SIGNAL(valueChanged(int)), this, SLOT(settingsChanged()));
+ connect(dragTimeEdit, SIGNAL(valueChanged(int)), this, SLOT(settingsChanged()));
+ connect(cbDrag, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
+ connect(cbStroke, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
+ connect(cbClick, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
+ connect(cbStart, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
+
+ connect(buttonStartStop, SIGNAL(clicked()), this, SLOT(startStopSelected()));
+ buttonDefault->setGuiItem(KStdGuiItem::defaults());
+ connect(buttonDefault, SIGNAL(clicked()), this, SLOT(defaultSelected()));
+ connect(buttonReset, SIGNAL(clicked()), this, SLOT(resetSelected()));
+ buttonApply->setGuiItem(KStdGuiItem::apply());
+ connect(buttonApply, SIGNAL(clicked()), this, SLOT(applySelected()));
+ buttonHelp->setGuiItem(KStdGuiItem::help());
+ connect(buttonHelp, SIGNAL(clicked()), this, SLOT(helpSelected()));
+ buttonClose->setGuiItem(KStdGuiItem::close());
+ connect(buttonClose, SIGNAL(clicked()), this, SLOT(closeSelected()));
+#if KDE_VERSION >= KDE_MAKE_VERSION (3,1,90)
+ buttonQuit->setGuiItem(KStdGuiItem::quit());
+#endif // KDE 3.2
+ connect(buttonQuit, SIGNAL(clicked()), this, SLOT(quitSelected()));
+
+ // When we first start, it's nice to not click immediately.
+ // So, tell MT we're just starting
+ mousetool_just_started = true;
+
+ startTimer(100);
+ trayIcon = new KMouseToolTray (this, "systemTrayIcon");
+ updateStartStopText ();
+ connect(trayIcon, SIGNAL(startStopSelected()), this, SLOT(startStopSelected()));
+ connect(trayIcon, SIGNAL(configureSelected()), this, SLOT(configureSelected()));
+ connect(trayIcon, SIGNAL(aboutSelected()), this, SLOT(aboutSelected()));
+ connect(trayIcon, SIGNAL(helpSelected()), this, SLOT(helpSelected()));
+ connect(trayIcon, SIGNAL(quitSelected()), this, SLOT(quitSelected()));
+
+ aboutDlg = new KAboutApplication (0, "KMouseToolDlg", false);
+}
+
+KMouseTool::~KMouseTool()
+{
+}
+
+// *********************************************************
+// Raw X functions
+// Begin mouse monitoring and event generation code.
+// these should be moved to a separate file.
+void LeftClick()
+{
+ XTestFakeButtonEvent(display, 1, TRUE, 0);
+ XTestFakeButtonEvent(display, 1, FALSE, 0);
+}
+
+void DoubleClick()
+{
+ XTestFakeButtonEvent(display, 1, TRUE, 0);
+ XTestFakeButtonEvent(display, 1, FALSE, 100);
+ XTestFakeButtonEvent(display, 1, TRUE, 200);
+ XTestFakeButtonEvent(display, 1, FALSE, 300);
+}
+
+void RightClick()
+{
+ XTestFakeButtonEvent(display, 3, TRUE, 0);
+ XTestFakeButtonEvent(display, 3, FALSE, 0);
+}
+
+
+void LeftDn()
+{
+ XTestFakeButtonEvent(display, 1, TRUE, 0);
+}
+
+
+void LeftUp()
+{
+ XTestFakeButtonEvent(display, 1, FALSE, 0);
+}
+
+
+void queryPointer(Window *pidRoot, int *pnRx, int *pnRy, int *pnX, int *pnY, unsigned int *puMask)
+{
+ Window id2, idRoot;
+ int screen_num;
+
+ screen_num = DefaultScreen(display);
+ idRoot = RootWindow(display,screen_num);
+ XQueryPointer(display, idRoot, &idRoot, &id2, pnRx, pnRy, pnX, pnY, puMask);
+
+ *pidRoot = idRoot;
+}
+
+// return 1 if cursor has moved, 0 otherwise
+int CursorHasMoved (int minMovement)
+{
+ static int nOldRootX = -1;
+ static int nOldRootY = -1;
+
+// XEvent evButtonEvent;
+ Window idRootWin;
+ int nRootX, nRootY, nWinX, nWinY;
+ unsigned int uintMask;
+
+ queryPointer(&idRootWin, &nRootX, &nRootY, &nWinX, &nWinY, &uintMask);
+
+ int nRes = 0;
+ if ((nRootX>nOldRootX?nRootX-nOldRootX:nOldRootX-nRootX) >= minMovement)
+ nRes = 1;
+ if ((nRootY>nOldRootY?nRootY-nOldRootY:nOldRootY-nRootY) >= minMovement)
+ nRes = 1;
+
+ currentXPosition = nRootX;
+ currentYPosition = nRootY;
+
+ if (nRes) {
+ nOldRootX = nRootX;
+ nOldRootY = nRootY;
+ }
+
+ return nRes;
+}
+// End mouse monitoring and event creation code
+
+
+bool KMouseTool::isAutostart()
+{
+ QString sym = autostartdirname;
+ sym += "kmousetool"; // sym is now full path to symlink
+ QFileInfo fi(sym);
+
+ return fi.exists();
+}
+
+void KMouseTool::setAutostart (bool start)
+{
+ QString sym = autostartdirname;
+ sym += "kmousetool"; // sym is now full path to symlink
+ QFileInfo fi(sym);
+ QString cmd;
+
+ if (start) {
+ if (!fi.exists()) // if it doesn't exist, make it
+ cmd.sprintf("ln -s %s %s", appfilename.latin1(), autostartdirname.latin1());
+ }
+ else {
+ if (fi.exists()) // if it exists, delete it
+ cmd.sprintf("rm -f %s", sym.latin1());
+ }
+ system(cmd.ascii());
+}
+
+bool KMouseTool::applySettings()
+{
+ int drag, dwell;
+
+ dwell = dwellTimeEdit->value();
+ drag = dragTimeEdit->value() ;
+
+ // The drag time must be less than the dwell time
+ if ( dwell < drag) {
+ KMessageBox::sorry(this, i18n("The drag time must be less than or equal to the dwell time."), i18n("Invalid Value"));
+ return false;
+ }
+
+ // if we got here, we must be okay.
+ min_movement = movementEdit->value();
+ smart_drag_on = cbDrag->isChecked();
+ playSound = cbClick->isChecked();
+ strokesEnabled = cbStroke->isChecked();
+ setAutostart (cbStart->isChecked());
+
+ dwell_time = dwell;
+ drag_time = drag;
+ tick_count = max_ticks;
+
+ saveOptions();
+ settingsChanged();
+ return true;
+}
+
+// Save options to kmousetoolrc file
+void KMouseTool::loadOptions()
+{
+ kapp->config()->setGroup("UserOptions");
+
+ playSound = kapp->config()->readBoolEntry("AudibleClick",false);
+ smart_drag_on = kapp->config()->readBoolEntry("SmartDrag",false);
+
+ dwell_time = kapp->config()->readNumEntry("DwellTime",5);
+ drag_time = kapp->config()->readNumEntry("DragTime",3);
+ min_movement = kapp->config()->readNumEntry("Movement",5);
+ strokesEnabled = kapp->config()->readBoolEntry("strokesEnabled",false);
+
+ QPoint p;
+ int x = kapp->config()->readNumEntry("x",0);
+ int y = kapp->config()->readNumEntry("y",0);
+ p.setX(x);
+ p.setY(y);
+ move(p);
+
+ mousetool_is_running = kapp->config()->readBoolEntry("MouseToolIsRunning",false);
+ display = XOpenDisplay(NULL);
+}
+
+// Save options to kmousetoolrc file
+void KMouseTool::saveOptions()
+{
+ QPoint p = pos();
+ int x = p.x();
+ int y = p.y();
+
+ kapp->config()->setGroup("ProgramOptions");
+ kapp->config()->writeEntry("Version", KMOUSETOOL_VERSION);
+ kapp->config()->setGroup("UserOptions");
+ kapp->config()->writeEntry("x", x);
+ kapp->config()->writeEntry("y", y);
+ kapp->config()->writeEntry("strokesEnabled", strokesEnabled);
+ kapp->config()->writeEntry("IsMinimized", isHidden());
+ kapp->config()->writeEntry("DwellTime", dwell_time);
+ kapp->config()->writeEntry("DragTime", drag_time);
+ kapp->config()->writeEntry("Movement", min_movement);
+ kapp->config()->writeEntry("SmartDrag", smart_drag_on);
+ kapp->config()->writeEntry("AudibleClick", playSound);
+ kapp->config()->writeEntry("MouseToolIsRunning", mousetool_is_running);
+ kapp->config()->sync();
+}
+
+void KMouseTool::updateStartStopText()
+{
+ if (mousetool_is_running)
+ buttonStartStop->setText(i18n("&Stop"));
+ else
+ buttonStartStop->setText(i18n("&Start"));
+ trayIcon->updateStartStopText(mousetool_is_running);
+}
+
+bool KMouseTool::newSettings()
+{
+ return ((dwell_time != dwellTimeEdit->value()) ||
+ (drag_time != dragTimeEdit->value()) ||
+ (min_movement != movementEdit->value()) ||
+ (smart_drag_on != cbDrag->isChecked()) ||
+ (playSound != cbClick->isChecked()) ||
+ (strokesEnabled != cbStroke->isChecked()) ||
+ (isAutostart() != cbStart->isChecked()));
+}
+
+bool KMouseTool::defaultSettings()
+{
+ return ((5 == dwellTimeEdit->value()) &&
+ (3 == dragTimeEdit->value()) &&
+ (5 == movementEdit->value()) &&
+ !cbDrag->isChecked() &&
+ !cbClick->isChecked() &&
+ !cbStroke->isChecked() &&
+ !cbStart->isChecked());
+}
+
+/******** SLOTS **********/
+
+// Value or state changed
+void KMouseTool::settingsChanged ()
+{
+ buttonReset->setEnabled (newSettings());
+ buttonApply->setEnabled (newSettings());
+ buttonDefault->setDisabled (defaultSettings());
+}
+
+// Buttons within the dialog
+void KMouseTool::startStopSelected()
+{
+ mousetool_is_running = !mousetool_is_running;
+ updateStartStopText();
+}
+
+void KMouseTool::defaultSelected()
+{
+ setDefaultSettings();
+}
+
+void KMouseTool::resetSelected()
+{
+ resetSettings();
+}
+
+void KMouseTool::applySelected()
+{
+ applySettings();
+}
+
+// Buttons at the bottom of the dialog
+void KMouseTool::helpSelected()
+{
+ kapp->invokeHelp();
+}
+
+void KMouseTool::closeSelected()
+{
+ if (newSettings())
+ {
+ int answer = KMessageBox::questionYesNoCancel (this,
+ i18n("There are unsaved changes in the active module.\nDo you want to apply the changes before closing the configuration window or discard the changes?"),
+ i18n("Closing Configuration Window"),
+ KStdGuiItem::apply(), KStdGuiItem::discard(), "AutomaticSave");
+ if (answer == KMessageBox::Yes)
+ applySettings();
+ else if (answer == KMessageBox::No)
+ resetSettings();
+ if (answer != KMessageBox::Cancel)
+ hide();
+ }
+ else
+ hide();
+}
+
+void KMouseTool::quitSelected()
+{
+ if (newSettings())
+ {
+ int answer = KMessageBox::questionYesNoCancel (this,
+ i18n("There are unsaved changes in the active module.\nDo you want to apply the changes before quitting KMousetool or discard the changes?"),
+ i18n("Quitting KMousetool"),
+ KStdGuiItem::apply(), KStdGuiItem::discard(), "AutomaticSave");
+ if (answer == KMessageBox::Yes)
+ applySettings();
+ if (answer != KMessageBox::Cancel)
+ {
+ saveOptions();
+ kapp->quit();
+ }
+ }
+ else
+ {
+ saveOptions();
+ kapp->quit();
+ }
+}
+
+// Menu functions
+void KMouseTool::configureSelected()
+{
+ show();
+ raise();
+ setActiveWindow();
+}
+
+void KMouseTool::aboutSelected()
+{
+ aboutDlg->show();
+}
+
+
+
+KMouseToolTray::KMouseToolTray (QWidget *parent, const char *name) : KSystemTray (parent, name)
+{
+ startStopId = contextMenu()->insertItem (i18n("&Start"), this, SIGNAL(startStopSelected()));
+ contextMenu()->insertSeparator();
+ contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("configure", KIcon::Small),
+ i18n("&Configure KMouseTool..."), this, SIGNAL(configureSelected()));
+ contextMenu()->insertSeparator();
+ contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("contents", KIcon::Small),
+ i18n("KMousetool &Handbook"), this, SIGNAL(helpSelected()));
+ contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("kmousetool", KIcon::Small),
+ i18n("&About KMouseTool"), this, SIGNAL(aboutSelected()));
+}
+
+KMouseToolTray::~KMouseToolTray() {
+}
+
+void KMouseToolTray::updateStartStopText(bool mousetool_is_running)
+{
+ QPixmap icon;
+
+ if (mousetool_is_running) {
+ contextMenu()->changeItem (startStopId, i18n("&Stop"));
+ icon = KGlobal::iconLoader()->loadIcon("kmousetool_on", KIcon::Small);
+ }
+ else {
+ contextMenu()->changeItem (startStopId, i18n("&Start"));
+ icon = KGlobal::iconLoader()->loadIcon("kmousetool_off", KIcon::Small);
+ }
+ setPixmap (icon);
+ show();
+}
diff --git a/kmousetool/kmousetool/kmousetool.desktop b/kmousetool/kmousetool/kmousetool.desktop
new file mode 100644
index 0000000..1517c3f
--- /dev/null
+++ b/kmousetool/kmousetool/kmousetool.desktop
@@ -0,0 +1,138 @@
+# KDE Config File
+[Desktop Entry]
+Type=Application
+Exec=kmousetool -caption "%c" %i %m
+Icon=kmousetool
+DocPath=kmousetool/index.html
+Comment=Clicks the mouse for you, reducing the effects of RSI
+Comment[ar]=ينقر على الفأرة بدلا منك، مُخَفِّفاً عنك آلام RSI
+Comment[bg]=Автоматично щракване с бутона на мишката
+Comment[bs]=Klika mišem za vas, smanjujući efekte RSI-ja
+Comment[ca]=Fa els clics del ratolí­, reduint els efectes del RSI (índex de força relativa)
+Comment[cs]=Kliká za vás myší, omezuje tak efekt RSI
+Comment[cy]=Clicio'r llygoden i chi, wrth esmwytho effeithiau RSI
+Comment[da]=Klikker på musen for dig, reducerer virkningen af RSI-smerte
+Comment[de]=Führt Mausklicks für Sie aus
+Comment[el]=Ενεργεί τα κλικ του ποντικιού για σας, μειώνοντας τις επιδράσεις των τραυμάτων από τη συνεχή επανάληψη (RSI)
+Comment[eo]=Klakas la muson por vi, tio reduktas la efekton de RSI
+Comment[es]=Pulsa los botones del ratón por usted, reduciendo los efectos de RSI
+Comment[et]=Klõpsab hiirt sinu eest, vähendades võimalike lihasevalude ohtu
+Comment[eu]=Sagua zure ordez klikatzen du, RSI-aren efektuak gutxitzeko
+Comment[fa]=موشی را برایتان فشار می‌دهد، اثرات RSI را کاهش می‌دهد
+Comment[fi]=Napsauttaa hiirtä puolestasi rannevammojen ehkäisemiseksi
+Comment[fr]=Clique sur la souris à votre place, limitant les douleurs liées aux TMS
+Comment[ga]=Cliceálann seo an luch duit, chun tionchar gortú athstraidhneála a laghdú
+Comment[gl]=Preme o rato por ti, reducindo os efeitos da RSI
+Comment[he]=לוחץ על העכבר עבורך, ובכך מקל על פרק היד
+Comment[hi]=आपके लिए माउस क्लिक करता है, बार-बार क्लिक के कारण ऊंगलियों में होने वाली क्षति को कम करता है
+Comment[hu]=Automatikus egérkattintás (RSI-szindrómában szenvedőknek)
+Comment[is]=Smellir músarhnöppunum fyrir þig og dregur úr áhrifum RSI
+Comment[it]=Fa clic sul mouse al posto tuo, riducendo gli effetti della RSI
+Comment[ja]=RSI (反復運動過多損傷) を防ぐために、あなたの代わりにマウスをクリック
+Comment[ka]=დაწკაპავს თაგუნას თქვენს მაგივრად, ამცირებს RSI ეფექტებს
+Comment[km]=ចុច​កណ្ដុរ​ឲ្យ​អ្នក ដែល​កាត់​បន្ថយ​បែបផែន​របស់ RSI
+Comment[lt]=Nuspaudžia pelės klavišą, sumažindamas skausmo sindromą
+Comment[ms]=Mengklik tetikus untuk anda, mengurangkan kesan RSI
+Comment[mt]=Jikklikkjalek il-maws, biex tevita wġigħ RSI
+Comment[nb]=Trykker museknappen for deg, gir mindre musesyke
+Comment[nds]=Klickt de Muus för Di, minnert de Effekten vun RSI af
+Comment[ne]=तपाईँका लागि RSI को प्रभाव घटाएर माउस क्लिक गर्छ
+Comment[nl]=Klikt de muisknop voor u, vermindert de effecten van RSI
+Comment[nn]=Klikkar med musa for deg, for å hindra belastningsskadar
+Comment[pa]=ਮਾਊਸ ਨੂੰ ਦਬਾਉਣ ਨਾਲ ਤੁਹਾਡੇ ਲਈ RSI ਪਰਭਾਵ ਘੱਟ ਜਾਵੇਗਾ
+Comment[pl]=Klika za Ciebie myszą, ograniczając nadwyrężanie mięśni
+Comment[pt]=Carrega no rato por si, aliviando dores motivadas por RSI
+Comment[pt_BR]= Clica o mouse para você, facilitando a dificuldade do RSI
+Comment[ro]=Execută clicuri pentru dumneavoastră, reducînd oboseala mîinii
+Comment[ru]=Утилита управления мышью для облегчения болевых синдромов
+Comment[sk]=Kliká za vás myšou, uľahčuje bolesti RSI
+Comment[sl]=Za vas klika miško, da vam olajša bolečine v zapestju
+Comment[sr]=Кликће мишем за вас, умањујући вам болове у зглобу
+Comment[sr@Latn]=Klikće mišem za vas, umanjujući vam bolove u zglobu
+Comment[sv]=Klickar musen åt dig, för att mildra smärta från musarm
+Comment[ta]=Clicks the mouse for you, reducing the effects of RSI RSI
+Comment[tg]=Зер кардани муш барои шумо, бо камшавии таъсирҳои RSI
+Comment[th]=คลิ้กเม้าส์สำหรับคุณเพื่อลดความเสียงต่อการเป็นโรค RSI
+Comment[tr]=RSI özelliklerini azaltarak sizin için fareyi tıklar
+Comment[uk]=Клацає мишкою для вас для полегшення відчуття болі в зап'ясті
+Comment[vi]=Ấn chuột giúp bạn, giảm tác động của RSI
+Comment[zh_CN]=为您点击鼠标,减轻肢体重复性劳损(RSI)效应
+Comment[zh_TW]=為您點擊滑鼠, 減少重複施緊傷害(RSI)的影響
+Terminal=false
+Name=KMouseTool
+Name[cy]=KErfynLlygoden
+Name[eo]=Kmusilo
+Name[hi]=के-माउस टूल
+Name[km]= KMouseTool
+Name[ne]=केडीई माउस उपकरण
+Name[pa]=ਕੇ ਮਾਊਸ ਸੰਦ
+Name[ro]=Utilitar mouse
+Name[sv]=Kmousetool
+Name[ta]=கே சுட்டிக்கருவி
+Name[tg]=Асбоби КМуш
+Name[th]=ปรับแต่งเม้าส์ - K
+Name[tr]=Kmousetool
+Name[uz]=Sichqoncha vositasi
+Name[uz@cyrillic]=Сичқонча воситаси
+Name[vi]=Công cụ Chuột KDE
+Name[zh_CN]=K 鼠标工具
+Name[zh_TW]=K-滑鼠工具
+GenericName=Automatic Mouse Click
+GenericName[ar]=نقر الفأرة التلقائي
+GenericName[bg]=Инструмент за мишката
+GenericName[bs]=Automatsko klikanje mišem
+GenericName[ca]=Clic automàtic del ratolí
+GenericName[cs]=Automatické klikání myší
+GenericName[cy]=Clic Llygoden Ymysgogol
+GenericName[da]=Automatisk museklik
+GenericName[de]=Automatische Mausklicks
+GenericName[el]=Αυτόματο κλικ ποντικιού
+GenericName[eo]=Aŭtomata Musklako
+GenericName[es]=Pulsación automática del ratón
+GenericName[et]=Hiire automaatne klõpsaja
+GenericName[eu]=Saguaren klik automatikoak
+GenericName[fa]=فشار خودکار موشی
+GenericName[fi]=Automaattinen hiirennapsautus
+GenericName[fr]=Clic de souris automatique
+GenericName[ga]=Cliceáil uathoibríoch luiche
+GenericName[gl]=Preme o rato automaticamente
+GenericName[he]=לחיצת עכבר אוטומטית
+GenericName[hi]=स्वचालित माउस क्लिक
+GenericName[hu]=Automatikus kattintás
+GenericName[is]=Sjálfvirkur músahnappasmellir
+GenericName[it]=Clic automatico del mouse
+GenericName[ja]=自動マウスクリック
+GenericName[ka]=თაგუნას ავტომატური წკაპი
+GenericName[km]= ចុចកណ្តុរ​ដោយ​ស្វ័យប្រវត្តិ
+GenericName[lt]=Automatiniai pelės paspaudimai
+GenericName[mk]=Автоматско кликнување на глушецот
+GenericName[ms]=Klik Tetikus Automatik
+GenericName[mt]=Klikk tal-Maws Awtomatiku
+GenericName[nb]=Automatisk museklikk
+GenericName[nds]=Automaatsche Muusklicks
+GenericName[ne]=स्वचालित माउस क्लिक
+GenericName[nl]=Automatische muisklik
+GenericName[nn]=Automatisk museklikk
+GenericName[pa]=ਐਟੋਮੈਟਿਕ ਮਾਊਸ ਕਲਿੱਕ
+GenericName[pl]=Automatyczne klikanie myszą
+GenericName[pt]=Carregar no Rato
+GenericName[pt_BR]=Clique Automático do Mouse
+GenericName[ro]=Clic automat de mouse
+GenericName[ru]=Автощелчок мышью
+GenericName[sk]=Automatické klikanie myšou
+GenericName[sl]=Samodejni klik miške
+GenericName[sr]=Аутоматски клик мишем
+GenericName[sr@Latn]=Automatski klik mišem
+GenericName[sv]=Automatiska musklick
+GenericName[ta]=தானியங்கி சுட்டி சொடுக்கல்
+GenericName[tg]=Зер кардани автоматии муш
+GenericName[th]=คลิ้กเม้าส์อัตโนมัติ
+GenericName[tr]=Otomatik Fare Tıklaması
+GenericName[uk]=Автоматичне клацання мишкою
+GenericName[uz]=Sichqonchani avto-bosish
+GenericName[uz@cyrillic]=Сичқончани авто-босиш
+GenericName[vi]=Ấn Chuột Tự động
+GenericName[zh_CN]=自动鼠标点击
+GenericName[zh_TW]=自動滑鼠點擊
+Categories=Qt;KDE;Utility;Accessibility;
+
diff --git a/kmousetool/kmousetool/kmousetool.h b/kmousetool/kmousetool/kmousetool.h
new file mode 100644
index 0000000..88a05ec
--- /dev/null
+++ b/kmousetool/kmousetool/kmousetool.h
@@ -0,0 +1,209 @@
+/***************************************************************************
+ kmousetool.h - description
+ -------------------
+ begin : Sun Jan 20 23:27:58 PST 2002
+ copyright : (C) 2002-2003 by Jeff Roush
+ email : jeff@mousetool.com
+ copyright : (C) 2003 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ copyright : (C) 2003 by Gunnar Schmi Dt
+ email : gunnar@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KMOUSETOOL_H
+#define KMOUSETOOL_H
+
+#include <qdir.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "version.h"
+
+#include <kapplication.h>
+#include <ksystemtray.h>
+#include <qwidget.h>
+#include "mtstroke.h"
+#include "kmousetoolui.h"
+
+class QLineEdit;
+class QLabel;
+class QCheckBox;
+class QPushButton;
+class KAudioPlayer;
+class KAboutApplication;
+class KMouseToolTray;
+
+
+/**
+ * KMouseTool is the base class of the project
+ *
+ * It is the main widget for the dialog
+ *
+ */
+
+class KMouseTool : public KMouseToolUI
+{
+ Q_OBJECT
+
+private:
+ MTStroke stroke;
+
+ // boolean flags to keep track of program states
+ int mouse_is_down;
+ int continue_timer;
+ int tick_count;
+ int dwell_time;
+ int drag_time;
+ int max_ticks;
+ int min_movement;
+ bool smart_drag_on;
+ bool playSound;
+ bool mousetool_is_running;
+ bool mousetool_just_started;
+ bool moving;
+ bool strokesEnabled;
+
+ QString autostartdirname;
+ QString rcfilename;
+ QString appfilename;
+ QString mSoundFileName;
+ KAudioPlayer *mplayer;
+ KMouseToolTray *trayIcon;
+
+ KAboutApplication *aboutDlg;
+
+ /**
+ * Initialize all variables
+ */
+ void init_vars();
+
+ /**
+ * Take care of details of playing .wav file
+ *
+ * Currently uses KAudioPlayer::play(), which has an annoying delay.
+ *
+ * The solution seems to be to use MCOP, but I haven't been able to get that to work yet.
+ */
+ void playTickSound();
+
+ /**
+ * Load state of program from "kmousetool.rc" in the user's local .kde folder,
+ *
+ */
+ void loadOptions();
+
+ /**
+ * Save state of program under the user's local .kde folder,
+ * in a file named "kmousetool.rc"
+ *
+ */
+ void saveOptions();
+
+ /**
+ * This function changes text on button depending on
+ * state of time (either "start", or "stop").
+ **/
+ void updateStartStopText();
+
+ /**
+ * Returns true if the current values in the settings window are different
+ * from the settings currently used
+ **/
+ bool newSettings();
+
+ /**
+ * Returns true if the current values in the settings window are identical
+ * with the default settings
+ **/
+ bool defaultSettings();
+
+ /**
+ * Resets the values in the settings window to the settings currently used
+ **/
+ void resetSettings();
+
+ /**
+ * Sets the values in the settings window to the default settings
+ **/
+ void setDefaultSettings();
+
+ /**
+ * Applies the current values in the settings window
+ **/
+ bool applySettings();
+
+ bool isAutostart();
+ void setAutostart (bool start);
+
+public slots:
+ /**
+ * This slot is called whenever a value in the settings window was changed.
+ * It enabled and disables the three buttons "Defaults", "Reset" and "Apply".
+ **/
+ void settingsChanged();
+
+ void startStopSelected();
+
+ void defaultSelected();
+ void resetSelected();
+ void applySelected();
+
+ void helpSelected();
+ void closeSelected();
+ void quitSelected();
+
+ void aboutSelected();
+ void configureSelected();
+
+public:
+ /**
+ * This function runs the show; it is called once every
+ * 1/10 second.
+ *
+ * It checks to see if SmartDrag is on, and compares the
+ * current mouse position to its previous position to see
+ * whether to send a down click, and up click, or wait.
+ */
+ void timerEvent (QTimerEvent *e);
+
+ /**
+ * This generates a normal click event --
+ * down, up, or down-up, depending on smart-drag settings and current state
+ */
+ void normalClick();
+
+ /**
+ * construtor
+ */
+ KMouseTool(QWidget* parent=0, const char *name=0);
+
+ /** destructor */
+ ~KMouseTool();
+};
+
+class KMouseToolTray : public KSystemTray {
+ Q_OBJECT
+ int startStopId;
+public:
+ KMouseToolTray (QWidget *parent=0, const char *name=0);
+ ~KMouseToolTray();
+
+ void updateStartStopText (bool mousetool_is_running);
+signals:
+ void startStopSelected();
+ void configureSelected();
+ void aboutSelected();
+ void helpSelected();
+};
+#endif
diff --git a/kmousetool/kmousetool/kmousetoolui.ui b/kmousetool/kmousetool/kmousetoolui.ui
new file mode 100644
index 0000000..05b3322
--- /dev/null
+++ b/kmousetool/kmousetool/kmousetoolui.ui
@@ -0,0 +1,422 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>KMouseToolUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KMouseToolUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>544</width>
+ <height>395</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>KMouseTool</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Settings</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="3" column="0">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="0" column="0">
+ <property name="name">
+ <cstring>dragTimeSpace</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>dragTimeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Drag t&amp;ime (1/10 sec):</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>dragTimeEdit</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="KIntSpinBox" row="3" column="1">
+ <property name="name">
+ <cstring>dragTimeEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maxValue">
+ <number>40</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>3</number>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>dwellTimeEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maxValue">
+ <number>40</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>5</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>movementLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Minimum movement:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>movementEdit</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>movementEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maxValue">
+ <number>40</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>cbStroke</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Enable strokes</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>dwellTimeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>D&amp;well time (1/10 sec):</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>dwellTimeEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>cbDrag</cstring>
+ </property>
+ <property name="text">
+ <string>Smar&amp;t drag</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="7" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonDefault</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Defaults</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonReset</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Reset</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer4_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonApply</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Apply</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox" row="6" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>cbStart</cstring>
+ </property>
+ <property name="text">
+ <string>Start with &amp;KDE</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="5" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>cbClick</cstring>
+ </property>
+ <property name="text">
+ <string>A&amp;udible click</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>KMouseTool will run as a background application after you close this dialog. To change the settings again, restart KMouseTool or use the KDE system tray.</string>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignJustify|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>8</width>
+ <height>8</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonStartStop</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Start</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonHelp</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Help</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>241</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonClose</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Close</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonQuit</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>cbDrag</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>dragTimeLabel</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>cbDrag</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>dragTimeEdit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kmousetool/kmousetool/main.cpp b/kmousetool/kmousetool/main.cpp
new file mode 100644
index 0000000..29c5e30
--- /dev/null
+++ b/kmousetool/kmousetool/main.cpp
@@ -0,0 +1,79 @@
+/***************************************************************************
+ main.cpp - description
+ -------------------
+ begin : Sun Jan 20 23:27:58 PST 2002
+ copyright : (C) 2002 by Jeff Roush
+ email : jeff@mousetool.com
+ copyright : (C) 2003 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kuniqueapplication.h>
+#include <dcopclient.h>
+#include <qmessagebox.h>
+#include <kconfig.h>
+
+#include "kmousetool.h"
+
+static const char description[] =
+ I18N_NOOP("KMouseTool");
+// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE
+
+
+static KCmdLineOptions options[] =
+{
+ KCmdLineLastOption
+ // INSERT YOUR COMMANDLINE OPTIONS HERE
+};
+
+int main(int argc, char *argv[])
+{
+ KAboutData aboutData( "kmousetool", I18N_NOOP("KMouseTool"),
+ KMOUSETOOL_VERSION, description, KAboutData::License_GPL,
+ "(c) 2002-2003, Jeff Roush\n(c) 2003, Gunnar Schmi Dt", 0, "http://www.mousetool.com", "gunnar@schmi-dt.de");
+
+ aboutData.addAuthor("Gunnar Schmi Dt", I18N_NOOP("Current maintainer"), "gunnar@schmi-dt.de", "http://www.schmi-dt.de");
+ aboutData.addAuthor("Olaf Schmidt", I18N_NOOP("Usability improvements"), "ojschmidt@kde.org");
+ aboutData.addAuthor("Jeff Roush", I18N_NOOP("Original author"), "jeff@mousetool.com", "http://www.mousetool.com");
+
+ aboutData.addCredit("Joe Betts");
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+ KUniqueApplication::addCmdLineOptions();
+
+ if (!KUniqueApplication::start()) {
+ DCOPClient *client = new DCOPClient();
+ client->attach();
+ QByteArray data;
+ QCString replyType;
+ QByteArray replyData;
+ if ( !client->call("kmousetool", "qt/KMouseToolUI", "show()",
+ data, replyType, replyData, true) ||
+ !client->call("kmousetool", "qt/KMouseToolUI", "raise()",
+ data, replyType, replyData, true) )
+ fprintf(stderr, "The DCOP calls failed\n");
+ delete client;
+ exit(0);
+ }
+ KUniqueApplication a;
+
+ KMouseTool *kmousetool = new KMouseTool();
+
+ if (!kapp->config()->readBoolEntry("IsMinimized", false))
+ kmousetool->show();
+
+ return a.exec();
+}
diff --git a/kmousetool/kmousetool/mousetool_tap.wav b/kmousetool/kmousetool/mousetool_tap.wav
new file mode 100644
index 0000000..797facb
--- /dev/null
+++ b/kmousetool/kmousetool/mousetool_tap.wav
Binary files differ
diff --git a/kmousetool/kmousetool/mtstroke.cpp b/kmousetool/kmousetool/mtstroke.cpp
new file mode 100644
index 0000000..16b1078
--- /dev/null
+++ b/kmousetool/kmousetool/mtstroke.cpp
@@ -0,0 +1,288 @@
+/***************************************************************************
+ mtstroke.cpp - description
+ -------------------
+ begin : Fri Oct 11 2002
+ copyright : (C) 2002 by Jeff Roush
+ email : jeff@mousetool.com
+ copyright : (C) 2003 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "mtstroke.h"
+#include "kmousetool.h"
+#include <iostream>
+
+// these are for locating the stroke information file
+#include <kstandarddirs.h>
+#include <qstring.h>
+
+// #include <string>
+
+using namespace std;
+
+const int MTStroke::DontClick = -1;
+const int MTStroke::bumped_mouse = 0;
+const int MTStroke::normal = 1;
+const int MTStroke::RightClick = 2;
+const int MTStroke::DoubleClick = 3;
+const int MTStroke::circle = 4;
+const int MTStroke::LowerLeftStroke = 5;
+const int MTStroke::UpperRightStroke = 6;
+const int MTStroke::LowerRightStroke = 7;
+const int MTStroke::UpperLeftStroke = 8;
+
+int MTStroke::delta_xy = 10;
+
+const int MTStroke::min_num_points = 5;
+
+Pt MTStroke::LowerLeft (0,0);
+Pt MTStroke::LowerRight(0,0);
+Pt MTStroke::UpperLeft (0,0);
+Pt MTStroke::UpperRight(0,0);
+
+
+
+MTStroke::MTStroke(){
+ readSequence();
+}
+MTStroke::~MTStroke(){
+}
+
+// add the new point, but only if it's not the same as the previous point.
+void MTStroke::addPt(const int x, const int y)
+{
+ if (points.size()==0) {
+ points.push_back(Pt(x,y));
+ }
+ else {
+ Pt pt(x,y);
+ if (!pt.sameAs(points[points.size()-1])) {
+ points.push_back(Pt(x,y));
+ }
+ }
+}
+
+
+/*
+ * Loop over all the strokes;
+ * return true if the given point is included
+ */
+bool MTStroke::pointsContain(Pt pt)
+{
+ std::vector<Pt>::iterator pos;
+ for (pos=points.begin(); pos<points.end(); pos++) {
+ if (pt.x==pos->x && pt.y==pos->y)
+ return true;
+ }
+ return false;
+}
+
+int MTStroke::getStrokeType()
+{
+ int size = points.size();
+
+ // If the mouse moved just a bit, it was probably bumped. Don't click.
+ if (size<min_num_points)
+ return normal;
+// return bumped_mouse;
+
+ Pt lastPoint = points[points.size()-1];
+
+ // If the mouse is pausing in a corner, then the user is either in the middle of a
+ // stroke, or wants to rest the mouse. Don't click.
+ if (lastPoint.sameAs(LowerLeft) || lastPoint.sameAs(LowerRight)
+ || lastPoint.sameAs(UpperLeft) || lastPoint.sameAs(UpperRight))
+ return DontClick;
+
+ // If the mouse visited a corner...
+ if (pointsContain(LowerLeft)) {
+ reset();
+ return LowerLeftStroke;
+ }
+ if (pointsContain(UpperRight)) {
+ reset();
+ return UpperRightStroke;
+ }
+ scale();
+
+ std::map<std::string, int>::iterator keypos = sequenceMap.find(sequence);
+ if (keypos == sequenceMap.end()) {
+ reset();
+ return normal;
+ }
+ reset();
+// return RightClick;
+ return keypos->second;
+}
+
+void MTStroke::scale()
+{
+ getExtent();
+ int deltax = stroke_maxx - stroke_minx;
+ int deltay = stroke_maxy - stroke_miny;
+ int delta = max(deltax, deltay);
+ int scale = (int) delta/2;
+
+ std::vector<Pt>::iterator pos;
+ for (pos=points.begin(); pos<points.end(); pos++) {
+
+ // add an extra (scale/2) because the divide rounds _down_, and we want to
+ // round _up_ or _down_, depending on which is closer.
+ pos->x = (int) (pos->x-stroke_minx + scale/2)/scale;
+ pos->y = (int) (pos->y-stroke_miny + scale/2)/scale;
+
+ // now, get the integer representing this position and add it to the stroke sequence
+ int n = 3*pos->y + pos->x + 1;
+ int index = sequence.size()-1;
+ n += '0';
+ if (index==-1)
+ sequence += n;
+ else if (n!=sequence[index])
+ sequence += n;
+ }
+}
+
+int MTStroke::max(int n, int m)
+{
+ if (n>m)
+ return n;
+ return m;
+}
+
+
+/*
+ * Find the bounding rectangle for the stroke
+ */
+void MTStroke::getExtent()
+{
+ stroke_minx = UpperRight.x;
+ stroke_maxx = 0;
+ stroke_miny = LowerLeft.y;
+ stroke_maxy = 0;
+
+ std::vector<Pt>::iterator pos;
+ for (pos=points.begin(); pos<points.end(); pos++) {
+ if (stroke_minx > pos->x)
+ stroke_minx = pos->x;
+ if (stroke_maxx < pos->x)
+ stroke_maxx = pos->x;
+ if (stroke_miny > pos->y)
+ stroke_miny = pos->y;
+ if (stroke_maxy < pos->y)
+ stroke_maxy = pos->y;
+ }
+}
+
+// test if strokefile exists; if not, create it from defaults.
+// if unable to create it,
+bool MTStroke::readSequence()
+{
+ QString strokefilename;
+ strokefilename = locate("config", "kmousetool_strokes.txt");
+ if (strokefilename.isEmpty()) {
+ // make default
+ if (sequenceMap.size()==0)
+ makeDefaultSequenceMap();
+ writeSequence();
+ return false;
+ }
+ ifstream infile (strokefilename.ascii());
+ if (!infile) {
+ // make default
+ if (sequenceMap.size()==0)
+ makeDefaultSequenceMap();
+ writeSequence();
+ return false;
+ }
+
+ while (!infile.eof()) {
+ string str;
+ infile >> str;
+ if (str[0] == '#')
+ readToEndOfLine(infile);
+ else {
+ // get the associated action
+ string str2;
+ infile >> str2;
+ int n = str2[0] - '0'; // the action is a single integer digit; convert it to an int
+ sequenceMap[ string(str) ] = n;
+ }
+ }
+ return true;
+}
+
+bool MTStroke::writeSequence()
+{
+ QString strokefilename;
+ strokefilename = locateLocal("config", "kmousetool_strokes.txt");
+
+ ofstream outfile (strokefilename.ascii(), ios::out);
+ if (!outfile) {
+ return false;
+ }
+
+ outfile << "# This file contains definitions for valid strokes for KMouseTool\n";
+ outfile << "# To make sense of the numbers: \n";
+ outfile << "# The mouse path begins and ends when the mouse is paused.\n";
+ outfile << "# Imagine a square enclosing the path.\n";
+ outfile << "# Divide the square into 9 boxes, and number them like so:\n";
+ outfile << "# 1 2 3\n";
+ outfile << "# 4 5 6\n";
+ outfile << "# 7 8 9\n";
+ outfile << "# \n";
+ outfile << "# The mouse path can then be described by a sequence of numbers:\n";
+ outfile << "# for example, \"12321\" describes the mouse moving from left to right and back.\n";
+ outfile << "# This general scheme follows libstroke (http://www.etla.net/~willey/projects/libstroke/)\n";
+ outfile << "# although it was reimplemented from scratch for KMouseTool.\n";
+ outfile << "\n";
+ outfile << "# For each stroke recognized, provide an integer describing an action\n";
+ outfile << "# KMouseTool can take. At the moment, valid actions are:\n";
+ outfile << "# -1 Don't click\n";
+ outfile << "# 1 Normal click (use Smart Drag if that's enabled)\n";
+ outfile << "# 2 Right click\n";
+ outfile << "# 3 Double click\n";
+ outfile << "\n";
+ outfile << "#Stroke\tAction\n";
+ std::map<std::string, int>::iterator pos = sequenceMap.begin();
+ while (pos != sequenceMap.end()) {
+ outfile << pos->first << "\t" << pos->second << "\n";
+ pos++;
+ }
+ return true;
+}
+
+void MTStroke::makeDefaultSequenceMap()
+{
+ sequenceMap[ string("12321") ] = RightClick;
+ sequenceMap[ string("1321") ] = RightClick;
+ sequenceMap[ string("1231") ] = RightClick;
+ sequenceMap[ string("131") ] = RightClick;
+
+ sequenceMap[ string("32123") ] = DoubleClick;
+ sequenceMap[ string("3213") ] = DoubleClick;
+ sequenceMap[ string("3123") ] = DoubleClick;
+ sequenceMap[ string("313") ] = DoubleClick;
+/*
+ sequenceMap[ string("") ] = ;
+ sequenceMap[ string("") ] = ;
+ sequenceMap[ string("") ] = ;
+ sequenceMap[ string("") ] = ;
+ sequenceMap[ string("") ] = ;
+*/
+}
+
+void MTStroke::readToEndOfLine(ifstream &infile)
+{
+ char ch = 'a';
+ while (ch != '\n')
+ infile.get(ch);
+}
diff --git a/kmousetool/kmousetool/mtstroke.h b/kmousetool/kmousetool/mtstroke.h
new file mode 100644
index 0000000..171204c
--- /dev/null
+++ b/kmousetool/kmousetool/mtstroke.h
@@ -0,0 +1,103 @@
+/***************************************************************************
+ mtstroke.h - description
+ -------------------
+ begin : Fri Oct 11 2002
+ copyright : (C) 2002 by Jeff Roush
+ email : jeff@mousetool.com
+ copyright : (C) 2003 by Olaf Schmidt
+ email : ojschmidt@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef MTSTROKE_H
+#define MTSTROKE_H
+#include <vector>
+#include <fstream>
+#include <map>
+#include <string>
+#include <cstdlib>
+
+/**Implements stroke recording for MouseTool.
+ *@author Jeff Roush
+ */
+
+class Pt {
+
+ public:
+ int x,y;
+ Pt () { } ;
+ Pt (const int xx, const int yy) { x=xx; y=yy; };
+ bool sameAs(Pt pt) { return (x==pt.x&&y==pt.y); };
+ bool nearTo(Pt pt, int delta) { return ( (std::abs(x-pt.x)<delta) && (std::abs(y-pt.y)<delta) ); }
+
+ void dump();
+};
+
+class MTStroke {
+ std::vector<Pt> points;
+// std::vector<int> sequence;
+ std::string sequence;
+ std::map<std::string, int> sequenceMap;
+
+ int stroke_minx;
+ int stroke_maxx;
+ int stroke_miny;
+ int stroke_maxy;
+
+ void makeDefaultSequenceMap();
+
+public:
+ // stroke types
+ static const int bumped_mouse;
+ static const int normal;
+ static const int RightClick;
+ static const int DoubleClick;
+ static const int circle;
+ static const int DontClick;
+ static const int LowerLeftStroke;
+ static const int UpperRightStroke;
+ static const int LowerRightStroke;
+ static const int UpperLeftStroke;
+
+ // Static ints
+ static int delta_xy;
+ static Pt LowerLeft;
+ static Pt LowerRight;
+ static Pt UpperLeft;
+ static Pt UpperRight;
+
+ // min points before it can be considered a "stroke"
+ static const int min_num_points;
+
+ static void setLowerLeft (int x, int y) { LowerLeft.x = x; LowerLeft.y = y; };
+ static void setLowerRight(int x, int y) { LowerRight.x = x; LowerRight.y = y; };
+ static void setUpperLeft (int x, int y) { UpperLeft.x = x; UpperLeft.y = y; };
+ static void setUpperRight(int x, int y) { UpperRight.x = x; UpperRight.y = y; };
+
+ void dump();
+ void scale();
+ void addPt(int, int);
+ int max(int, int);
+ bool pointsContain(Pt pt);
+ int getStrokeType();
+ void getExtent();
+// void getSequence();
+ bool readSequence();
+ bool writeSequence();
+ void readToEndOfLine(std::ifstream &infile);
+
+ void reset() { points.clear(); sequence = ""; }
+
+ MTStroke();
+ ~MTStroke();
+};
+
+#endif
diff --git a/kmousetool/kmousetool/pics/Makefile.am b/kmousetool/kmousetool/pics/Makefile.am
new file mode 100644
index 0000000..f80db48
--- /dev/null
+++ b/kmousetool/kmousetool/pics/Makefile.am
@@ -0,0 +1,3 @@
+kmousetooliconsdir = $(kde_datadir)/kmousetool/icons
+kmousetoolicons_ICON = AUTO
+KDE_ICON = kmousetool
diff --git a/kmousetool/kmousetool/pics/hi16-action-kmousetool_off.png b/kmousetool/kmousetool/pics/hi16-action-kmousetool_off.png
new file mode 100644
index 0000000..e1a6fed
--- /dev/null
+++ b/kmousetool/kmousetool/pics/hi16-action-kmousetool_off.png
Binary files differ
diff --git a/kmousetool/kmousetool/pics/hi16-action-kmousetool_on.png b/kmousetool/kmousetool/pics/hi16-action-kmousetool_on.png
new file mode 100644
index 0000000..2745591
--- /dev/null
+++ b/kmousetool/kmousetool/pics/hi16-action-kmousetool_on.png
Binary files differ
diff --git a/kmousetool/kmousetool/pics/hi16-app-kmousetool.png b/kmousetool/kmousetool/pics/hi16-app-kmousetool.png
new file mode 100644
index 0000000..b70b4bf
--- /dev/null
+++ b/kmousetool/kmousetool/pics/hi16-app-kmousetool.png
Binary files differ
diff --git a/kmousetool/kmousetool/pics/hi32-action-kmousetool_off.png b/kmousetool/kmousetool/pics/hi32-action-kmousetool_off.png
new file mode 100644
index 0000000..db81487
--- /dev/null
+++ b/kmousetool/kmousetool/pics/hi32-action-kmousetool_off.png
Binary files differ
diff --git a/kmousetool/kmousetool/pics/hi32-action-kmousetool_on.png b/kmousetool/kmousetool/pics/hi32-action-kmousetool_on.png
new file mode 100644
index 0000000..0613275
--- /dev/null
+++ b/kmousetool/kmousetool/pics/hi32-action-kmousetool_on.png
Binary files differ
diff --git a/kmousetool/kmousetool/pics/hi32-app-kmousetool.png b/kmousetool/kmousetool/pics/hi32-app-kmousetool.png
new file mode 100644
index 0000000..391b486
--- /dev/null
+++ b/kmousetool/kmousetool/pics/hi32-app-kmousetool.png
Binary files differ
diff --git a/kmousetool/kmousetool/version.h b/kmousetool/kmousetool/version.h
new file mode 100644
index 0000000..9560d03
--- /dev/null
+++ b/kmousetool/kmousetool/version.h
@@ -0,0 +1,8 @@
+// KMouseTool Version Information
+//
+#ifndef kmousetool_version_h
+#define kmousetool_version_h
+
+#define KMOUSETOOL_VERSION "1.12"
+
+#endif /*version_h*/
diff --git a/kmouth/AUTHORS b/kmouth/AUTHORS
new file mode 100644
index 0000000..f8aec9b
--- /dev/null
+++ b/kmouth/AUTHORS
@@ -0,0 +1,2 @@
+Author:
+Gunnar Schmidt <gunnar@schmi-dt.de>, 2002-2003 \ No newline at end of file
diff --git a/kmouth/Makefile.am b/kmouth/Makefile.am
new file mode 100644
index 0000000..a5314bf
--- /dev/null
+++ b/kmouth/Makefile.am
@@ -0,0 +1,32 @@
+bin_PROGRAMS = kmouth
+
+kmouth_SOURCES = preferencesui.ui texttospeechconfigurationui.ui texttospeechconfigurationwidget.cpp optionsdialog.cpp configwizard.cpp phraseedit.cpp phraselist.cpp speech.cpp texttospeechsystem.cpp phraselistitem.cpp kmouth.cpp main.cpp
+kmouth_LDADD = ./phrasebook/libphrasebook.a ./wordcompletion/libwordcompletion.a -lkdeprint $(LIB_KFILE) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) $(LIBSOCKET)
+
+SUBDIRS = icons phrasebook wordcompletion books .
+
+EXTRA_DIST = main.cpp version.h kmouth.cpp kmouth.h kmouthui.rc kmouth.desktop phraselistitem.cpp phraselistitem.h texttospeechsystem.cpp texttospeechsystem.h speech.cpp speech.h phraselist.cpp phraselist.h phraseedit.cpp phraseedit.h kmouthrc configwizard.cpp configwizard.h optionsdialog.cpp optionsdialog.h texttospeechconfigurationwidget.h texttospeechconfigurationwidget.cpp texttospeechconfigurationui.ui preferencesui.ui
+
+kde_conf_DATA = kmouthrc
+
+apps_DATA = kmouth.desktop
+appsdir = $(kde_appsdir)/Applications
+
+# set the include path for X, qt and KDE
+INCLUDES= -Iphrasebook -Iwordcompletion $(all_includes)
+
+METASOURCES = AUTO
+
+# the library search path.
+kmouth_LDFLAGS = $(all_libraries) -lkspell $(KDE_RPATH)
+
+rcdir = $(kde_datadir)/kmouth
+rc_DATA = kmouthui.rc
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui */*.ui >> ./rc.cpp
+ LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) $$LIST -o $(podir)/kmouth.pot; \
+ fi
+
diff --git a/kmouth/books/Makefile.am b/kmouth/books/Makefile.am
new file mode 100644
index 0000000..b289519
--- /dev/null
+++ b/kmouth/books/Makefile.am
@@ -0,0 +1,9 @@
+
+de_DATA = de.desktop de-courteousness.phrasebook de-greetings.phrasebook de-howareyou.phrasebook de-personal.phrasebook
+dedir = $(kde_datadir)/kmouth/books/de
+
+en_DATA = en.desktop en-courteousness.phrasebook en-greetings.phrasebook en-howareyou.phrasebook en-personal.phrasebook
+endir = $(kde_datadir)/kmouth/books/en
+
+sv_DATA = sv.desktop sv-courteousness.phrasebook sv-greetings.phrasebook sv-howareyou.phrasebook sv-personal.phrasebook
+svdir = $(kde_datadir)/kmouth/books/sv
diff --git a/kmouth/books/de-courteousness.phrasebook b/kmouth/books/de-courteousness.phrasebook
new file mode 100644
index 0000000..36aa51e
--- /dev/null
+++ b/kmouth/books/de-courteousness.phrasebook
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Freundlichkeit">
+<phrase shortcut="">bitte</phrase>
+<phrase shortcut="">bitte sch&#246;n</phrase>
+<phrase shortcut="">danke</phrase>
+<phrase shortcut="">danke sch&#246;n</phrase>
+<phrase shortcut="">gern geschehen</phrase>
+<phrase shortcut="">Guten Appetit</phrase>
+<phrase shortcut="">kein problem</phrase>
+<phrase shortcut="">entschuldigung</phrase>
+<phrase shortcut="">das tut mir leid</phrase>
+</phrasebook>
diff --git a/kmouth/books/de-greetings.phrasebook b/kmouth/books/de-greetings.phrasebook
new file mode 100644
index 0000000..a38547b
--- /dev/null
+++ b/kmouth/books/de-greetings.phrasebook
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Gr&#252;&#223;e">
+<phrase shortcut="">Hallo.</phrase>
+<phrase shortcut="">Hi!</phrase>
+<phrase shortcut="">Moin!</phrase>
+<phrase shortcut="">Guten Morgen.</phrase>
+<phrase shortcut="">Guten Tag.</phrase>
+<phrase shortcut="">Guten Nachmittag.</phrase>
+<phrase shortcut="">Guten Abend.</phrase>
+<phrase shortcut="">Tsch&#252;ss!</phrase>
+<phrase shortcut="">Auf Wiedersehen!</phrase>
+<phrase shortcut="">Mach's gut!</phrase>
+<phrase shortcut="">Bis bald!</phrase>
+<phrase shortcut="">Bis dann!</phrase>
+<phrase shortcut="">Pass auf dich auf!</phrase>
+</phrasebook>
diff --git a/kmouth/books/de-howareyou.phrasebook b/kmouth/books/de-howareyou.phrasebook
new file mode 100644
index 0000000..831179f
--- /dev/null
+++ b/kmouth/books/de-howareyou.phrasebook
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Wie geht's?">
+<phrase shortcut="">Wie geht es Ihnen?</phrase>
+<phrase shortcut="">Wie geht es euch?</phrase>
+<phrase shortcut="">Wie geht es dir?</phrase>
+<phrase shortcut="">Mir geht es gut.</phrase>
+<phrase shortcut="">Es ist heute ein sch&#246;ner Tag.</phrase>
+<phrase shortcut="">Ich f&#252;hle mich heute ziemlich schlapp.</phrase>
+<phrase shortcut="">Ich habe Schmerzen.</phrase>
+<phrase shortcut="">Mir ist langweilig, aber sonst geht es mir gut.</phrase>
+<phrase shortcut="">Irgendwie geht es mir heute ziemlich beschissen.</phrase>
+</phrasebook>
diff --git a/kmouth/books/de-personal.phrasebook b/kmouth/books/de-personal.phrasebook
new file mode 100644
index 0000000..2125526
--- /dev/null
+++ b/kmouth/books/de-personal.phrasebook
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Pers&#246;nliches">
+<phrase shortcut="">Ich kann leider nur &#252;ber diesen dummen Computer sprechen.</phrase>
+<phrase shortcut="">Ich bin sehr m&#252;de und m&#246;chte jetzt etwas schlafen.</phrase>
+<phrase shortcut="">Sch&#246;n, dass du da bist.</phrase>
+<phrase shortcut="">Es freut mich, dich zu sehen.</phrase>
+<phrase shortcut="">Schade, dass du schon gehen musst.</phrase>
+<phrase shortcut="">Wann sehen wir uns wieder?</phrase>
+</phrasebook>
diff --git a/kmouth/books/de.desktop b/kmouth/books/de.desktop
new file mode 100644
index 0000000..0b8708a
--- /dev/null
+++ b/kmouth/books/de.desktop
@@ -0,0 +1,60 @@
+[Desktop Entry]
+Name=German
+Name[ar]=ألمانية
+Name[bg]=Немски
+Name[br]=Alamaneg
+Name[bs]=Njemački
+Name[ca]=Alemany
+Name[cs]=Německy
+Name[cy]=Almaeneg
+Name[da]=Tysk
+Name[de]=Deutsch
+Name[el]=Γερμανικά
+Name[eo]=Germana
+Name[es]=Alemán
+Name[et]=Saksa
+Name[eu]=Alemaniera
+Name[fa]=آلمانی
+Name[fi]=Saksalainen
+Name[fr]=Allemand
+Name[ga]=Gearmáinis
+Name[gl]=Alemán
+Name[he]=גרמנית
+Name[hi]= जर्मनी
+Name[hu]=Német
+Name[is]=Þýska
+Name[it]=Tedesco
+Name[ja]=ドイツ語
+Name[ka]=გერმანული
+Name[km]= អាល្លឺម៉ង់
+Name[lt]=Vokiečių
+Name[mk]=Германски
+Name[ms]=Jerman
+Name[mt]=Ġermaniż
+Name[nb]=Tysk
+Name[nds]=Hoochdüütsch
+Name[ne]=जर्मनी
+Name[nl]=Duits
+Name[nn]=Tysk
+Name[pa]=ਜਰਮਨ
+Name[pl]=Niemiecka
+Name[pt]=Alemão
+Name[pt_BR]=Alemão
+Name[ro]=Germană
+Name[ru]=Немецкий
+Name[rw]=Ikidage
+Name[sk]=nemčina
+Name[sl]=nemško
+Name[sr]=Немачки
+Name[sr@Latn]=Nemački
+Name[sv]=Tyska
+Name[ta]=ஜெர்மன்
+Name[tg]=Немисӣ
+Name[th]=เยอรมัน
+Name[tr]=Almanca
+Name[uk]=Німецька
+Name[uz]=Nemischa
+Name[uz@cyrillic]=Немисча
+Name[vi]=Đức
+Name[zh_CN]=德语
+Name[zh_TW]=德語
diff --git a/kmouth/books/en-courteousness.phrasebook b/kmouth/books/en-courteousness.phrasebook
new file mode 100644
index 0000000..46daede
--- /dev/null
+++ b/kmouth/books/en-courteousness.phrasebook
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Courteousness">
+<phrase shortcut="">thanks</phrase>
+<phrase shortcut="">thank you</phrase>
+<phrase shortcut="">thank you very much</phrase>
+<phrase shortcut="">please</phrase>
+<phrase shortcut="">here you are</phrase>
+<phrase shortcut="">you are welcome</phrase>
+<phrase shortcut="">Have a nice meal</phrase>
+<phrase shortcut="">no problem</phrase>
+<phrase shortcut="">excuse me</phrase>
+<phrase shortcut="">sorry</phrase>
+<phrase shortcut="">i am sorry</phrase>
+</phrasebook>
diff --git a/kmouth/books/en-greetings.phrasebook b/kmouth/books/en-greetings.phrasebook
new file mode 100644
index 0000000..dfee73b
--- /dev/null
+++ b/kmouth/books/en-greetings.phrasebook
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Greetings">
+<phrase shortcut="">Hello.</phrase>
+<phrase shortcut="">Hi!</phrase>
+<phrase shortcut="">Good morning.</phrase>
+<phrase shortcut="">Good afternoon.</phrase>
+<phrase shortcut="">Good evening.</phrase>
+<phrase shortcut="">Bye!</phrase>
+<phrase shortcut="">Bye, bye!</phrase>
+<phrase shortcut="">Good bye!</phrase>
+<phrase shortcut="">Cheers!</phrase>
+<phrase shortcut="">See you later!</phrase>
+<phrase shortcut="">Take care!</phrase>
+</phrasebook>
diff --git a/kmouth/books/en-howareyou.phrasebook b/kmouth/books/en-howareyou.phrasebook
new file mode 100644
index 0000000..3c0164e
--- /dev/null
+++ b/kmouth/books/en-howareyou.phrasebook
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="How are you?">
+<phrase shortcut="">How are you?</phrase>
+<phrase shortcut="">How do you do?</phrase>
+<phrase shortcut="">I am fine.</phrase>
+<phrase shortcut="">It's a nice day.</phrase>
+<phrase shortcut="">I feel nerveless today.</phrase>
+<phrase shortcut="">I feel bored, but apart from that I am OK.</phrase>
+<phrase shortcut="">Today my pain is quite strong.</phrase>
+<phrase shortcut="">I really feel bad today.</phrase>
+</phrasebook>
diff --git a/kmouth/books/en-personal.phrasebook b/kmouth/books/en-personal.phrasebook
new file mode 100644
index 0000000..6b70229
--- /dev/null
+++ b/kmouth/books/en-personal.phrasebook
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Personal">
+<phrase shortcut="">I can only talk using this stupid machine.</phrase>
+<phrase shortcut="">Sorry, I am quite tired and need a rest now.</phrase>
+<phrase shortcut="">Thanks for your coming.</phrase>
+<phrase shortcut="">It is nice to see you.</phrase>
+<phrase shortcut="">It was very nice to chat with you.</phrase>
+<phrase shortcut="">When will you come again?</phrase>
+</phrasebook>
diff --git a/kmouth/books/en.desktop b/kmouth/books/en.desktop
new file mode 100644
index 0000000..5766e05
--- /dev/null
+++ b/kmouth/books/en.desktop
@@ -0,0 +1,61 @@
+# KDE Config File
+[Desktop Entry]
+Name=English
+Name[ar]=إنجليزية
+Name[bg]=Английски
+Name[br]=Saozneg
+Name[bs]=Engleski
+Name[ca]=Anglès
+Name[cs]=Anglicky
+Name[cy]=Saesneg
+Name[da]=Engelsk
+Name[de]=Englisch
+Name[el]=Αγγλικά
+Name[eo]=Angla
+Name[es]=Inglés
+Name[et]=Inglise
+Name[eu]=Ingelesa
+Name[fa]=انگلیسی
+Name[fi]=Englantilainen
+Name[fr]=Anglais
+Name[ga]=Béarla
+Name[gl]=Inglés
+Name[he]=אנגלית
+Name[hi]= अंग्रेजी
+Name[hu]=Angol
+Name[is]=Enska
+Name[it]=Inglese
+Name[ja]=英語
+Name[ka]=ინგლისური
+Name[km]= អង់គ្លេស​
+Name[lt]=Anglų
+Name[mk]=Англиски
+Name[ms]=Inggeris
+Name[mt]=Ingliż
+Name[nb]=Engelsk
+Name[nds]=Engelsch
+Name[ne]=अंग्रेजी
+Name[nl]=Engels
+Name[nn]=Engelsk
+Name[pa]=ਅੰਗਰੇਜ਼ੀ
+Name[pl]=Angielska
+Name[pt]=Inglês
+Name[pt_BR]=Inglês
+Name[ro]=Engleză
+Name[ru]=Английский
+Name[rw]=Icyongereza
+Name[sk]=angličtina
+Name[sl]=angleško
+Name[sr]=Енглески
+Name[sr@Latn]=Engleski
+Name[sv]=Engelska
+Name[ta]=ஆங்கிலம்
+Name[tg]=Англисӣ
+Name[th]=อังกฤษ
+Name[tr]=İngilizce
+Name[uk]=Англійська
+Name[uz]=Inglizcha
+Name[uz@cyrillic]=Инглизча
+Name[vi]=Anh
+Name[zh_CN]=英语
+Name[zh_TW]=英語
diff --git a/kmouth/books/nl-courteousness.phrasebook b/kmouth/books/nl-courteousness.phrasebook
new file mode 100644
index 0000000..609d7e3
--- /dev/null
+++ b/kmouth/books/nl-courteousness.phrasebook
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Hoffelijkheid">
+<phrase shortcut="">dank je</phrase>
+<phrase shortcut="">dankjewel</phrase>
+<phrase shortcut="">alsjeblieft</phrase>
+<phrase shortcut="">graag gedaan</phrase>
+<phrase shortcut="">eet smakelijk</phrase>
+<phrase shortcut="">geen probleem</phrase>
+<phrase shortcut="">neem me niet kwalijk</phrase>
+<phrase shortcut="">sorry</phrase>
+<phrase shortcut="">het spijt me</phrase>
+</phrasebook>
diff --git a/kmouth/books/nl-greetings.phrasebook b/kmouth/books/nl-greetings.phrasebook
new file mode 100644
index 0000000..6ea950e
--- /dev/null
+++ b/kmouth/books/nl-greetings.phrasebook
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Groeten">
+<phrase shortcut="">Hallo.</phrase>
+<phrase shortcut="">Hoi!</phrase>
+<phrase shortcut="">Goedemorgen.</phrase>
+<phrase shortcut="">Goedemiddag.</phrase>
+<phrase shortcut="">Goedenavond.</phrase>
+<phrase shortcut="">Dag!</phrase>
+<phrase shortcut="">Doei!</phrase>
+<phrase shortcut="">Tot ziens!</phrase>
+<phrase shortcut="">Later!</phrase>
+<phrase shortcut="">Kijk je uit?</phrase>
+</phrasebook>
diff --git a/kmouth/books/nl-howareyou.phrasebook b/kmouth/books/nl-howareyou.phrasebook
new file mode 100644
index 0000000..fb54408
--- /dev/null
+++ b/kmouth/books/nl-howareyou.phrasebook
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Hoe gaat het?">
+<phrase shortcut="">Hoe gaat het?</phrase>
+<phrase shortcut="">Hoe is het?</phrase>
+<phrase shortcut="">Met mij gaat het goed.</phrase>
+<phrase shortcut="">Het is lekker weer.</phrase>
+<phrase shortcut="">Ik voel me vandaag niet lekker.</phrase>
+<phrase shortcut="">Ik verveel me, maar verder gaat het wel.</phrase>
+<phrase shortcut="">Ik heb vandaag heel veel pijn.</phrase>
+<phrase shortcut="">Ik voel me vandaag ronduit slecht.</phrase>
+</phrasebook>
diff --git a/kmouth/books/nl-personal.phrasebook b/kmouth/books/nl-personal.phrasebook
new file mode 100644
index 0000000..ccb297d
--- /dev/null
+++ b/kmouth/books/nl-personal.phrasebook
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Persoonlijk">
+<phrase shortcut="">Ik kan alleen maar praten als ik deze stomme computer gebruik.</phrase>
+<phrase shortcut="">Sorry, ik ben moe. Ik ga slapen.</phrase>
+<phrase shortcut="">Leuk dat je even langsgekomen bent.</phrase>
+<phrase shortcut="">Leuk je te zien.</phrase>
+<phrase shortcut="">Wanneer zie ik je weer?</phrase>
+</phrasebook>
diff --git a/kmouth/books/nl.desktop b/kmouth/books/nl.desktop
new file mode 100644
index 0000000..e2ac386
--- /dev/null
+++ b/kmouth/books/nl.desktop
@@ -0,0 +1,50 @@
+# KDE Config File
+[Desktop Entry]
+Name=Dutch
+Name[bg]=Холандски
+Name[br]=Nederlandeg
+Name[bs]=Holandski
+Name[ca]=Holandès
+Name[cs]=Holandsky
+Name[cy]=Iseldireg
+Name[da]=Hollandsk
+Name[de]=Niederländisch
+Name[es]=Danés
+Name[et]=Hollandi
+Name[eu]=Nederlandera
+Name[fa]=هلندی
+Name[fi]=Tanskalainen
+Name[fr]=Hollandais
+Name[ga]=Ollainnis
+Name[gl]=Holandés
+Name[he]=דנית
+Name[hu]=Holland
+Name[is]=Hollenska
+Name[it]=Olandese
+Name[ja]=オランダ語
+Name[ka]=ჰოლანდიური
+Name[km]= ហុល្លង់​
+Name[lt]=Olandų
+Name[mk]=Холандски
+Name[ms]=Belanda
+Name[nb]=Nederlandsk
+Name[nds]=Nedderlannsch
+Name[ne]=डच
+Name[nl]=Nederlands
+Name[pa]=ਡੱਚ
+Name[pl]=Holenderska
+Name[pt]=Holandês
+Name[pt_BR]=Holandês
+Name[ru]=Голландский
+Name[rw]=Ikinyaholande
+Name[sk]=holandčina
+Name[sl]=Nizozemsko
+Name[sr]=Холандски
+Name[sr@Latn]=Holandski
+Name[sv]=Holländska
+Name[tg]=Немисӣ
+Name[tr]=Flemenkçe
+Name[uk]=Голландська
+Name[vi]=Hà Lan
+Name[zh_CN]=荷兰语
+Name[zh_TW]=荷蘭語
diff --git a/kmouth/books/sv-courteousness.phrasebook b/kmouth/books/sv-courteousness.phrasebook
new file mode 100644
index 0000000..9789cce
--- /dev/null
+++ b/kmouth/books/sv-courteousness.phrasebook
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Artighet">
+<phrase shortcut="">Tack</phrase>
+<phrase shortcut="">Tack så mycket</phrase>
+<phrase shortcut="">Varsågod</phrase>
+<phrase shortcut="">Smaklig måltid</phrase>
+<phrase shortcut="">Inga problem</phrase>
+<phrase shortcut="">Ursäkta mig</phrase>
+<phrase shortcut="">Ursäkta</phrase>
+<phrase shortcut="">Jag är ledsen</phrase>
+</phrasebook>
diff --git a/kmouth/books/sv-greetings.phrasebook b/kmouth/books/sv-greetings.phrasebook
new file mode 100644
index 0000000..6d8af9c
--- /dev/null
+++ b/kmouth/books/sv-greetings.phrasebook
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Hälsningar">
+<phrase shortcut="">Hallå.</phrase>
+<phrase shortcut="">Hej!</phrase>
+<phrase shortcut="">God morgon.</phrase>
+<phrase shortcut="">God eftermiddag.</phrase>
+<phrase shortcut="">God kväll.</phrase>
+<phrase shortcut="">Hej då!</phrase>
+<phrase shortcut="">Adjö!</phrase>
+<phrase shortcut="">Hejsan!</phrase>
+<phrase shortcut="">Vi ses!</phrase>
+<phrase shortcut="">Ha det bra!</phrase>
+</phrasebook>
diff --git a/kmouth/books/sv-howareyou.phrasebook b/kmouth/books/sv-howareyou.phrasebook
new file mode 100644
index 0000000..fd548ee
--- /dev/null
+++ b/kmouth/books/sv-howareyou.phrasebook
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Hur mår du?">
+<phrase shortcut="">Hur står det till?</phrase>
+<phrase shortcut="">Hur mår du?</phrase>
+<phrase shortcut="">Jag mår bra.</phrase>
+<phrase shortcut="">Det är en trevlig dag.</phrase>
+<phrase shortcut="">Jag är upprörd idag.</phrase>
+<phrase shortcut="">Jag är uttråkad, men annars mår jag bra.</phrase>
+<phrase shortcut="">Jag har riktigt ont idag.</phrase>
+<phrase shortcut="">Jag känner mig verkligt dålig idag.</phrase>
+</phrasebook>
diff --git a/kmouth/books/sv-personal.phrasebook b/kmouth/books/sv-personal.phrasebook
new file mode 100644
index 0000000..37f7636
--- /dev/null
+++ b/kmouth/books/sv-personal.phrasebook
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE phrasebook>
+<phrasebook name="Personligt">
+<phrase shortcut="">Jag kan bara prata med hjälp av den här dumma maskinen.</phrase>
+<phrase shortcut="">Tyvärr är jag ganska trött nu och behöver ta en paus.</phrase>
+<phrase shortcut="">Tack för att du kom.</phrase>
+<phrase shortcut="">Trevligt att se dig.</phrase>
+<phrase shortcut="">Det var roligt att prata med dig.</phrase>
+<phrase shortcut="">När kommer du tillbaka?</phrase>
+</phrasebook>
diff --git a/kmouth/books/sv.desktop b/kmouth/books/sv.desktop
new file mode 100644
index 0000000..46a8145
--- /dev/null
+++ b/kmouth/books/sv.desktop
@@ -0,0 +1,61 @@
+# KDE Config File
+[Desktop Entry]
+Name=Swedish
+Name[ar]=سويدية
+Name[bg]=Шведски
+Name[br]=Svedeg
+Name[bs]=Švedski
+Name[ca]=Suec
+Name[cs]=Švédsky
+Name[cy]=Swedeg
+Name[da]=Svensk
+Name[de]=Schwedisch
+Name[el]=Σουηδικά
+Name[eo]=Sveda
+Name[es]=Sueco
+Name[et]=Rootsi
+Name[eu]=Suediera
+Name[fa]=سوئدی
+Name[fi]=Ruotsalainen
+Name[fr]=Suédois
+Name[ga]=Sualainnis
+Name[gl]=Sueco
+Name[he]=שוודית
+Name[hi]=स्वीडिश
+Name[hu]=Svéd
+Name[is]=Sænska
+Name[it]=Svedese
+Name[ja]=スウェーデン語
+Name[ka]=შვედური
+Name[km]= ស៊ុយអែដ
+Name[lt]=Švedų
+Name[mk]=Шведски
+Name[ms]=Sweden
+Name[mt]=Svediż
+Name[nb]=Svensk
+Name[nds]=Sweedsch
+Name[ne]=स्वीडिस
+Name[nl]=Zweeds
+Name[nn]=Svensk
+Name[pa]=ਸਵੀਡਨੀ
+Name[pl]=Szwedzka
+Name[pt]=Sueco
+Name[pt_BR]=Suíço
+Name[ro]=Suedeză
+Name[ru]=Шведский
+Name[rw]=Ikinyasuwede
+Name[sk]=švédčina
+Name[sl]=švedsko
+Name[sr]=Шведски
+Name[sr@Latn]=Švedski
+Name[sv]=Svenska
+Name[ta]=ஸ்வீடிஷ்
+Name[tg]=Шведӣ
+Name[th]=สวีเดน
+Name[tr]=İsveççe
+Name[uk]=Шведська
+Name[uz]=Shvedcha
+Name[uz@cyrillic]=Шведча
+Name[vi]=Thuỵ Điển
+Name[zh_CN]=瑞典语
+Name[zh_TW]=瑞典語
diff --git a/kmouth/configwizard.cpp b/kmouth/configwizard.cpp
new file mode 100644
index 0000000..d22c463
--- /dev/null
+++ b/kmouth/configwizard.cpp
@@ -0,0 +1,144 @@
+/***************************************************************************
+ configwizard.cpp - description
+ -------------------
+ begin : Mit Nov 20 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include "configwizard.h"
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <ksconfig.h>
+#include <kconfig.h>
+
+#include "texttospeechconfigurationwidget.h"
+#include "phrasebook/phrasebookdialog.h"
+#include "wordcompletion/wordcompletion.h"
+#include "wordcompletion/dictionarycreationwizard.h"
+
+ConfigWizard::ConfigWizard (QWidget *parent, const char *name, KConfig *config)
+ : KWizard(parent, name, true)
+{
+ setCaption (i18n("Initial Configuration - KMouth"));
+
+ initCommandPage (config);
+ initBookPage ();
+ initCompletion (config);
+}
+
+ConfigWizard::~ConfigWizard() {
+}
+
+void ConfigWizard::initCommandPage(KConfig *config) {
+ config->setGroup("TTS System");
+ bool displayCommand = false;
+ if (!config->hasKey("Command")) displayCommand = true;
+ if (!config->hasKey("StdIn")) displayCommand = true;
+ if (!config->hasKey("Codec")) displayCommand = true;
+
+ if (displayCommand) {
+ commandWidget = new TextToSpeechConfigurationWidget (this, "ttsPage");
+ commandWidget->readOptions (config, "TTS System");
+ addPage (commandWidget, i18n("Text-to-Speech Configuration"));
+ setHelpEnabled (commandWidget, true);
+ setFinishEnabled (commandWidget, true);
+ }
+ else
+ commandWidget = 0;
+}
+
+void ConfigWizard::initBookPage() {
+ QString standardBook = KApplication::kApplication()->dirs()->findResource("appdata", "standard.phrasebook");
+ bool displayBook = (standardBook.isNull() || standardBook.isEmpty());
+
+ if (displayBook) {
+ bookWidget = new InitialPhraseBookWidget (this, "pbPage");
+ addPage (bookWidget, i18n("Initial Phrase Book"));
+ setHelpEnabled (bookWidget, true);
+ setFinishEnabled (bookWidget, true);
+ if (commandWidget != 0)
+ setFinishEnabled (commandWidget, false);
+ }
+ else
+ bookWidget = 0;
+}
+
+void ConfigWizard::initCompletion (KConfig *config) {
+ if (!WordCompletion::isConfigured()) {
+ QString dictionaryFile = KApplication::kApplication()->dirs()->findResource("appdata", "dictionary.txt");
+ QFile file(dictionaryFile);
+ if (file.exists()) {
+ // If there is a word completion dictionary but no entry in the
+ // configuration file, we need to add it there.
+ config->setGroup("Dictionary 0");
+ config->writeEntry ("Filename", "dictionary.txt");
+ config->writeEntry ("Name", "Default");
+ config->writeEntry ("Language", QString::null);
+ config->sync();
+ }
+ }
+
+ if (config->hasGroup("Completion")) {
+ completionWidget = 0;
+ return;
+ }
+
+ if (!WordCompletion::isConfigured()) {
+ completionWidget = new CompletionWizardWidget(this, "completionPage");
+ addPage (completionWidget, i18n("Word Completion"));
+ setHelpEnabled (completionWidget, true);
+ setFinishEnabled (completionWidget, true);
+
+ if (commandWidget != 0)
+ setFinishEnabled (commandWidget, false);
+ if (bookWidget != 0)
+ setFinishEnabled (bookWidget, false);
+ }
+ else
+ completionWidget = 0;
+}
+
+void ConfigWizard::saveConfig (KConfig *config) {
+ if (commandWidget != 0) {
+ commandWidget->ok();
+ commandWidget->saveOptions (config, "TTS System");
+ }
+
+ if (bookWidget != 0)
+ bookWidget->createBook();
+
+ if (completionWidget != 0)
+ completionWidget->ok (config);
+}
+
+bool ConfigWizard::requestConfiguration () {
+ if (commandWidget != 0 || bookWidget != 0 || completionWidget != 0)
+ return (exec() == QDialog::Accepted);
+ else
+ return false;
+}
+
+bool ConfigWizard::configurationNeeded () {
+ return (commandWidget != 0 || bookWidget != 0 || completionWidget != 0);
+}
+
+void ConfigWizard::help () {
+ KApplication::kApplication()->invokeHelp ("Wizard");
+}
+
+#include "configwizard.moc"
diff --git a/kmouth/configwizard.h b/kmouth/configwizard.h
new file mode 100644
index 0000000..8ddcb60
--- /dev/null
+++ b/kmouth/configwizard.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ configwizard.h - description
+ -------------------
+ begin : Mit Nov 20 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef CONFIGWIZARD_H
+#define CONFIGWIZARD_H
+
+#include <qwidget.h>
+
+#include <kwizard.h>
+
+class KConfig;
+class TextToSpeechConfigurationWidget;
+class InitialPhraseBookWidget;
+class CompletionWizardWidget;
+
+/**The class ConfigWizard is used when the user starts KMouth for the first
+ * time. It asks the user to provide a first set of configuration data.
+ *@author Gunnar Schmi Dt
+ */
+
+class ConfigWizard : public KWizard {
+ Q_OBJECT
+public:
+ ConfigWizard (QWidget *parent, const char *name, KConfig *config);
+ ~ConfigWizard();
+
+ bool configurationNeeded ();
+ bool requestConfiguration ();
+ void saveConfig (KConfig *config);
+
+protected:
+ void help();
+
+private:
+ void initCommandPage (KConfig *config);
+ void initBookPage();
+ void initCompletion (KConfig *config);
+
+ TextToSpeechConfigurationWidget *commandWidget;
+ InitialPhraseBookWidget *bookWidget;
+ CompletionWizardWidget *completionWidget;
+};
+
+#endif
diff --git a/kmouth/icons/Makefile.am b/kmouth/icons/Makefile.am
new file mode 100644
index 0000000..5830f8f
--- /dev/null
+++ b/kmouth/icons/Makefile.am
@@ -0,0 +1,11 @@
+####### kdevelop will overwrite this part!!! (begin)##########
+
+SUBDIRS = history phrase phrasebook app
+
+EXTRA_DIST = hi16-action-speak.png hi32-action-speak.png hi48-action-speak.png hi22-action-speak.png
+
+####### kdevelop will overwrite this part!!! (end)############
+
+kmouthiconsdir = $(kde_datadir)/kmouth/icons
+kmouthicons_ICON = AUTO
+
diff --git a/kmouth/icons/app/Makefile.am b/kmouth/icons/app/Makefile.am
new file mode 100644
index 0000000..ff9afea
--- /dev/null
+++ b/kmouth/icons/app/Makefile.am
@@ -0,0 +1 @@
+KDE_ICON = kmouth
diff --git a/kmouth/icons/app/hi16-app-kmouth.png b/kmouth/icons/app/hi16-app-kmouth.png
new file mode 100644
index 0000000..69078b9
--- /dev/null
+++ b/kmouth/icons/app/hi16-app-kmouth.png
Binary files differ
diff --git a/kmouth/icons/app/hi22-app-kmouth.png b/kmouth/icons/app/hi22-app-kmouth.png
new file mode 100644
index 0000000..1052d56
--- /dev/null
+++ b/kmouth/icons/app/hi22-app-kmouth.png
Binary files differ
diff --git a/kmouth/icons/app/hi32-app-kmouth.png b/kmouth/icons/app/hi32-app-kmouth.png
new file mode 100644
index 0000000..617025f
--- /dev/null
+++ b/kmouth/icons/app/hi32-app-kmouth.png
Binary files differ
diff --git a/kmouth/icons/app/hi48-app-kmouth.png b/kmouth/icons/app/hi48-app-kmouth.png
new file mode 100644
index 0000000..26d22ce
--- /dev/null
+++ b/kmouth/icons/app/hi48-app-kmouth.png
Binary files differ
diff --git a/kmouth/icons/app/lo16-app-kmouth.png b/kmouth/icons/app/lo16-app-kmouth.png
new file mode 100644
index 0000000..69078b9
--- /dev/null
+++ b/kmouth/icons/app/lo16-app-kmouth.png
Binary files differ
diff --git a/kmouth/icons/app/lo22-app-kmouth.png b/kmouth/icons/app/lo22-app-kmouth.png
new file mode 100644
index 0000000..1052d56
--- /dev/null
+++ b/kmouth/icons/app/lo22-app-kmouth.png
Binary files differ
diff --git a/kmouth/icons/app/lo32-app-kmouth.png b/kmouth/icons/app/lo32-app-kmouth.png
new file mode 100644
index 0000000..617025f
--- /dev/null
+++ b/kmouth/icons/app/lo32-app-kmouth.png
Binary files differ
diff --git a/kmouth/icons/hi16-action-speak.png b/kmouth/icons/hi16-action-speak.png
new file mode 100644
index 0000000..69078b9
--- /dev/null
+++ b/kmouth/icons/hi16-action-speak.png
Binary files differ
diff --git a/kmouth/icons/hi22-action-speak.png b/kmouth/icons/hi22-action-speak.png
new file mode 100644
index 0000000..1052d56
--- /dev/null
+++ b/kmouth/icons/hi22-action-speak.png
Binary files differ
diff --git a/kmouth/icons/hi32-action-speak.png b/kmouth/icons/hi32-action-speak.png
new file mode 100644
index 0000000..617025f
--- /dev/null
+++ b/kmouth/icons/hi32-action-speak.png
Binary files differ
diff --git a/kmouth/icons/hi48-action-speak.png b/kmouth/icons/hi48-action-speak.png
new file mode 100644
index 0000000..26d22ce
--- /dev/null
+++ b/kmouth/icons/hi48-action-speak.png
Binary files differ
diff --git a/kmouth/icons/history/Makefile.am b/kmouth/icons/history/Makefile.am
new file mode 100644
index 0000000..abce34f
--- /dev/null
+++ b/kmouth/icons/history/Makefile.am
@@ -0,0 +1,9 @@
+####### kdevelop will overwrite this part!!! (begin)##########
+
+
+EXTRA_DIST = hi16-action-phrasehistory_open.png hi16-action-phrasehistory_print.png hi16-action-phrasehistory_save.png hi22-action-phrasehistory_open.png hi22-action-phrasehistory_print.png hi22-action-phrasehistory_save.png hi32-action-phrasehistory_open.png hi32-action-phrasehistory_print.png hi32-action-phrasehistory_save.png
+
+####### kdevelop will overwrite this part!!! (end)############
+
+kmouthiconsdir = $(kde_datadir)/kmouth/icons
+kmouthicons_ICON = AUTO
diff --git a/kmouth/icons/history/hi16-action-phrasehistory_open.png b/kmouth/icons/history/hi16-action-phrasehistory_open.png
new file mode 100644
index 0000000..abb66a2
--- /dev/null
+++ b/kmouth/icons/history/hi16-action-phrasehistory_open.png
Binary files differ
diff --git a/kmouth/icons/history/hi16-action-phrasehistory_print.png b/kmouth/icons/history/hi16-action-phrasehistory_print.png
new file mode 100644
index 0000000..7b589b0
--- /dev/null
+++ b/kmouth/icons/history/hi16-action-phrasehistory_print.png
Binary files differ
diff --git a/kmouth/icons/history/hi16-action-phrasehistory_save.png b/kmouth/icons/history/hi16-action-phrasehistory_save.png
new file mode 100644
index 0000000..157602e
--- /dev/null
+++ b/kmouth/icons/history/hi16-action-phrasehistory_save.png
Binary files differ
diff --git a/kmouth/icons/history/hi22-action-phrasehistory_open.png b/kmouth/icons/history/hi22-action-phrasehistory_open.png
new file mode 100644
index 0000000..85bfc08
--- /dev/null
+++ b/kmouth/icons/history/hi22-action-phrasehistory_open.png
Binary files differ
diff --git a/kmouth/icons/history/hi22-action-phrasehistory_print.png b/kmouth/icons/history/hi22-action-phrasehistory_print.png
new file mode 100644
index 0000000..a1eec0a
--- /dev/null
+++ b/kmouth/icons/history/hi22-action-phrasehistory_print.png
Binary files differ
diff --git a/kmouth/icons/history/hi22-action-phrasehistory_save.png b/kmouth/icons/history/hi22-action-phrasehistory_save.png
new file mode 100644
index 0000000..db87121
--- /dev/null
+++ b/kmouth/icons/history/hi22-action-phrasehistory_save.png
Binary files differ
diff --git a/kmouth/icons/history/hi32-action-phrasehistory_open.png b/kmouth/icons/history/hi32-action-phrasehistory_open.png
new file mode 100644
index 0000000..475ddbd
--- /dev/null
+++ b/kmouth/icons/history/hi32-action-phrasehistory_open.png
Binary files differ
diff --git a/kmouth/icons/history/hi32-action-phrasehistory_print.png b/kmouth/icons/history/hi32-action-phrasehistory_print.png
new file mode 100644
index 0000000..d63635a
--- /dev/null
+++ b/kmouth/icons/history/hi32-action-phrasehistory_print.png
Binary files differ
diff --git a/kmouth/icons/history/hi32-action-phrasehistory_save.png b/kmouth/icons/history/hi32-action-phrasehistory_save.png
new file mode 100644
index 0000000..4a39a25
--- /dev/null
+++ b/kmouth/icons/history/hi32-action-phrasehistory_save.png
Binary files differ
diff --git a/kmouth/icons/phrase/Makefile.am b/kmouth/icons/phrase/Makefile.am
new file mode 100644
index 0000000..15f3677
--- /dev/null
+++ b/kmouth/icons/phrase/Makefile.am
@@ -0,0 +1,9 @@
+####### kdevelop will overwrite this part!!! (begin)##########
+
+
+EXTRA_DIST = hi16-action-phrase.png hi16-action-phrase_new.png hi16-action-phrase_open.png hi16-action-phrase_save.png hi22-action-phrase.png hi22-action-phrase_new.png hi22-action-phrase_open.png hi22-action-phrase_save.png hi32-action-phrase.png hi32-action-phrase_new.png hi32-action-phrase_open.png hi32-action-phrase_save.png
+
+####### kdevelop will overwrite this part!!! (end)############
+
+kmouthiconsdir = $(kde_datadir)/kmouth/icons
+kmouthicons_ICON = AUTO
diff --git a/kmouth/icons/phrase/hi16-action-phrase.png b/kmouth/icons/phrase/hi16-action-phrase.png
new file mode 100644
index 0000000..709efd0
--- /dev/null
+++ b/kmouth/icons/phrase/hi16-action-phrase.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi16-action-phrase_new.png b/kmouth/icons/phrase/hi16-action-phrase_new.png
new file mode 100644
index 0000000..b8eaa20
--- /dev/null
+++ b/kmouth/icons/phrase/hi16-action-phrase_new.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi16-action-phrase_open.png b/kmouth/icons/phrase/hi16-action-phrase_open.png
new file mode 100644
index 0000000..2b87847
--- /dev/null
+++ b/kmouth/icons/phrase/hi16-action-phrase_open.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi16-action-phrase_save.png b/kmouth/icons/phrase/hi16-action-phrase_save.png
new file mode 100644
index 0000000..4d42077
--- /dev/null
+++ b/kmouth/icons/phrase/hi16-action-phrase_save.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi22-action-phrase.png b/kmouth/icons/phrase/hi22-action-phrase.png
new file mode 100644
index 0000000..4fbb2a9
--- /dev/null
+++ b/kmouth/icons/phrase/hi22-action-phrase.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi22-action-phrase_new.png b/kmouth/icons/phrase/hi22-action-phrase_new.png
new file mode 100644
index 0000000..5885d76
--- /dev/null
+++ b/kmouth/icons/phrase/hi22-action-phrase_new.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi22-action-phrase_open.png b/kmouth/icons/phrase/hi22-action-phrase_open.png
new file mode 100644
index 0000000..6556f6e
--- /dev/null
+++ b/kmouth/icons/phrase/hi22-action-phrase_open.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi22-action-phrase_save.png b/kmouth/icons/phrase/hi22-action-phrase_save.png
new file mode 100644
index 0000000..652c506
--- /dev/null
+++ b/kmouth/icons/phrase/hi22-action-phrase_save.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi32-action-phrase.png b/kmouth/icons/phrase/hi32-action-phrase.png
new file mode 100644
index 0000000..7b55281
--- /dev/null
+++ b/kmouth/icons/phrase/hi32-action-phrase.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi32-action-phrase_new.png b/kmouth/icons/phrase/hi32-action-phrase_new.png
new file mode 100644
index 0000000..c3e1ff1
--- /dev/null
+++ b/kmouth/icons/phrase/hi32-action-phrase_new.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi32-action-phrase_open.png b/kmouth/icons/phrase/hi32-action-phrase_open.png
new file mode 100644
index 0000000..1892548
--- /dev/null
+++ b/kmouth/icons/phrase/hi32-action-phrase_open.png
Binary files differ
diff --git a/kmouth/icons/phrase/hi32-action-phrase_save.png b/kmouth/icons/phrase/hi32-action-phrase_save.png
new file mode 100644
index 0000000..1634e7a
--- /dev/null
+++ b/kmouth/icons/phrase/hi32-action-phrase_save.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/Makefile.am b/kmouth/icons/phrasebook/Makefile.am
new file mode 100644
index 0000000..f5c9320
--- /dev/null
+++ b/kmouth/icons/phrasebook/Makefile.am
@@ -0,0 +1,9 @@
+####### kdevelop will overwrite this part!!! (begin)##########
+
+
+EXTRA_DIST = hi16-action-phrasebook.png hi16-action-phrasebook_new.png hi16-action-phrasebook_open.png hi16-action-phrasebook_save.png hi22-action-phrasebook.png hi22-action-phrasebook_new.png hi22-action-phrasebook_open.png hi22-action-phrasebook_save.png hi32-action-phrasebook.png hi32-action-phrasebook_new.png hi32-action-phrasebook_open.png hi32-action-phrasebook_save.png hi16-action-phrasebook_closed.png hi22-action-phrasebook_closed.png hi32-action-phrasebook_closed.png
+
+####### kdevelop will overwrite this part!!! (end)############
+
+kmouthiconsdir = $(kde_datadir)/kmouth/icons
+kmouthicons_ICON = AUTO
diff --git a/kmouth/icons/phrasebook/hi16-action-phrasebook.png b/kmouth/icons/phrasebook/hi16-action-phrasebook.png
new file mode 100644
index 0000000..394f70e
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi16-action-phrasebook.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi16-action-phrasebook_closed.png b/kmouth/icons/phrasebook/hi16-action-phrasebook_closed.png
new file mode 100644
index 0000000..5f1fb19
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi16-action-phrasebook_closed.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi16-action-phrasebook_new.png b/kmouth/icons/phrasebook/hi16-action-phrasebook_new.png
new file mode 100644
index 0000000..2de13d1
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi16-action-phrasebook_new.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi16-action-phrasebook_open.png b/kmouth/icons/phrasebook/hi16-action-phrasebook_open.png
new file mode 100644
index 0000000..494e886
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi16-action-phrasebook_open.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi16-action-phrasebook_save.png b/kmouth/icons/phrasebook/hi16-action-phrasebook_save.png
new file mode 100644
index 0000000..6164045
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi16-action-phrasebook_save.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi22-action-phrasebook.png b/kmouth/icons/phrasebook/hi22-action-phrasebook.png
new file mode 100644
index 0000000..c7b7a79
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi22-action-phrasebook.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi22-action-phrasebook_closed.png b/kmouth/icons/phrasebook/hi22-action-phrasebook_closed.png
new file mode 100644
index 0000000..7d87220
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi22-action-phrasebook_closed.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi22-action-phrasebook_new.png b/kmouth/icons/phrasebook/hi22-action-phrasebook_new.png
new file mode 100644
index 0000000..37b9492
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi22-action-phrasebook_new.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi22-action-phrasebook_open.png b/kmouth/icons/phrasebook/hi22-action-phrasebook_open.png
new file mode 100644
index 0000000..c58cfdd
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi22-action-phrasebook_open.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi22-action-phrasebook_save.png b/kmouth/icons/phrasebook/hi22-action-phrasebook_save.png
new file mode 100644
index 0000000..c221ce3
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi22-action-phrasebook_save.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi32-action-phrasebook.png b/kmouth/icons/phrasebook/hi32-action-phrasebook.png
new file mode 100644
index 0000000..6d339b8
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi32-action-phrasebook.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi32-action-phrasebook_closed.png b/kmouth/icons/phrasebook/hi32-action-phrasebook_closed.png
new file mode 100644
index 0000000..2e65c88
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi32-action-phrasebook_closed.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi32-action-phrasebook_new.png b/kmouth/icons/phrasebook/hi32-action-phrasebook_new.png
new file mode 100644
index 0000000..4e3136f
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi32-action-phrasebook_new.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi32-action-phrasebook_open.png b/kmouth/icons/phrasebook/hi32-action-phrasebook_open.png
new file mode 100644
index 0000000..518cdb7
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi32-action-phrasebook_open.png
Binary files differ
diff --git a/kmouth/icons/phrasebook/hi32-action-phrasebook_save.png b/kmouth/icons/phrasebook/hi32-action-phrasebook_save.png
new file mode 100644
index 0000000..3f55caf
--- /dev/null
+++ b/kmouth/icons/phrasebook/hi32-action-phrasebook_save.png
Binary files differ
diff --git a/kmouth/kmouth.cpp b/kmouth/kmouth.cpp
new file mode 100644
index 0000000..c78a010
--- /dev/null
+++ b/kmouth/kmouth.cpp
@@ -0,0 +1,484 @@
+/***************************************************************************
+ kmouth.cpp - description
+ -------------------
+ begin : Mon Aug 26 15:41:23 CEST 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// include files for QT
+#include <qdir.h>
+#include <qpainter.h>
+
+// include files for KDE
+#include <kiconloader.h>
+#include <kmenubar.h>
+#include <kstatusbar.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kstdaction.h>
+#include <kprinter.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+
+// application specific includes
+#include "kmouth.h"
+#include "phraselist.h"
+#include "phrasebook/phrasebook.h"
+#include "phrasebook/phrasebookdialog.h"
+#include "optionsdialog.h"
+#include "configwizard.h"
+
+#define ID_STATUS_MSG 1
+
+KMouthApp::KMouthApp(QWidget* , const char* name):KMainWindow(0, name)
+{
+ isConfigured = false;
+ config=kapp->config();
+
+ ///////////////////////////////////////////////////////////////////
+ // call inits to invoke all other construction parts
+ initStatusBar();
+ initPhraseList();
+ initActions();
+ optionsDialog = new OptionsDialog(this);
+ connect (optionsDialog, SIGNAL(configurationChanged ()),
+ this, SLOT(slotConfigurationChanged ()));
+ connect (optionsDialog, SIGNAL(configurationChanged ()),
+ phraseList, SLOT(configureCompletion ()));
+
+ phrases = new KActionCollection (this);
+
+ readOptions();
+ ConfigWizard *wizard = new ConfigWizard (this, "ConfigWizard", config);
+ if (wizard->configurationNeeded ()) {
+ if (wizard->requestConfiguration ()) {
+ isConfigured = true;
+ saveOptions();
+ wizard->saveConfig (config);
+ readOptions();
+ }
+ else
+ isConfigured = false;
+ }
+ else
+ isConfigured = true;
+ delete wizard;
+
+ if (isConfigured) {
+ phraseList->configureCompletion();
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ // disable actions at startup
+ fileSaveAs->setEnabled(false);
+ filePrint->setEnabled(false);
+}
+
+KMouthApp::~KMouthApp()
+{
+
+}
+
+bool KMouthApp::configured() {
+ return isConfigured;
+}
+
+void KMouthApp::initActions() {
+// The "File" menu
+ fileOpen = new KAction(i18n("&Open as History..."), "phrasehistory_open", KStdAccel::open(), this, SLOT(slotFileOpen()), actionCollection(),"file_open");
+ fileOpen->setStatusText(i18n("Opens an existing file as history"));
+ fileOpen->setWhatsThis (i18n("Opens an existing file as history"));
+
+ fileSaveAs = new KAction(i18n("Save &History As..."), "phrasehistory_save", KStdAccel::save(), this, SLOT(slotFileSaveAs()), actionCollection(),"file_save_as");
+ fileSaveAs->setStatusText(i18n("Saves the actual history as..."));
+ fileSaveAs->setWhatsThis (i18n("Saves the actual history as..."));
+
+ filePrint = new KAction(i18n("&Print History..."), "phrasehistory_print", KStdAccel::print(), this, SLOT(slotFilePrint()), actionCollection(),"file_print");
+ filePrint->setStatusText(i18n("Prints out the actual history"));
+ filePrint->setWhatsThis (i18n("Prints out the actual history"));
+
+ fileQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
+ fileQuit->setStatusText(i18n("Quits the application"));
+ fileQuit->setWhatsThis (i18n("Quits the application"));
+
+// The "Edit" menu
+ editCut = KStdAction::cut(phraseList, SLOT(cut()), actionCollection());
+ editCut->setStatusText(i18n("Cuts the selected section and puts it to the clipboard"));
+ editCut->setWhatsThis (i18n("Cuts the selected section and puts it to the clipboard. If there is some text selected in the edit field it is placed it on the clipboard. Otherwise the selected sentences in the history (if any) are placed on the clipboard."));
+
+ editCopy = KStdAction::copy(phraseList, SLOT(copy()), actionCollection());
+ editCopy->setStatusText(i18n("Copies the selected section to the clipboard"));
+ editCopy->setWhatsThis (i18n("Copies the selected section to the clipboard. If there is some text selected in the edit field it is copied to the clipboard. Otherwise the selected sentences in the history (if any) are copied to the clipboard."));
+
+ editPaste = KStdAction::paste(phraseList, SLOT(paste()), actionCollection());
+ editPaste->setStatusText(i18n("Pastes the clipboard contents to actual position"));
+ editPaste->setWhatsThis (i18n("Pastes the clipboard contents at the current cursor position into the edit field."));
+
+ editSpeak = new KAction (i18n("&Speak"), "speak", 0, phraseList, SLOT(speak()), actionCollection(),"edit_speak");
+ editSpeak->setStatusText(i18n("Speaks the currently active sentence(s)"));
+ editSpeak->setWhatsThis (i18n("Speaks the currently active sentence(s). If there is some text in the edit field it is spoken. Otherwise the selected sentences in the history (if any) are spoken."));
+
+// The "Phrase book" menu
+ phrasebookEdit = new KAction(i18n("&Edit..."), 0, 0, this, SLOT(slotEditPhrasebook()), actionCollection(),"phrasebook_edit");
+
+// The "Options" menu
+ viewMenuBar = KStdAction::showMenubar(this, SLOT(slotViewMenuBar()), actionCollection());
+ viewToolBar = KStdAction::showToolbar(this, SLOT(slotViewToolBar()), actionCollection());
+ viewToolBar->setStatusText(i18n("Enables/disables the toolbar"));
+ viewToolBar->setWhatsThis (i18n("Enables/disables the toolbar"));
+
+ viewPhrasebookBar = new KToggleAction (i18n("Show P&hrasebook Bar"), 0, 0, this, SLOT(slotViewPhrasebookBar()), actionCollection(), "showPhrasebookBar");
+ viewPhrasebookBar->setStatusText(i18n("Enables/disables the phrasebook bar"));
+ viewPhrasebookBar->setWhatsThis (i18n("Enables/disables the phrasebook bar"));
+
+ viewStatusBar = KStdAction::showStatusbar(this, SLOT(slotViewStatusBar()), actionCollection());
+ viewStatusBar->setStatusText(i18n("Enables/disables the statusbar"));
+ viewStatusBar->setWhatsThis (i18n("Enables/disables the statusbar"));
+
+ configureTTS = new KAction (i18n("&Configure KMouth..."), "configure", 0, this, SLOT(slotConfigureTTS()), actionCollection(), "configureTTS");
+ configureTTS->setStatusText(i18n("Opens the configuration dialog"));
+ configureTTS->setWhatsThis (i18n("Opens the configuration dialog"));
+
+// The "Help" menu
+ // The "Help" menu will automatically get created.
+
+// The popup menu of the list of spoken sentences
+ phraseListSpeak = new KAction (i18n("&Speak"), "speak", 0, phraseList, SLOT(speakListSelection()), actionCollection(), "phraselist_speak");
+ phraseListSpeak->setStatusText(i18n("Speaks the currently selected phrases in the history"));
+ phraseListSpeak->setWhatsThis (i18n("Speaks the currently selected phrases in the history"));
+
+ phraseListRemove = new KAction (i18n("&Delete"), "editdelete", 0, phraseList, SLOT(removeListSelection()), actionCollection(), "phraselist_remove");
+ phraseListRemove->setStatusText(i18n("Deletes the currently selected phrases from the history"));
+ phraseListRemove->setWhatsThis (i18n("Deletes the currently selected phrases from the history"));
+
+ phraseListCut = new KAction (i18n("Cu&t"), "editcut", 0, phraseList, SLOT(cutListSelection()), actionCollection(), "phraselist_cut");
+ phraseListCut->setStatusText(i18n("Cuts the currently selected phrases from the history and puts them to the clipboard"));
+ phraseListCut->setWhatsThis (i18n("Cuts the currently selected phrases from the history and puts them to the clipboard"));
+
+ phraseListCopy = new KAction (i18n("&Copy"), "editcopy", 0, phraseList, SLOT(copyListSelection()), actionCollection(), "phraselist_copy");
+ phraseListCut->setStatusText(i18n("Copies the currently selected phrases from the history to the clipboard"));
+ phraseListCut->setWhatsThis (i18n("Copies the currently selected phrases from the history to the clipboard"));
+
+ phraselistSelectAll = new KAction (i18n("Select &All Entries"), 0, 0, phraseList, SLOT(selectAllEntries()), actionCollection(),"phraselist_select_all");
+ phraselistSelectAll->setStatusText(i18n("Selects all phrases in the history"));
+ phraselistSelectAll->setWhatsThis (i18n("Selects all phrases in the history"));
+
+ phraselistDeselectAll = new KAction (i18n("D&eselect All Entries"), 0, 0, phraseList, SLOT(deselectAllEntries()), actionCollection(),"phraselist_deselect_all");
+ phraselistDeselectAll->setStatusText(i18n("Deselects all phrases in the history"));
+ phraselistDeselectAll->setWhatsThis (i18n("Deselects all phrases in the history"));
+
+// The popup menu of the edit field
+ // The popup menu of the edit field will automatically get created.
+
+ // use the absolute path to your kmouthui.rc file for testing purpose in createGUI();
+ createGUI();
+}
+
+void KMouthApp::initStatusBar()
+{
+ ///////////////////////////////////////////////////////////////////
+ // STATUSBAR
+ // TODO: add your own items you need for displaying current application status.
+ statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG);
+}
+
+void KMouthApp::initPhraseList()
+{
+ ////////////////////////////////////////////////////////////////////
+ // create the main widget here that is managed by KTMainWindow's view-region and
+ // connect the widget to your document to display document contents.
+
+ phraseList = new PhraseList(this);
+ setCentralWidget(phraseList);
+}
+
+void KMouthApp::openDocumentFile(const KURL& url)
+{
+ slotStatusMsg(i18n("Opening file..."));
+
+ phraseList->open (url);
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KMouthApp::saveOptions() {
+ if (isConfigured) {
+ config->setGroup("General Options");
+ config->writeEntry("Geometry", size());
+ config->writeEntry("Show Menubar", viewMenuBar->isChecked());
+ config->writeEntry("Show Toolbar", viewToolBar->isChecked());
+ config->writeEntry("Show Phrasebook Bar", viewPhrasebookBar->isChecked());
+ config->writeEntry("Show Statusbar",viewStatusBar->isChecked());
+ config->writeEntry("ToolBarPos", (int) toolBar("mainToolBar")->barPos());
+
+ if (phraseList != 0)
+ phraseList->saveCompletionOptions(config);
+ optionsDialog->saveOptions(config);
+ toolBar("mainToolBar")->saveSettings (config, "mainToolBar");
+ toolBar("phrasebookBar")->saveSettings (config, "phrasebookBar");
+ }
+}
+
+
+void KMouthApp::readOptions()
+{
+ config->setGroup("General Options");
+
+ // bar status settings
+ bool bViewMenubar = config->readBoolEntry("Show Menubar", true);
+ viewMenuBar->setChecked(bViewMenubar);
+ slotViewMenuBar();
+
+ bool bViewToolbar = config->readBoolEntry("Show Toolbar", true);
+ viewToolBar->setChecked(bViewToolbar);
+ slotViewToolBar();
+
+ bool bViewPhrasebookbar = config->readBoolEntry("Show Phrasebook Bar", true);
+ viewPhrasebookBar->setChecked(bViewPhrasebookbar);
+
+ bool bViewStatusbar = config->readBoolEntry("Show Statusbar", true);
+ viewStatusBar->setChecked(bViewStatusbar);
+ slotViewStatusBar();
+
+
+ // bar position settings
+ KToolBar::BarPosition toolBarPos;
+ toolBarPos=(KToolBar::BarPosition) config->readNumEntry("ToolBarPos", KToolBar::Top);
+ toolBar("mainToolBar")->setBarPos(toolBarPos);
+
+ QSize size=config->readSizeEntry("Geometry");
+ if(!size.isEmpty())
+ {
+ resize(size);
+ }
+
+ optionsDialog->readOptions(config);
+
+ toolBar("mainToolBar")->applySettings (config, "mainToolBar");
+ toolBar("phrasebookBar")->applySettings (config, "phrasebookBar");
+
+ QString standardBook = KApplication::kApplication()->dirs()->findResource("appdata", "standard.phrasebook");
+ if (!standardBook.isEmpty()) {
+ PhraseBook book;
+ book.open(KURL::fromPathOrURL( standardBook ));
+ slotPhrasebookConfirmed(book);
+ }
+ if (phraseList != 0)
+ phraseList->readCompletionOptions(config);
+}
+
+bool KMouthApp::queryClose()
+{
+ return true;
+}
+
+bool KMouthApp::queryExit()
+{
+ saveOptions();
+ return true;
+}
+
+void KMouthApp::enableMenuEntries(bool existSelectedEntries, bool existDeselectedEntries) {
+ bool existEntries = existSelectedEntries | existDeselectedEntries;
+ fileSaveAs->setEnabled (existEntries);
+ filePrint->setEnabled (existEntries);
+
+ phraselistSelectAll->setEnabled (existDeselectedEntries);
+
+ phraselistDeselectAll->setEnabled (existSelectedEntries);
+ phraseListSpeak->setEnabled (existSelectedEntries);
+ phraseListRemove->setEnabled (existSelectedEntries);
+ phraseListCut->setEnabled (existSelectedEntries);
+ phraseListCopy->setEnabled (existSelectedEntries);
+}
+
+/////////////////////////////////////////////////////////////////////
+// SLOT IMPLEMENTATION
+/////////////////////////////////////////////////////////////////////
+
+void KMouthApp::slotFileOpen() {
+ slotStatusMsg(i18n("Opening file..."));
+
+ phraseList->open();
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KMouthApp::slotFileSaveAs() {
+ slotStatusMsg(i18n("Saving history with a new filename..."));
+
+ phraseList->save();
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KMouthApp::slotFilePrint()
+{
+ slotStatusMsg(i18n("Printing..."));
+
+ KPrinter printer;
+ if (printer.setup(this))
+ {
+ phraseList->print(&printer);
+ }
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KMouthApp::slotFileQuit()
+{
+ slotStatusMsg(i18n("Exiting..."));
+ saveOptions();
+ // close the first window, the list makes the next one the first again.
+ // This ensures that queryClose() is called on each window to ask for closing
+ KMainWindow* w;
+ if (memberList)
+ {
+ for(w=memberList->first(); w!=0; w=memberList->first())
+ {
+ // only close the window if the closeEvent is accepted. If the user presses Cancel on the saveModified() dialog,
+ // the window and the application stay open.
+ if(!w->close())
+ break;
+ memberList->removeRef(w);
+ }
+ }
+}
+
+void KMouthApp::slotEditPhrasebook () {
+ PhraseBookDialog *phraseBookDialog = PhraseBookDialog::get();
+ // As we do not know whether the we are already connected to the slot,
+ // we first disconnect and then connect again.
+ disconnect (phraseBookDialog, SIGNAL(phrasebookConfirmed (PhraseBook &)),
+ this, SLOT(slotPhrasebookConfirmed (PhraseBook &)));
+ connect (phraseBookDialog, SIGNAL(phrasebookConfirmed (PhraseBook &)),
+ this, SLOT(slotPhrasebookConfirmed (PhraseBook &)));
+
+ // As we do not know whether the phrase book edit window is already open,
+ // we first open and then raise it, so that it is surely the top window.
+ phraseBookDialog->show();
+ phraseBookDialog->raise();
+}
+
+void KMouthApp::slotViewMenuBar() {
+ slotStatusMsg(i18n("Toggling menubar..."));
+
+ if(!viewMenuBar->isChecked())
+ menuBar()->hide();
+ else
+ menuBar()->show();
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KMouthApp::slotViewToolBar()
+{
+ slotStatusMsg(i18n("Toggling toolbar..."));
+ ///////////////////////////////////////////////////////////////////
+ // turn Toolbar on or off
+ if(!viewToolBar->isChecked())
+ {
+ toolBar("mainToolBar")->hide();
+ }
+ else
+ {
+ toolBar("mainToolBar")->show();
+ }
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KMouthApp::slotViewPhrasebookBar()
+{
+ slotStatusMsg(i18n("Toggling phrasebook bar..."));
+ ///////////////////////////////////////////////////////////////////
+ // turn Toolbar on or off
+ if(!viewPhrasebookBar->isChecked())
+ {
+ toolBar("phrasebookBar")->hide();
+ }
+ else
+ {
+ toolBar("phrasebookBar")->show();
+ }
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KMouthApp::slotViewStatusBar()
+{
+ slotStatusMsg(i18n("Toggle the statusbar..."));
+ ///////////////////////////////////////////////////////////////////
+ //turn Statusbar on or off
+ if(!viewStatusBar->isChecked())
+ {
+ statusBar()->hide();
+ }
+ else
+ {
+ statusBar()->show();
+ }
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+void KMouthApp::slotConfigureTTS() {
+ phraseList->saveWordCompletion();
+ optionsDialog->show();
+}
+
+
+void KMouthApp::slotStatusMsg(const QString &text)
+{
+ ///////////////////////////////////////////////////////////////////
+ // change status message permanently
+ statusBar()->clear();
+ statusBar()->changeItem(text, ID_STATUS_MSG);
+}
+
+void KMouthApp::slotPhrasebookConfirmed (PhraseBook &book) {
+ QString name = "phrasebooks";
+ QPopupMenu *popup = (QPopupMenu *)factory()->container(name, this);
+ KToolBar *toolbar = toolBar ("phrasebookBar");
+
+ KActionPtrList actions = phrases->actions ();
+ KActionPtrList::iterator iter;
+ for (iter = actions.begin(); iter != actions.end(); ++iter) {
+ (*iter)->unplugAll();
+ }
+ delete phrases;
+
+ phrases = new KActionCollection (this, actionCollection());
+ book.addToGUI (popup, toolbar, phrases, this, SLOT(slotPhraseSelected (const QString &)));
+
+ QString bookLocation = KApplication::kApplication()->dirs()->saveLocation ("appdata", "/");
+ if (!bookLocation.isNull() && !bookLocation.isEmpty()) {
+ book.save (KURL::fromPathOrURL( bookLocation + "standard.phrasebook" ));
+ }
+}
+
+void KMouthApp::slotConfigurationChanged()
+{
+ optionsDialog->saveOptions (config);
+}
+
+void KMouthApp::slotPhraseSelected (const QString &phrase) {
+ phraseList->insert (phrase);
+ if (optionsDialog->isSpeakImmediately())
+ phraseList->speak ();
+}
+
+TextToSpeechSystem *KMouthApp::getTTSSystem() const {
+ return optionsDialog->getTTSSystem();
+}
+
+#include "kmouth.moc"
diff --git a/kmouth/kmouth.desktop b/kmouth/kmouth.desktop
new file mode 100644
index 0000000..2ab68da
--- /dev/null
+++ b/kmouth/kmouth.desktop
@@ -0,0 +1,80 @@
+# KDE Config File
+[Desktop Entry]
+Type=Application
+Exec=kmouth -caption "%c" %i %m
+Icon=kmouth
+DocPath=kmouth/index.html
+Comment=
+Comment[ro]=Un utilitar de mărit zone ale ecranului
+Terminal=false
+Name=KMouth
+Name[ar]=برنامج KMouth
+Name[cy]=KCeg
+Name[eo]=KBuŝo
+Name[hi]=के-माउथ
+Name[is]=KMunnur
+Name[km]= KMouth
+Name[ne]=केडीई माउथ
+Name[pa]=ਕੇ-ਮੂੰਹ
+Name[ro]=Vorbitor
+Name[sv]=Kmouth
+Name[ta]=K வாய்
+Name[tg]=KДаҳон
+Name[tr]=Kmouth
+Name[vi]=Mồm K
+Name[zh_CN]=K 语音精灵
+GenericName=Speech Synthesizer Frontend
+GenericName[ar]=واجهة النَظام الصَوتي
+GenericName[bg]=Синтезатор на глас
+GenericName[bs]=Program za sintezu govora
+GenericName[ca]=Interfície per al sintetitzador de veu
+GenericName[cs]=Rozhraní hlasového syntetizátoru
+GenericName[cy]=Blaen-wyneb Syntheseisydd Lleferydd
+GenericName[da]=Forende til tale-synthesizer
+GenericName[de]=Oberfläche für Sprachsynthesizer
+GenericName[el]=Συνθέτης ομιλίας
+GenericName[en_GB]=Speech Synthesiser Frontend
+GenericName[eo]=Fasado Por Parolsintezilo
+GenericName[es]=Interfaz de usuario para síntesis de voz
+GenericName[et]=Kõnesüntesaator
+GenericName[eu]=Hizkera-sintetizadorearen interfazea
+GenericName[fa]=پایانۀ ترکیب‌دهندۀ گفتار
+GenericName[fi]=Puhesyntetisaattorin käyttöliittymä
+GenericName[fr]=Interface graphique de synthèse vocale
+GenericName[ga]=Clár tosaigh an sintéiseoir cainte
+GenericName[gl]=Interface para o Sintetizador de Voz
+GenericName[hi]=स्पीच सिंथेसाइज़र फ्रन्टएण्ड
+GenericName[hu]=Beszédszintetizátor
+GenericName[is]=Viðmót á talgerfilinn
+GenericName[it]=Interfaccia grafica per il sintetizzatore vocale
+GenericName[ja]=スピーチシンセサイザフロントエンド
+GenericName[ka]=საუბრის სინქრონიზაციის ინტერფეისი
+GenericName[km]= ផ្នែក​ខាង​មុខ​កម្មវិធី​សង្គ្រោះ​ការ​និយាយ
+GenericName[lt]=Kalbos sintezatoriaus naudotojo sąsaja
+GenericName[mk]=Преден крај на синтисајзерот за говор
+GenericName[ms]=Antaramuka Pensintesis Pertuturan
+GenericName[mt]=Programm Għall-Ħolqien ta' Diskors Artifiċjali
+GenericName[nb]=Brukerflate for talesystem
+GenericName[nds]=Böversiet för de Blicksnuut
+GenericName[ne]=संवाद सिन्थेसाइजर फ्रन्टइन्ड
+GenericName[nl]=Spraaksynthesizer
+GenericName[nn]=Grensesnitt for talesyntese
+GenericName[pa]=ਬੋਲੀ ਸੰਸਲੇਸ਼ਣ ਮੁੱਖ
+GenericName[pl]=Program obsługujący syntezator mowy
+GenericName[pt]=Sintetizador de Fala
+GenericName[pt_BR]=Interface do Sintetizador de Fala
+GenericName[ro]=Interfaţă pentru sinteză vocală
+GenericName[ru]=Интерфейс к синтезаторам речи
+GenericName[sk]=Rozhranie pre syntetizátor reči
+GenericName[sl]=Vmesnik za sintezo govora
+GenericName[sr]=Интерфејс за синтетизатор говора
+GenericName[sr@Latn]=Interfejs za sintetizator govora
+GenericName[sv]=Gränssnitt för talsyntes
+GenericName[tg]=Сухани Синтезатори Пешбуда
+GenericName[th]=ฟร้อนต์เอนด์สำหรับเครื่องสังเคราะห์คำพูด
+GenericName[tr]=Konuşma Sentezleyici Arayüzü
+GenericName[uk]=Графічний інтерфейс синтезатора мовлення
+GenericName[vi]=Giao diện Tổng hợp Giọng nói
+GenericName[zh_CN]=语音合成器前端
+GenericName[zh_TW]=語音合成器前端
+Categories=Qt;KDE;Utility;Accessibility;
diff --git a/kmouth/kmouth.h b/kmouth/kmouth.h
new file mode 100644
index 0000000..6ff6bad
--- /dev/null
+++ b/kmouth/kmouth.h
@@ -0,0 +1,187 @@
+/***************************************************************************
+ kmouth.h - description
+ -------------------
+ begin : Mon Aug 26 15:41:23 CEST 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KMOUTH_H
+#define KMOUTH_H
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// include files for Qt
+
+// include files for KDE
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <kaccel.h>
+#include <kaction.h>
+#include <kurl.h>
+
+// forward declaration of the KMouth classes
+class PhraseList;
+class OptionsDialog;
+class TextToSpeechSystem;
+class PhraseBookDialog;
+class PhraseBook;
+
+/**
+ * The base class for KMouth application windows. It sets up the main
+ * window and reads the config file as well as providing a menubar, toolbar
+ * and statusbar.
+ * KMouthApp reimplements the methods that KMainWindow provides for main window handling and supports
+ * full session management as well as using KActions.
+ * @see KMainWindow
+ * @see KApplication
+ * @see KConfig
+ *
+ * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team.
+ * @version KDevelop version 1.2 code generation
+ */
+class KMouthApp : public KMainWindow
+{
+ Q_OBJECT
+
+ public:
+ /** construtor of KMouthApp, calls all init functions to create the application.
+ */
+ KMouthApp(QWidget* parent=0, const char* name=0);
+ ~KMouthApp();
+ /** Returns true if the configuration wizard was not needed or when it
+ * was successfully completed.
+ */
+ bool configured();
+ /** opens a file specified by commandline option
+ */
+ void openDocumentFile(const KURL& url=KURL());
+
+ TextToSpeechSystem *getTTSSystem() const;
+
+ /** called by PhraseList in order to enable or disable the actions depending
+ * on the contents of the phrase list.
+ */
+ void enableMenuEntries(bool existSelectedEntries, bool existDeselectedEntries);
+
+ protected:
+ /** save general Options like all bar positions and status as well as the geometry and the recent file list to the configuration
+ * file
+ */
+ void saveOptions();
+ /** read general Options again and initialize all variables like the recent file list
+ */
+ void readOptions();
+ /** initializes the phrase list */
+ void initPhraseList();
+ /** initializes the KActions of the application */
+ void initActions();
+ /** sets up the statusbar for the main window by initialzing a statuslabel.
+ */
+ void initStatusBar();
+ /** queryClose is called by KTMainWindow on each closeEvent of a window. Against the
+ * default implementation (only returns true), this calles saveModified() on the document object to ask if the document shall
+ * be saved if Modified; on cancel the closeEvent is rejected.
+ * @see KTMainWindow#queryClose
+ * @see KTMainWindow#closeEvent
+ */
+ virtual bool queryClose();
+ /** queryExit is called by KTMainWindow when the last window of the application is going to be closed during the closeEvent().
+ * Against the default implementation that just returns true, this calls saveOptions() to save the settings of the last window's
+ * properties.
+ * @see KTMainWindow#queryExit
+ * @see KTMainWindow#closeEvent
+ */
+ virtual bool queryExit();
+
+ public slots:
+ /** open a file and load it into the history */
+ void slotFileOpen();
+ /** save a document */
+ void slotFileSaveAs();
+ /** print the actual file */
+ void slotFilePrint();
+ /** closes all open windows by calling close() on each memberList item until the list is empty, then quits the application.
+ * If queryClose() returns false because the user canceled the saveModified() dialog, the closing breaks.
+ */
+ void slotFileQuit();
+ /** edits the phrase books
+ */
+ void slotEditPhrasebook ();
+ /** toggles the menu bar
+ */
+ void slotViewMenuBar();
+ /** toggles the toolbar
+ */
+ void slotViewToolBar();
+ /** toggles the phrasebook bar
+ */
+ void slotViewPhrasebookBar();
+ /** toggles the statusbar
+ */
+ void slotViewStatusBar();
+ /** configures the TTS system
+ */
+ void slotConfigureTTS();
+ /** changes the statusbar contents for the standard label permanently, used to indicate current actions.
+ * @param text the text that is displayed in the statusbar
+ */
+ void slotStatusMsg(const QString &text);
+
+ void slotPhrasebookConfirmed (PhraseBook &book);
+
+ void slotConfigurationChanged();
+
+ void slotPhraseSelected (const QString &phrase);
+
+ private:
+ bool isConfigured;
+ /** the configuration object of the application */
+ KConfig *config;
+ /** The phrase list */
+ PhraseList *phraseList;
+ /** The configuration dialog */
+ OptionsDialog *optionsDialog;
+
+ // KAction pointers to enable/disable actions
+ KAction* fileOpen;
+ KAction* fileSaveAs;
+ KAction* filePrint;
+ KAction* fileQuit;
+
+ KAction* editCut;
+ KAction* editCopy;
+ KAction* editPaste;
+ KAction* editSpeak;
+
+ KActionCollection *phrases;
+ KAction* phrasebookEdit;
+
+ KToggleAction* viewMenuBar;
+ KToggleAction* viewToolBar;
+ KToggleAction* viewPhrasebookBar;
+ KToggleAction* viewStatusBar;
+ KAction* configureTTS;
+
+ KAction* phraseListSpeak;
+ KAction* phraseListRemove;
+ KAction* phraseListCut;
+ KAction* phraseListCopy;
+ KAction* phraselistSelectAll;
+ KAction* phraselistDeselectAll;
+};
+
+#endif // KMOUTH_H
diff --git a/kmouth/kmouth.lsm b/kmouth/kmouth.lsm
new file mode 100644
index 0000000..0657065
--- /dev/null
+++ b/kmouth/kmouth.lsm
@@ -0,0 +1,14 @@
+Begin3
+Title: KMouth
+Version: 0.1
+Entered-date:
+Description: Lets your computer speak
+Keywords:
+Author: Gunnar Schmi Dt <kmouth@schmi-dt.de>
+Maintained-by: Gunnar Schmi Dt <kmouth@schmi-dt.de>
+Primary-site:
+Home-page: http://www.schmi-dt.de/kmouth/index.en.html
+Original-site:
+Platforms: Linux and other Unices
+Copying-policy: GNU Public License
+End
diff --git a/kmouth/kmouthrc b/kmouth/kmouthrc
new file mode 100644
index 0000000..2b82c9f
--- /dev/null
+++ b/kmouth/kmouthrc
@@ -0,0 +1,9 @@
+[General Options]
+Geometry=550,400
+
+[mainToolBar]
+Index=0
+
+[phrasebookBar]
+IconText=IconTextRight
+Index=1
diff --git a/kmouth/kmouthui.rc b/kmouth/kmouthui.rc
new file mode 100644
index 0000000..3a2ed82
--- /dev/null
+++ b/kmouth/kmouthui.rc
@@ -0,0 +1,93 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="kmouth" version="1">
+<MenuBar>
+ <Menu name="file" noMerge="1"><text>&amp;File</text>
+ <Action name="file_open"/>
+ <Action name="file_save_as"/>
+ <Action name="file_print"/>
+ <Separator />
+ <Action name="file_quit"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="edit_speak"/>
+ </Menu>
+ <Menu name="phrasebooks"><text>&amp;Phrase Books</text>
+ <Action name="phrasebook_edit"/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Action name="showPhrasebookBar" append="show_merge"/>
+ <Action name="configureTTS" append="configure_merge"/>
+ </Menu>
+</MenuBar>
+
+<Menu name="phraselist_selection_popup" noMerge="1">
+ <Action name="phraselist_speak"/>
+ <!-- Separator / -->
+ <!-- Action name="phraselist_into_phrasebook"/ -->
+ <Separator />
+ <Action name="phraselist_remove"/>
+ <Separator />
+ <Action name="phraselist_cut"/>
+ <Action name="phraselist_copy"/>
+ <Separator />
+ <Action name="phraselist_select_all"/>
+ <Action name="phraselist_deselect_all"/>
+ <Separator />
+ <Action name="file_open"/>
+ <Action name="file_save_as"/>
+</Menu>
+
+<Menu name="phraselist_popup" noMerge="1">
+ <Action name="phraselist_select_all"/>
+ <Action name="phraselist_deselect_all"/>
+ <Separator />
+ <Action name="file_open"/>
+ <Action name="file_save_as"/>
+</Menu>
+
+<Menu name="phrasebook_popup" noMerge="1">
+ <Action name="phrasebook_paste"/>
+ <Separator />
+ <Action name="phrasebook_add_chapter"/>
+ <Action name="phrasebook_add_phrase"/>
+ <Separator />
+ <Action name="phrasebook_import"/>
+ <Action name="phrasebook_import_standard_book"/>
+ <Action name="phrasebook_export"/>
+</Menu>
+
+<Menu name="phrasebook_book_popup" noMerge="1">
+ <Action name="phrasebook_remove"/>
+ <Separator />
+ <Action name="phrasebook_cut"/>
+ <Action name="phrasebook_copy"/>
+ <Action name="phrasebook_paste"/>
+ <Separator />
+ <Action name="phrasebook_add_chapter"/>
+ <Action name="phrasebook_add_phrase"/>
+ <Separator />
+ <Action name="phrasebook_import"/>
+ <Action name="phrasebook_import_standard_book"/>
+ <Action name="phrasebook_export"/>
+</Menu>
+
+<Menu name="phrasebook_phrase_popup" noMerge="1">
+ <Action name="phrasebook_remove"/>
+ <Separator />
+ <Action name="phrasebook_cut"/>
+ <Action name="phrasebook_copy"/>
+ <Separator />
+ <Action name="phrase_export"/>
+</Menu>
+
+<ToolBar name="mainToolBar" noMerge="1">
+ <Action name="file_open"/>
+ <Action name="file_open_history"/>
+ <Action name="file_save_as"/>
+ <Action name="file_print"/>
+ <Separator />
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+</ToolBar>
+</kpartgui>
diff --git a/kmouth/main.cpp b/kmouth/main.cpp
new file mode 100644
index 0000000..0f9c875
--- /dev/null
+++ b/kmouth/main.cpp
@@ -0,0 +1,73 @@
+/***************************************************************************
+ main.cpp - description
+ -------------------
+ begin : Mon Aug 26 15:41:23 CEST 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kuniqueapplication.h>
+
+#include "kmouth.h"
+#include "version.h"
+
+static const char description[] =
+ I18N_NOOP("A type-and-say front end for speech synthesizers");
+// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE
+
+
+static KCmdLineOptions options[] =
+{
+ { "+[File]", I18N_NOOP("History file to open"), 0 },
+ KCmdLineLastOption
+ // INSERT YOUR COMMANDLINE OPTIONS HERE
+};
+
+int main(int argc, char *argv[])
+{
+
+ KAboutData aboutData( "kmouth", I18N_NOOP("KMouth"),
+ KMOUTH_VERSION, description, KAboutData::License_GPL,
+ "(c) 2002/2003, Gunnar Schmi Dt", 0, "http://www.schmi-dt.de/kmouth/index.en.html", "kmouth@schmi-dt.de");
+ aboutData.addAuthor("Gunnar Schmi Dt",0, "kmouth@schmi-dt.de");
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+
+ aboutData.addCredit("Olaf Schmidt", I18N_NOOP("Tips, extended phrase books"), 0, 0);
+ KApplication app;
+
+ if (app.isRestored())
+ {
+ RESTORE(KMouthApp);
+ }
+ else
+ {
+ KMouthApp *kmouth = new KMouthApp();
+ if (!kmouth->configured())
+ return 0;
+
+ kmouth->show();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if (args->count())
+ {
+ kmouth->openDocumentFile(args->url(0));
+ }
+ args->clear();
+ }
+ return app.exec();
+}
diff --git a/kmouth/optionsdialog.cpp b/kmouth/optionsdialog.cpp
new file mode 100644
index 0000000..4873167
--- /dev/null
+++ b/kmouth/optionsdialog.cpp
@@ -0,0 +1,238 @@
+/***************************************************************************
+ optionsdialog.cpp - description
+ -------------------
+ begin : Don Nov 21 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qgrid.h>
+#include <qtabwidget.h>
+#include <qpixmap.h>
+#include <qfile.h>
+
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kcmodule.h>
+#include <klibloader.h>
+#include <kparts/componentfactory.h>
+
+#include "optionsdialog.h"
+#include "wordcompletion/wordcompletionwidget.h"
+
+#include "texttospeechconfigurationwidget.h"
+#include "speech.h"
+
+PreferencesWidget::PreferencesWidget (QWidget *parent, const char *name)
+ : PreferencesUI (parent, name)
+{
+ speakCombo->setCurrentItem (1);
+ speak = false;
+
+ closeCombo->setCurrentItem (2);
+ save = 2;
+}
+
+PreferencesWidget::~PreferencesWidget() {
+}
+
+void PreferencesWidget::cancel() {
+ if (speak)
+ speakCombo->setCurrentItem (0);
+ else
+ speakCombo->setCurrentItem (1);
+ closeCombo->setCurrentItem (save);
+}
+
+void PreferencesWidget::ok() {
+ speak = speakCombo->currentItem () == 0;
+ save = closeCombo->currentItem ();
+}
+
+void PreferencesWidget::readOptions (KConfig *config) {
+ config->setGroup("Preferences");
+ if (config->hasKey("AutomaticSpeak"))
+ if (config->readEntry ("AutomaticSpeak") == "Yes")
+ speak = true;
+ else
+ speak = false;
+ else
+ speak = false;
+
+ config->setGroup("Notification Messages");
+ if (config->hasKey("AutomaticSave"))
+ if (config->readEntry ("AutomaticSave") == "Yes")
+ save = 0;
+ else
+ save = 1;
+ else
+ save = 2;
+
+ if (speak)
+ speakCombo->setCurrentItem (0);
+ else
+ speakCombo->setCurrentItem (1);
+ closeCombo->setCurrentItem (save);
+}
+
+void PreferencesWidget::saveOptions (KConfig *config) {
+ config->setGroup("Preferences");
+ if (speak)
+ config->writeEntry ("AutomaticSpeak", "Yes");
+ else
+ config->writeEntry ("AutomaticSpeak", "No");
+
+ config->setGroup("Notification Messages");
+ if (save == 0)
+ config->writeEntry ("AutomaticSave", "Yes");
+ else if (save == 1)
+ config->writeEntry ("AutomaticSave", "No");
+ else
+ config->deleteEntry ("AutomaticSave");
+}
+
+bool PreferencesWidget::isSpeakImmediately () {
+ return speak;
+}
+
+/***************************************************************************/
+
+OptionsDialog::OptionsDialog (QWidget *parent)
+ : KDialogBase(IconList, i18n("Configuration"), Ok|Apply|Cancel|Help, Ok,
+ parent, "configuration", false, true)
+{
+ setHelp ("config-dialog");
+
+ QPixmap iconGeneral = KGlobal::iconLoader()->loadIcon("configure", KIcon::NoGroup, KIcon::SizeMedium);
+ QGrid *pageGeneral = addGridPage (1, Qt::Horizontal, i18n("General Options"), QString::null, iconGeneral);
+
+ tabCtl = new QTabWidget (pageGeneral, "general");
+
+ behaviourWidget = new PreferencesWidget (tabCtl, "prefPage");
+ behaviourWidget->layout()->setMargin(KDialog::marginHint());
+ tabCtl->addTab (behaviourWidget, i18n("&Preferences"));
+
+ commandWidget = new TextToSpeechConfigurationWidget (tabCtl, "ttsTab");
+ commandWidget->layout()->setMargin(KDialog::marginHint());
+ tabCtl->addTab (commandWidget, i18n("&Text-to-Speech"));
+
+ QPixmap iconCompletion = KGlobal::iconLoader()->loadIcon("keyboard", KIcon::NoGroup, KIcon::SizeMedium);
+ QGrid *pageCompletion = addGridPage (1, Qt::Horizontal, i18n("Word Completion"), QString::null, iconCompletion);
+ completionWidget = new WordCompletionWidget(pageCompletion, "Word Completion widget");
+
+ kttsd = loadKttsd();
+ if (kttsd != 0) {
+ QPixmap iconKttsd = KGlobal::iconLoader()->loadIcon("multimedia", KIcon::NoGroup, KIcon::SizeMedium);
+ QGrid *pageKttsd = addGridPage (1, Qt::Horizontal, i18n("KTTSD Speech Service"),
+ i18n("KDE Text-to-Speech Daemon Configuration"), iconKttsd);
+
+ kttsd->reparent(pageKttsd,0,QPoint(0,0),true);
+ }
+}
+
+OptionsDialog::~OptionsDialog() {
+ unloadKttsd();
+}
+
+void OptionsDialog::slotCancel() {
+ KDialogBase::slotCancel();
+ commandWidget->cancel();
+ behaviourWidget->cancel();
+ completionWidget->load();
+ if (kttsd != 0)
+ kttsd->load ();
+}
+
+void OptionsDialog::slotOk() {
+ KDialogBase::slotOk();
+ commandWidget->ok();
+ behaviourWidget->ok();
+ completionWidget->save();
+ emit configurationChanged();
+ if (kttsd != 0)
+ kttsd->save ();
+
+}
+
+void OptionsDialog::slotApply() {
+ KDialogBase::slotApply();
+ commandWidget->ok();
+ behaviourWidget->ok();
+ completionWidget->save();
+ emit configurationChanged();
+ if (kttsd != 0)
+ kttsd->save ();
+}
+
+TextToSpeechSystem *OptionsDialog::getTTSSystem() const {
+ return commandWidget->getTTSSystem();
+}
+
+void OptionsDialog::readOptions (KConfig *config) {
+ commandWidget->readOptions (config, "TTS System");
+ behaviourWidget->readOptions (config);
+}
+
+void OptionsDialog::saveOptions (KConfig *config) {
+ commandWidget->saveOptions (config, "TTS System");
+ behaviourWidget->saveOptions (config);
+ config->sync();
+}
+
+bool OptionsDialog::isSpeakImmediately () {
+ return behaviourWidget->isSpeakImmediately ();
+}
+
+KCModule *OptionsDialog::loadKttsd () {
+ KLibLoader *loader = KLibLoader::self();
+
+ QString libname = "kcm_kttsd";
+ KLibrary *lib = loader->library(QFile::encodeName(libname));
+
+ if (lib == 0) {
+ libname = "libkcm_kttsd";
+ lib = loader->library(QFile::encodeName("libkcm_kttsd"));
+ }
+
+ if (lib != 0) {
+ QString initSym("init_");
+ initSym += libname;
+
+ if (lib->hasSymbol(QFile::encodeName(initSym))) {
+ // Reuse "lib" instead of letting createInstanceFromLibrary recreate it
+ KLibFactory *factory = lib->factory();
+ if (factory != 0) {
+ KCModule *module = KParts::ComponentFactory::createInstanceFromFactory<KCModule> (factory);
+ if (module)
+ return module;
+ }
+ }
+
+ lib->unload();
+ }
+ return 0;
+}
+
+void OptionsDialog::unloadKttsd () {
+ KLibLoader *loader = KLibLoader::self();
+ loader->unloadLibrary(QFile::encodeName("libkcm_kttsd"));
+ loader->unloadLibrary(QFile::encodeName("kcm_kttsd"));
+}
+
+#include "optionsdialog.moc"
diff --git a/kmouth/optionsdialog.h b/kmouth/optionsdialog.h
new file mode 100644
index 0000000..8597e70
--- /dev/null
+++ b/kmouth/optionsdialog.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ optionsdialog.h - description
+ -------------------
+ begin : Don Nov 21 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// $Id$
+
+#ifndef OPTIONSDIALOG_H
+#define OPTIONSDIALOG_H
+
+#include <qobject.h>
+#include "preferencesui.h"
+#include "texttospeechconfigurationwidget.h"
+class QTabWidget;
+class KCModule;
+class WordCompletionWidget;
+
+/**This class represents a configuration widget for user preferences.
+ *@author Gunnar Schmi Dt
+ */
+
+class PreferencesWidget : public PreferencesUI {
+ Q_OBJECT
+public:
+ PreferencesWidget(QWidget *parent, const char *name);
+ ~PreferencesWidget();
+
+ void readOptions (KConfig *config);
+ void saveOptions (KConfig *config);
+
+ void ok();
+ void cancel();
+
+ bool isSpeakImmediately();
+
+private:
+ bool speak;
+ int save;
+};
+
+/**This class represents a configuration dialog for the options of KMouth.
+ *@author Gunnar Schmi Dt
+ */
+
+class OptionsDialog : public KDialogBase {
+ Q_OBJECT
+public:
+ OptionsDialog(QWidget *parent);
+ ~OptionsDialog();
+
+ void slotCancel();
+ void slotOk();
+ void slotApply();
+
+ TextToSpeechSystem *getTTSSystem() const;
+
+ void readOptions (KConfig *config);
+ void saveOptions (KConfig *config);
+
+ bool isSpeakImmediately();
+
+signals:
+ void configurationChanged ();
+
+private:
+ QTabWidget *tabCtl;
+ TextToSpeechConfigurationWidget *commandWidget;
+ PreferencesWidget *behaviourWidget;
+ KCModule *kttsd;
+ WordCompletionWidget *completionWidget;
+
+ KCModule *loadKttsd ();
+ void unloadKttsd ();
+};
+
+#endif
diff --git a/kmouth/phrasebook/Makefile.am b/kmouth/phrasebook/Makefile.am
new file mode 100644
index 0000000..bc0b31c
--- /dev/null
+++ b/kmouth/phrasebook/Makefile.am
@@ -0,0 +1,16 @@
+####### kdevelop will overwrite this part!!! (begin)##########
+noinst_LIBRARIES = libphrasebook.a
+
+INCLUDES = $(all_includes)
+
+libphrasebook_a_METASOURCES = AUTO
+
+libphrasebook_a_SOURCES = buttonboxui.ui phrasetree.cpp phrasebookparser.cpp phrasebookdialog.cpp phrasebook.cpp
+
+
+EXTRA_DIST = phrasebook.cpp phrasebook.h phrasebookdialog.cpp phrasebookdialog.h phrasebookparser.cpp phrasebookparser.h phrasetree.cpp phrasetree.h phrasebookdialogui.rc buttonboxui.ui
+
+####### kdevelop will overwrite this part!!! (end)############
+
+rcdir = $(kde_datadir)/kmouth
+rc_DATA = phrasebookdialogui.rc
diff --git a/kmouth/phrasebook/buttonboxui.ui b/kmouth/phrasebook/buttonboxui.ui
new file mode 100644
index 0000000..abc999b
--- /dev/null
+++ b/kmouth/phrasebook/buttonboxui.ui
@@ -0,0 +1,107 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>ButtonBoxUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ButtonBoxUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>278</width>
+ <height>141</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Currently Selected Phrase or Phrase Book</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>phrasebox</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Currently Selected Phrase or Phrase Book</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QWidget" row="3" column="2">
+ <property name="name">
+ <cstring>keyButtonPlace</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>lineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this line edit you define the name of a sub-phrasebook or the contents of a phrase.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>noKey</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;None</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this option then the selected phrase will not be reachable by a keyboard shortcut.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="1">
+ <property name="name">
+ <cstring>customKey</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;ustom</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this option then the selected phrase will be reachable by a keyboard shortcut. You can change the shortcut with the button next to this option.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>shortcutLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Shortcut for the phrase:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>textLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Text of the &amp;phrase:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>lineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this line edit you define the name of a sub-phrasebook or the contents of a phrase.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kmouth/phrasebook/phrasebook.cpp b/kmouth/phrasebook/phrasebook.cpp
new file mode 100644
index 0000000..0ec8da3
--- /dev/null
+++ b/kmouth/phrasebook/phrasebook.cpp
@@ -0,0 +1,512 @@
+/***************************************************************************
+ phrasebook.cpp - description
+ -------------------
+ begin : Don Sep 19 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qprinter.h>
+#include <qpainter.h>
+#include <qfile.h>
+#include <qxml.h>
+#include <qregexp.h>
+#include <qptrstack.h>
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <ktoolbar.h>
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kglobalsettings.h>
+
+#include "phrasebookparser.h"
+#include "phrasebook.h"
+
+Phrase::Phrase() {
+ this->phrase = "";
+ this->shortcut = "";
+}
+
+Phrase::Phrase (const QString &phrase) {
+ this->phrase = phrase;
+ this->shortcut = "";
+}
+
+Phrase::Phrase (const QString &phrase, const QString &shortcut) {
+ this->phrase = phrase;
+ this->shortcut = shortcut;
+}
+
+QString Phrase::getPhrase() const {
+ return phrase;
+}
+
+QString Phrase::getShortcut() const {
+ return shortcut;
+}
+
+void Phrase::setPhrase (const QString &phrase) {
+ this->phrase = phrase;
+}
+
+void Phrase::setShortcut (const QString &shortcut) {
+ this->shortcut = shortcut;
+}
+
+// ***************************************************************************
+
+PhraseBookEntry::PhraseBookEntry () {
+ phrase = Phrase();
+ level = 1;
+ isPhraseValue = false;
+}
+
+PhraseBookEntry::PhraseBookEntry (Phrase phrase, int level, bool isPhrase) {
+ this->phrase = phrase;
+ this->level = level;
+ isPhraseValue = isPhrase;
+}
+
+bool PhraseBookEntry::isPhrase() const {
+ return isPhraseValue;
+}
+
+Phrase PhraseBookEntry::getPhrase() const {
+ return phrase;
+}
+
+int PhraseBookEntry::getLevel() const {
+ return level;
+}
+
+// ***************************************************************************
+
+void PhraseBook::print(KPrinter *pPrinter) {
+ QPainter printpainter;
+ printpainter.begin(pPrinter);
+
+ QRect size = printpainter.viewport ();
+ int x = size.x();
+ int y = size.y();
+ int w = size.width();
+ printpainter.setFont (QFont (KGlobalSettings::generalFont().family(), 12));
+ QFontMetrics metrics = printpainter.fontMetrics();
+
+ PhraseBookEntryList::iterator it;
+ for (it = begin(); it != end(); ++it) {
+ QRect rect = metrics.boundingRect (x+16*(*it).getLevel(), y,
+ w-16*(*it).getLevel(), 0,
+ Qt::AlignJustify | Qt::WordBreak,
+ (*it).getPhrase().getPhrase());
+
+ if (y+rect.height() > size.height()) {
+ pPrinter->newPage();
+ y = 0;
+ }
+ printpainter.drawText (x+16*(*it).getLevel(),y,
+ w-16*(*it).getLevel(),rect.height(),
+ Qt::AlignJustify | Qt::WordBreak,
+ (*it).getPhrase().getPhrase());
+ y += rect.height();
+ }
+
+ printpainter.end();
+}
+
+bool PhraseBook::decode (const QString &xml) {
+ QXmlInputSource source;
+ source.setData (xml);
+ return decode (source);
+}
+
+bool PhraseBook::decode (QXmlInputSource &source) {
+ PhraseBookParser parser;
+ QXmlSimpleReader reader;
+ reader.setFeature ("http://trolltech.com/xml/features/report-start-end-entity", true);
+ reader.setContentHandler (&parser);
+
+ if (reader.parse(source)) {
+ PhraseBookEntryList::clear();
+ *(PhraseBookEntryList *)this += parser.getPhraseList();
+ return true;
+ }
+ else
+ return false;
+}
+
+QCString encodeString (const QString str) {
+ QCString res = "";
+ for (int i = 0; i < (int)str.length(); i++) {
+ QChar ch = str.at(i);
+ ushort uc = ch.unicode();
+ QCString number; number.setNum(uc);
+ if ((uc>127) || (uc<32) || (ch=='<') || (ch=='>') || (ch=='&') || (ch==';'))
+ res = res + "&#" + number + ";";
+ else
+ res = res + (char)uc;
+ }
+ return res;
+}
+
+QString PhraseBook::encode () {
+ QString result;
+ result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ result += "<!DOCTYPE phrasebook>\n";
+ result += "<phrasebook>\n";
+
+ PhraseBookEntryList::iterator it;
+ int level = 0;
+ for (it = begin(); it != end(); ++it) {
+ int newLevel = (*it).getLevel();
+ while (level < newLevel) {
+ result += "<phrasebook>\n";
+ level++;
+ }
+ while (level > newLevel) {
+ result += "</phrasebook>\n";
+ level--;
+ }
+
+ if ((*it).isPhrase()) {
+ Phrase phrase = (*it).getPhrase();
+ result += "<phrase shortcut=\"" + encodeString(phrase.getShortcut());
+ result += "\">" + encodeString(phrase.getPhrase()) + "</phrase>\n";
+ }
+ else {
+ Phrase phrase = (*it).getPhrase();
+ result += "<phrasebook name=\"" + encodeString(phrase.getPhrase()) + "\">\n";
+ level++;
+ }
+ }
+ while (level > 0) {
+ result += "</phrasebook>\n";
+ level--;
+ }
+ result += "</phrasebook>";
+ return result;
+}
+
+QStringList PhraseBook::toStringList () {
+ QStringList result;
+
+ PhraseBook::iterator it;
+ for (it = begin(); it != end(); ++it) {
+ if ((*it).isPhrase())
+ result += (*it).getPhrase().getPhrase();
+ }
+ return result;
+}
+
+bool PhraseBook::save (const KURL &url) {
+ QRegExp pattern("*.phrasebook",true,true);
+ return save (url, pattern.exactMatch(url.filename()));
+}
+
+
+void PhraseBook::save (QTextStream &stream, bool asPhrasebook) {
+ if (asPhrasebook)
+ stream << encode();
+ else
+ stream << toStringList().join("\n");
+}
+
+bool PhraseBook::save (const KURL &url, bool asPhrasebook) {
+ if (url.isLocalFile()) {
+ QFile file(url.path());
+ if(!file.open(IO_WriteOnly))
+ return false;
+
+ QTextStream stream(&file);
+ save (stream, asPhrasebook);
+ file.close();
+
+ if (file.status() != IO_Ok)
+ return false;
+ else
+ return true;
+ }
+ else {
+ KTempFile tempFile;
+ tempFile.setAutoDelete(true);
+
+ save (*tempFile.textStream(), asPhrasebook);
+ tempFile.close();
+
+ return KIO::NetAccess::upload(tempFile.name(), url);
+ }
+}
+
+int PhraseBook::save (QWidget *parent, const QString &title, KURL &url, bool phrasebookFirst) {
+ // KFileDialog::getSaveURL(...) is not useful here as we need
+ // to know the requested file type.
+
+ QString filters;
+ if (phrasebookFirst)
+ filters = i18n("*.phrasebook|Phrase Books (*.phrasebook)\n*.txt|Plain Text Files (*.txt)\n*|All Files");
+ else
+ filters = i18n("*.txt|Plain Text Files (*.txt)\n*.phrasebook|Phrase Books (*.phrasebook)\n*|All Files");
+
+ KFileDialog fdlg(QString::null,filters, parent, "filedialog", true);
+ fdlg.setCaption(title);
+ fdlg.setOperationMode( KFileDialog::Saving );
+
+ if (fdlg.exec() != QDialog::Accepted) {
+ return 0;
+ }
+
+ url = fdlg.selectedURL();
+
+ if (url.isEmpty() || !url.isValid()) {
+ return -1;
+ }
+
+ if (KIO::NetAccess::exists(url)) {
+ if (KMessageBox::warningContinueCancel(0,QString("<qt>%1</qt>").arg(i18n("The file %1 already exists. "
+ "Do you want to overwrite it?").arg(url.url())),i18n("File Exists"),i18n("&Overwrite"))==KMessageBox::Cancel) {
+ return 0;
+ }
+ }
+
+ bool result;
+ if (fdlg.currentFilter() == "*.phrasebook") {
+ if (url.fileName (false).contains('.') == 0) {
+ url.setFileName (url.fileName(false) + ".phrasebook");
+ }
+ else if (url.fileName (false).right (11).contains (".phrasebook", false) == 0) {
+ int filetype = KMessageBox::questionYesNoCancel (0,QString("<qt>%1</qt>").arg(i18n("Your chosen filename <i>%1</i> has a different extension than <i>.phrasebook</i>. "
+ "Do you wish to add <i>.phrasebook</i> to the filename?").arg(url.filename())),i18n("File Extension"),i18n("Add"),i18n("Do Not Add"));
+ if (filetype == KMessageBox::Cancel) {
+ return 0;
+ }
+ if (filetype == KMessageBox::Yes) {
+ url.setFileName (url.fileName(false) + ".phrasebook");
+ }
+ }
+ result = save (url, true);
+ }
+ else if (fdlg.currentFilter() == "*.txt") {
+ if (url.fileName (false).right (11).contains (".phrasebook", false) == 0) {
+ result = save (url, false);
+ }
+ else {
+ int filetype = KMessageBox::questionYesNoCancel (0,QString("<qt>%1</qt>").arg(i18n("Your chosen filename <i>%1</i> has the extension <i>.phrasebook</i>. "
+ "Do you wish to save in phrasebook format?").arg(url.filename())),i18n("File Extension"),i18n("As Phrasebook"),i18n("As Plain Text"));
+ if (filetype == KMessageBox::Cancel) {
+ return 0;
+ }
+ if (filetype == KMessageBox::Yes) {
+ result = save (url, true);
+ }
+ else {
+ result = save (url, false);
+ }
+ }
+ }
+ else // file format "All files" requested, so decide by extension
+ result = save (url);
+
+ if (result)
+ return 1;
+ else
+ return -1;
+}
+
+bool PhraseBook::open (const KURL &url) {
+ QString tempFile;
+ KURL fileUrl = url;
+
+ QString protocol = fileUrl.protocol();
+ if (protocol.isEmpty() || protocol.isNull()) {
+ fileUrl.setProtocol ("file");
+ fileUrl.setPath (url.url());
+ }
+
+ if (KIO::NetAccess::download (fileUrl, tempFile)) {
+ QStringList list = QStringList();
+
+ // First: try to load it as a normal phrase book
+ QFile file(tempFile);
+ QXmlInputSource source (&file);
+ bool error = !decode (source);
+
+ // Second: if the file does not contain a phrase book, load it as
+ // a plain text file
+ if (error) {
+ // Load each line of the plain text file as a new phrase
+
+ QFile file(tempFile);
+ if (file.open(IO_ReadOnly)) {
+ QTextStream stream(&file);
+
+ while (!stream.atEnd()) {
+ QString s = stream.readLine();
+ if (!(s.isNull() || s.isEmpty()))
+ *this += PhraseBookEntry(Phrase(s, ""), 0, true);
+ }
+ file.close();
+ error = false;
+ }
+ else
+ error = true;
+ }
+ KIO::NetAccess::removeTempFile (tempFile);
+
+ return !error;
+ }
+ else
+ return false;
+}
+
+void PhraseBook::addToGUI (QPopupMenu *popup, KToolBar *toolbar, KActionCollection *phrases,
+ QObject *receiver, const char *slot) const {
+ if ((popup != 0) || (toolbar != 0)) {
+ QPtrStack<QWidget> stack;
+ QWidget *parent = popup;
+ int level = 0;
+
+ QValueListConstIterator<PhraseBookEntry> it;
+ for (it = begin(); it != end(); ++it) {
+ int newLevel = (*it).getLevel();
+ while (newLevel > level) {
+ KActionMenu *menu = new KActionMenu("", "phrasebook");
+ menu->setDelayed(false);
+ phrases->insert(menu);
+ menu->plug (parent);
+ if (parent == popup)
+ menu->plug (toolbar);
+ if (parent != 0)
+ stack.push (parent);
+ parent = menu->popupMenu();
+ level++;
+ }
+ while (newLevel < level && (parent != popup)) {
+ parent = stack.pop();
+ level--;
+ }
+ if ((*it).isPhrase()) {
+ Phrase phrase = (*it).getPhrase();
+ KAction *action = new PhraseAction (phrase.getPhrase(),
+ phrase.getShortcut(), receiver, slot, phrases);
+ if (parent == popup)
+ action->plug (toolbar);
+ if (parent != 0)
+ action->plug(parent);
+ }
+ else {
+ Phrase phrase = (*it).getPhrase();
+ KActionMenu *menu = new KActionMenu(phrase.getPhrase(), "phrasebook");
+ menu->setDelayed(false);
+ phrases->insert(menu);
+ if (parent == popup)
+ menu->plug (toolbar);
+ if (parent != 0)
+ menu->plug (parent);
+ stack.push (parent);
+ parent = menu->popupMenu();
+ level++;
+ }
+ }
+ }
+}
+
+void PhraseBook::insert (const QString &name, const PhraseBook &book) {
+ *this += PhraseBookEntry(Phrase(name), 0, false);
+
+ QValueListConstIterator<PhraseBookEntry> it;
+ for (it = book.begin(); it != book.end(); ++it) {
+ *this += PhraseBookEntry ((*it).getPhrase(), (*it).getLevel()+1, (*it).isPhrase());
+ }
+}
+
+// ***************************************************************************
+
+PhraseBookDrag::PhraseBookDrag (PhraseBook *book, QWidget *dragSource, const char *name)
+ : QDragObject (dragSource, name)
+{
+ setBook (book);
+}
+
+PhraseBookDrag::PhraseBookDrag (QWidget *dragSource, const char *name)
+ : QDragObject (dragSource, name)
+{
+ setBook (0);
+}
+
+PhraseBookDrag::~PhraseBookDrag () {
+}
+
+void PhraseBookDrag::setBook (PhraseBook *book) {
+ if (book == 0) {
+ isEmpty = true;
+ xmlphrasebook.setText(QString::null);
+ xml.setText(QString::null);
+ plain.setText(QString::null);
+ }
+ else {
+ isEmpty = false;
+ xmlphrasebook.setText(book->encode());
+ xml.setText(book->encode());
+ plain.setText(book->toStringList().join("\n"));
+ }
+ xmlphrasebook.setSubtype("x-xml-phrasebook");
+ xml.setSubtype("xml");
+ plain.setSubtype("plain");
+}
+
+const char *PhraseBookDrag::format (int i) const {
+ if (isEmpty)
+ return plain.format(i);
+ else if (i%3 == 0)
+ return plain.format(i/3);
+ else if (i%3 == 1)
+ return xml.format(i/3);
+ else
+ return xmlphrasebook.format(i/3);
+}
+
+QByteArray PhraseBookDrag::encodedData (const char* mime) const {
+ QCString m(mime);
+ m = m.lower();
+ if (m.contains("xml-phrasebook"))
+ return xmlphrasebook.encodedData(mime);
+ else if (m.contains("xml"))
+ return xml.encodedData(mime);
+ else
+ return plain.encodedData(mime);
+}
+
+bool PhraseBookDrag::canDecode (const QMimeSource* e) {
+ return QTextDrag::canDecode(e);
+}
+
+bool PhraseBookDrag::decode (const QMimeSource *e, PhraseBook *book) {
+ QString string;
+ QCString subtype1 = "x-xml-phrasebook";
+ QCString subtype2 = "xml";
+
+ if (!QTextDrag::decode(e, string, subtype1))
+ if (!QTextDrag::decode(e, string, subtype2)) {
+ if (QTextDrag::decode(e, string)) {
+ *book += PhraseBookEntry(Phrase(string, ""), 0, true);
+ return true;
+ }
+ else return false;
+ }
+
+ return book->decode(string);
+}
+
+#include "phrasebook.moc"
diff --git a/kmouth/phrasebook/phrasebook.h b/kmouth/phrasebook/phrasebook.h
new file mode 100644
index 0000000..83cb3a9
--- /dev/null
+++ b/kmouth/phrasebook/phrasebook.h
@@ -0,0 +1,195 @@
+/***************************************************************************
+ phrasebook.h - description
+ -------------------
+ begin : Don Sep 19 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHRASEBOOK_H
+#define PHRASEBOOK_H
+
+#include <qobject.h>
+#include <qdragobject.h>
+#include <qxml.h>
+
+#include <kaction.h>
+#include <kprinter.h>
+
+class KURL;
+
+/**
+ * The class Phrase represents one phrase in a phrase book.
+ * @author Gunnar Schmi Dt
+ */
+class Phrase {
+ friend class PhraseBookParser;
+public:
+ Phrase();
+ Phrase (const QString &phrase);
+ Phrase (const QString &phrase, const QString &shortcut);
+
+ QString getPhrase() const;
+ QString getShortcut() const;
+
+ void setPhrase (const QString &phrase);
+ void setShortcut (const QString &shortcut);
+
+private:
+ QString phrase;
+ QString shortcut;
+};
+
+/**
+ * The class PhraseBookEntry implements a phrase book entry. That can be either
+ * a phrase or a start tag a sub phrase book.
+ * @author Gunnar Schmi Dt
+ */
+class PhraseBookEntry {
+public:
+ PhraseBookEntry ();
+ PhraseBookEntry (Phrase phrase, int level = 1, bool isPhrase = true);
+ ~PhraseBookEntry () {};
+
+ void setPhrase (Phrase phrase, int level = 1, bool isPhrase = true);
+
+ bool isPhrase() const;
+ Phrase getPhrase() const;
+ int getLevel() const;
+
+private:
+ bool isPhraseValue;
+ Phrase phrase;
+ int level;
+};
+
+typedef QValueList<PhraseBookEntry> PhraseBookEntryList;
+
+/**
+ * The class PhraseBook implements a phrase book. It mainly stores a
+ * token list where each token is a phrase book entry (either a phrase
+ * or a sub phrase book). The entries are placed into a tree structure
+ * as follows:
+ *
+ * The level of each entry tells the level in the tree (level=0 is the top
+ * level), each sub book in level i directly or indirectly contains all
+ * following entries until an entry of level at most i or the end of the
+ * token list.
+ *
+ * @author Gunnar Schmi Dt
+ */
+class PhraseBook : public PhraseBookEntryList {
+public:
+ PhraseBook() : PhraseBookEntryList() {};
+ ~PhraseBook() {};
+
+ /** opens a file containing a phrase book. Returns true if successful. */
+ bool open (const KURL &url);
+
+ /** decodes a phrase book. Returns true if successful. */
+ bool decode (const QString &xml);
+
+ /** decodes a phrase book. Returns true if successful. */
+ bool decode (QXmlInputSource &source);
+
+ /** Writes the phrases to a file. Returns true if successful. */
+ bool save (const KURL &url);
+
+ /** Writes the phrases to a file. Returns true if successful. */
+ bool save (const KURL &url, bool asPhrasebook);
+
+ /** Writes the phrases to a QTextStream. */
+ void save (QTextStream &stream, bool asPhrasebook);
+
+ /** Prints the phrases. */
+ void print (KPrinter *pPrinter);
+
+ /** Shows a file selector and writes the phrases to a file.
+ * @return 1, if the file got successfully written,
+ * 0, if the user canceled the operation,
+ * -1, if there was an error when saving the file.
+ */
+ int save (QWidget *parent, const QString &title, KURL &url, bool phrasebookFirst = true);
+
+ /** encodes the phrase book. Returns the encoded xml code. */
+ QString encode ();
+
+ /** Stores all entries in a QStringList. All hierarchy information and all
+ * shortcuts are ignored during this operation.
+ */
+ QStringList toStringList();
+
+ /** Adds the entries of the book to both the given popup menu and the given
+ * toolbar. The corresponding actions will be inserted into phrases.
+ */
+ void addToGUI (QPopupMenu *popup, KToolBar *toolbar,
+ KActionCollection *phrases,
+ QObject *receiver, const char *slot) const;
+
+ /** Inserts book into a new sub phrase book.
+ * @param name the name of the new sub phrase book.
+ * @param book the phrase book to insert.
+ */
+ void insert (const QString &name, const PhraseBook &book);
+};
+
+/**
+ * The class PhraseBookDrag implements drag and drop support for phrase books.
+ * @author Gunnar Schmi Dt
+ */
+class PhraseBookDrag: public QDragObject {
+ Q_OBJECT
+public:
+ PhraseBookDrag (PhraseBook *book, QWidget *dragSource = 0, const char *name = 0);
+ PhraseBookDrag (QWidget *dragSource = 0, const char *name = 0);
+ ~PhraseBookDrag ();
+
+ virtual void setBook (PhraseBook *book);
+
+ const char *format (int i) const;
+ virtual QByteArray encodedData (const char *) const;
+
+ static bool canDecode (const QMimeSource *e);
+ static bool decode (const QMimeSource *e, PhraseBook *book);
+
+private:
+ bool isEmpty;
+ QTextDrag xmlphrasebook;
+ QTextDrag xml;
+ QTextDrag plain;
+};
+
+class PhraseAction : public KAction {
+ Q_OBJECT
+public:
+ PhraseAction (const QString& phrase, const QString& cut, const QObject* receiver, const char* slot, KActionCollection* parent)
+ : KAction (phrase, "phrase", KShortcut(cut), 0, 0, parent, phrase.latin1()) {
+ this->phrase = phrase;
+ connect (this, SIGNAL(slotActivated (const QString &)), receiver, slot);
+ };
+ ~PhraseAction () {
+ }
+
+public slots:
+ void slotActivated () {
+ KAction::slotActivated();
+ emit slotActivated (phrase);
+ }
+
+signals:
+ void slotActivated (const QString &phrase);
+
+private:
+ QString phrase;
+};
+
+#endif
diff --git a/kmouth/phrasebook/phrasebookdialog.cpp b/kmouth/phrasebook/phrasebookdialog.cpp
new file mode 100644
index 0000000..cc79d2f
--- /dev/null
+++ b/kmouth/phrasebook/phrasebookdialog.cpp
@@ -0,0 +1,758 @@
+/***************************************************************************
+ phrasebookdialog.cpp - description
+ -------------------
+ begin : Don Sep 19 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// include files for QT
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qclipboard.h>
+#include <qradiobutton.h>
+#include <qevent.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qgroupbox.h>
+#include <qpopupmenu.h>
+#include <qvaluestack.h>
+#include <qptrstack.h>
+#include <qwhatsthis.h>
+
+// include files for KDE
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <kguiitem.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <kstandarddirs.h>
+#include <kdesktopfile.h>
+
+#include "phrasebookdialog.h"
+#include "buttonboxui.h"
+#include "phrasetree.h"
+
+namespace PhraseBookPrivate {
+ enum columns {
+ name = 1,
+ filename = 2
+ };
+}
+
+CheckBookItem::CheckBookItem (QListViewItem *parent, QListViewItem *last,
+ const QString &text, const QString &name, const QString &filename)
+ : QCheckListItem (parent, text, QCheckListItem::CheckBox)
+{
+ moveItem (last);
+ setText(PhraseBookPrivate::name, name);
+ setText(PhraseBookPrivate::filename, filename);
+ setSelectable(false);
+
+ if (filename.isNull() || filename.isEmpty())
+ numberOfBooks = 0;
+ else
+ numberOfBooks = 1;
+ selectedBooks = 0;
+ ((CheckBookItem*)parent)->childChange (numberOfBooks, selectedBooks);
+}
+
+CheckBookItem::CheckBookItem (QListView *parent, QListViewItem *last,
+ const QString &text, const QString &name, const QString &filename)
+ : QCheckListItem (parent, text, QCheckListItem::CheckBox)
+{
+ moveItem (last);
+ setText(PhraseBookPrivate::name, name);
+ setText(PhraseBookPrivate::filename, filename);
+ setSelectable(false);
+
+ if (filename.isNull() || filename.isEmpty())
+ numberOfBooks = 0;
+ else
+ numberOfBooks = 1;
+ selectedBooks = 0;
+}
+
+CheckBookItem::~CheckBookItem () {
+}
+
+void CheckBookItem::activate() {
+ QListView *lv = listView();
+
+ if ((lv != 0) && (!lv->isEnabled()) || (!isEnabled()))
+ return;
+
+ setOn (!isOn());
+ ignoreDoubleClick();
+}
+
+void CheckBookItem::stateChange (bool on) {
+ QListViewItem *item = firstChild();
+ if (item == 0) {
+ QListViewItem *parent = this->parent();
+ if (parent != 0) {
+ if (on)
+ ((CheckBookItem*)parent)->childChange (0, 1);
+ else
+ ((CheckBookItem*)parent)->childChange (0, -1);
+ }
+ }
+ else propagateStateChange();
+}
+
+void CheckBookItem::propagateStateChange () {
+ QListViewItem *item = firstChild();
+ while (item != 0) {
+ if (isOn() != ((QCheckListItem*)item)->isOn())
+ ((QCheckListItem*)item)->setOn (isOn());
+ else
+ ((CheckBookItem*)item)->propagateStateChange ();
+ item = item->nextSibling();
+ }
+}
+
+void CheckBookItem::childChange (int numberDiff, int selDiff) {
+ numberOfBooks += numberDiff;
+ selectedBooks += selDiff;
+ QListViewItem *parent = this->parent();
+ if (parent != 0)
+ ((CheckBookItem*)parent)->childChange (numberDiff, selDiff);
+
+ QString text = i18n(" (%1 of %2 books selected)");
+ text = text.arg(selectedBooks).arg(numberOfBooks);
+ setText(0, this->text(PhraseBookPrivate::name)+text);
+}
+
+/***************************************************************************/
+
+InitialPhraseBookWidget::InitialPhraseBookWidget (QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ QVBoxLayout *mainLayout = new QVBoxLayout (this, 0, KDialog::spacingHint());
+ QLabel *label = new QLabel (i18n("Please decide which phrase books you need:"), this, "booksTitle");
+ mainLayout->add (label);
+
+ books = new KListView (this, "books");
+ books->setSorting (-1);
+ books->setItemsMovable (false);
+ books->setDragEnabled (false);
+ books->setAcceptDrops (false);
+ books->addColumn (i18n("Book"));
+ books->setRootIsDecorated (true);
+ books->setAllColumnsShowFocus (true);
+ books->setSelectionMode (QListView::Multi);
+ mainLayout->add (books);
+
+ initStandardPhraseBooks();
+}
+
+InitialPhraseBookWidget::~InitialPhraseBookWidget () {
+}
+
+void InitialPhraseBookWidget::initStandardPhraseBooks() {
+ StandardBookList bookPaths = PhraseBookDialog::standardPhraseBooks();
+
+ QListViewItem *parent = 0;
+ QListViewItem *last = 0;
+ QStringList currentNamePath = "";
+ QPtrStack<QListViewItem> stack;
+ StandardBookList::iterator it;
+ for (it = bookPaths.begin(); it != bookPaths.end(); ++it) {
+ QString namePath = (*it).path;
+ QStringList dirs = QStringList::split("/", namePath);
+
+ QStringList::iterator it1=currentNamePath.begin();
+ QStringList::iterator it2=dirs.begin();
+ for (; (it1 != currentNamePath.end())
+ && (it1 != dirs.end()) && (*it1 == *it2); ++it1, ++it2);
+ for (; it1 != currentNamePath.end(); ++it1) {
+ last = parent;
+ parent = stack.pop();
+ }
+ for (; it2 != dirs.end(); ++it2) {
+ stack.push (parent);
+ QListViewItem *newParent;
+ if (parent == 0)
+ newParent = new CheckBookItem (books, last, *it2, *it2, QString::null);
+ else
+ newParent = new CheckBookItem (parent, last, *it2, *it2, QString::null);
+ parent = newParent;
+ last = 0;
+ }
+ currentNamePath = dirs;
+
+ QListViewItem *book;
+ if (parent == 0)
+ book = new CheckBookItem (books, last, (*it).name, (*it).name, (*it).filename);
+ else
+ book = new CheckBookItem (parent, last, (*it).name, (*it).name, (*it).filename);
+ last = book;
+ }
+}
+
+void InitialPhraseBookWidget::createBook () {
+ PhraseBook book;
+ QListViewItem *item = books->firstChild();
+ while (item != 0) {
+ if (item->firstChild() != 0) {
+ item = item->firstChild();
+ }
+ else {
+ if (((QCheckListItem*)item)->isOn()) {
+ PhraseBook localBook;
+ localBook.open(KURL( item->text(PhraseBookPrivate::filename )));
+ book += localBook;
+ }
+
+ while ((item != 0) && (item->nextSibling() == 0)) {
+ item = item->parent();
+ }
+ if (item != 0)
+ item = item->nextSibling();
+ }
+ }
+
+ QString bookLocation = KApplication::kApplication()->dirs()->saveLocation ("appdata", "/");
+ if (!bookLocation.isNull() && !bookLocation.isEmpty()) {
+ book.save (KURL( bookLocation + "standard.phrasebook" ));
+ }
+}
+
+/***************************************************************************/
+
+ButtonBoxWidget::ButtonBoxWidget (QWidget *parent, const char *name)
+: ButtonBoxUI (parent, name) {
+ keyButtonPlaceLayout = new QGridLayout (keyButtonPlace, 1, 1, 0, 0, "keyButtonPlaceLayout");
+
+ keyButton = new KKeyButton (keyButtonPlace, "key");
+ keyButtonPlaceLayout->addWidget (keyButton, 1,1);
+ QWhatsThis::add (keyButton, i18n("By clicking on this button you can select the keyboard shortcut associated with the selected phrase."));
+
+ group = new QButtonGroup (phrasebox);
+ group->hide();
+ group->setExclusive (true);
+ group->insert (noKey);
+ group->insert (customKey);
+}
+
+ButtonBoxWidget::~ButtonBoxWidget () {
+}
+
+/***************************************************************************/
+
+namespace PhraseBookPrivate {
+ PhraseBookDialog *instance = 0;
+}
+
+PhraseBookDialog::PhraseBookDialog ()
+ : KMainWindow (0, "phraseEditDialog")
+{
+ setCaption (i18n("Phrase Book"));
+ initGUI();
+ initActions();
+ initStandardPhraseBooks();
+ QString standardBook = KApplication::kApplication()->dirs()->findResource("appdata", "standard.phrasebook");
+ if (!standardBook.isNull() && !standardBook.isEmpty()) {
+ PhraseBook book;
+ book.open(KURL( standardBook ));
+ treeView->clear();
+ treeView->addBook(0, 0, &book);
+ treeView->setCurrentItem(treeView->firstChild());
+ selectionChanged();
+ phrasebookChanged = false;
+ }
+ // i18n("Edit Phrase Book")
+}
+
+PhraseBookDialog *PhraseBookDialog::get() {
+ if (PhraseBookPrivate::instance == 0)
+ PhraseBookPrivate::instance = new PhraseBookDialog();
+ return PhraseBookPrivate::instance;
+}
+
+PhraseBookDialog::~PhraseBookDialog() {
+ PhraseBookPrivate::instance = 0;
+}
+
+void PhraseBookDialog::initGUI () {
+ QWidget *page = new QWidget( this );
+ setCentralWidget(page);
+ QVBoxLayout *mainLayout = new QVBoxLayout (page, 0);
+
+ treeView = new PhraseTree (page, "phrasetree");
+ treeView->setSorting (-1);
+ treeView->setItemsMovable (true);
+ treeView->setDragEnabled (true);
+ treeView->setAcceptDrops (true);
+ treeView->addColumn (i18n("Phrase"));
+ treeView->addColumn (i18n("Shortcut"));
+ treeView->setRootIsDecorated (true);
+ treeView->setAllColumnsShowFocus (true);
+ treeView->setSelectionMode (QListView::Extended);
+ QWhatsThis::add (treeView, i18n("This list contains the current phrase book in a tree structure. You can select and modify individual phrases and sub phrase books"));
+ connect (treeView, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
+ connect (treeView, SIGNAL(contextMenuRequested (QListViewItem *, const QPoint &, int)), this, SLOT(contextMenuRequested (QListViewItem *, const QPoint &, int)));
+ connect (treeView, SIGNAL(dropped (QDropEvent *, QListViewItem *, QListViewItem *)), this, SLOT(slotDropped (QDropEvent *, QListViewItem *, QListViewItem *)));
+ connect (treeView, SIGNAL(moved (QListViewItem *, QListViewItem *, QListViewItem *)), this, SLOT(slotMoved (QListViewItem *, QListViewItem *, QListViewItem *)));
+ mainLayout->addWidget (treeView);
+
+ buttonBox = new ButtonBoxWidget (page, "buttonbox");
+ connect (buttonBox->lineEdit, SIGNAL(textChanged(const QString &)), SLOT(slotTextChanged(const QString &)));
+ connect (buttonBox->noKey, SIGNAL(clicked()), SLOT(slotNoKey()));
+ connect (buttonBox->customKey, SIGNAL(clicked()), SLOT(slotCustomKey()));
+ connect (buttonBox->keyButton, SIGNAL(capturedShortcut(const KShortcut&)), SLOT(capturedShortcut(const KShortcut&)));
+ mainLayout->addWidget (buttonBox);
+
+ treeView->setFocus();
+ selectionChanged();
+}
+
+void PhraseBookDialog::initActions() {
+// The file menu
+ fileNewPhrase = new KAction (i18n("&New Phrase"), "phrase_new", 0, this, SLOT(slotAddPhrase()), actionCollection(),"file_new_phrase");
+ fileNewPhrase->setStatusText(i18n("Adds a new phrase"));
+ fileNewPhrase->setWhatsThis (i18n("Adds a new phrase"));
+
+ fileNewBook = new KAction (i18n("New Phrase &Book"), "phrasebook_new", 0, this, SLOT(slotAddPhrasebook()), actionCollection(),"file_new_book");
+ fileNewBook->setStatusText(i18n("Adds a new phrase book into which other books and phrases can be placed"));
+ fileNewBook->setWhatsThis (i18n("Adds a new phrase book into which other books and phrases can be placed"));
+
+ fileSave = KStdAction::save(this, SLOT(slotSave()), actionCollection());
+ fileSave->setStatusText(i18n("Saves the phrase book onto the hard disk"));
+ fileSave->setWhatsThis (i18n("Saves the phrase book onto the hard disk"));
+
+ fileImport = new KAction (i18n("&Import..."), "phrasebook_open", 0, this, SLOT(slotImportPhrasebook()), actionCollection(),"file_import");
+ fileImport->setStatusText(i18n("Imports a file and adds its contents to the phrase book"));
+ fileImport->setWhatsThis (i18n("Imports a file and adds its contents to the phrase book"));
+
+ toolbarImport = new KToolBarPopupAction (i18n("&Import..."), "phrasebook_open", 0, this, SLOT(slotImportPhrasebook()), actionCollection(),"toolbar_import");
+ toolbarImport->setStatusText(i18n("Imports a file and adds its contents to the phrase book"));
+ toolbarImport->setWhatsThis (i18n("Imports a file and adds its contents to the phrase book"));
+
+ fileImportStandardBook = new KActionMenu (i18n("I&mport Standard Phrase Book"), "phrasebook_open", actionCollection(),"file_import_standard_book");
+ fileImportStandardBook->setStatusText(i18n("Imports a standard phrase book and adds its contents to the phrase book"));
+ fileImportStandardBook->setWhatsThis (i18n("Imports a standard phrase book and adds its contents to the phrase book"));
+
+ fileExport = new KAction (i18n("&Export..."), "phrasebook_save", 0, this, SLOT(slotExportPhrasebook()), actionCollection(),"file_export");
+ fileExport->setStatusText(i18n("Exports the currently selected phrase(s) or phrase book(s) into a file"));
+ fileExport->setWhatsThis (i18n("Exports the currently selected phrase(s) or phrase book(s) into a file"));
+
+ filePrint = KStdAction::print(this, SLOT(slotPrint()), actionCollection());
+ filePrint->setStatusText(i18n("Prints the currently selected phrase(s) or phrase book(s)"));
+ filePrint->setWhatsThis (i18n("Prints the currently selected phrase(s) or phrase book(s)"));
+
+ fileClose = KStdAction::close(this, SLOT(close()), actionCollection());
+ fileClose->setStatusText(i18n("Closes the window"));
+ fileClose->setWhatsThis (i18n("Closes the window"));
+
+// The edit menu
+ editCut = KStdAction::cut(this, SLOT(slotCut()), actionCollection());
+ editCut->setStatusText(i18n("Cuts the currently selected entries from the phrase book and puts it to the clipboard"));
+ editCut->setWhatsThis (i18n("Cuts the currently selected entries from the phrase book and puts it to the clipboard"));
+
+ editCopy = KStdAction::copy(this, SLOT(slotCopy()), actionCollection());
+ editCopy->setStatusText(i18n("Copies the currently selected entry from the phrase book to the clipboard"));
+ editCopy->setWhatsThis (i18n("Copies the currently selected entry from the phrase book to the clipboard"));
+
+ editPaste = KStdAction::paste(this, SLOT(slotPaste()), actionCollection());
+ editPaste->setStatusText(i18n("Pastes the clipboard contents to actual position"));
+ editPaste->setWhatsThis (i18n("Pastes the clipboard contents to actual position"));
+
+ editDelete = new KAction (i18n("&Delete"), "editdelete", 0, this, SLOT(slotRemove()), actionCollection(),"edit_delete");
+ editDelete->setStatusText(i18n("Deletes the selected entries from the phrase book"));
+ editDelete->setWhatsThis (i18n("Deletes the selected entries from the phrase book"));
+
+ // use the absolute path to your kmouthui.rc file for testing purpose in createGUI();
+ createGUI("phrasebookdialogui.rc");
+}
+
+QString PhraseBookDialog::displayPath (QString filename) {
+ QFileInfo file(filename);
+ QString path = file.dirPath();
+ QString dispPath = "";
+ uint position = path.find("/kmouth/books/")+QString("/kmouth/books/").length();
+
+ while (path.length() > position) {
+ file.setFile(path);
+
+ KDesktopFile *dirDesc = new KDesktopFile(path+"/.directory", true, "data");
+ QString name = dirDesc->readName();
+ delete dirDesc;
+
+ if (name.isNull() || name.isEmpty())
+ dispPath += "/" + file.fileName ();
+ else
+ dispPath += "/" + name;
+
+ path = file.dirPath();
+ }
+ return dispPath;
+}
+
+StandardBookList PhraseBookDialog::standardPhraseBooks() {
+ QStringList bookPaths = KGlobal::instance()->dirs()->findAllResources (
+ "data", "kmouth/books/*.phrasebook", true, true);
+ QStringList bookNames;
+ QMap<QString,StandardBook> bookMap;
+ QStringList::iterator it;
+ for (it = bookPaths.begin(); it != bookPaths.end(); ++it) {
+ PhraseBook pbook;
+ if (pbook.open (KURL( *it ))) {
+ StandardBook book;
+ book.name = (*pbook.begin()).getPhrase().getPhrase();
+
+ book.path = displayPath(*it);
+ book.filename = *it;
+
+ bookNames += book.path + "/" + book.name;
+ bookMap [book.path + "/" + book.name] = book;
+ }
+ }
+
+ bookNames.sort();
+
+ StandardBookList result;
+ for (it = bookNames.begin(); it != bookNames.end(); ++it)
+ result += bookMap [*it];
+
+ return result;
+}
+
+void PhraseBookDialog::initStandardPhraseBooks () {
+ StandardBookList bookPaths = standardPhraseBooks();
+
+ KActionMenu *parent = fileImportStandardBook;
+ QStringList currentNamePath = "x";
+ QPtrStack<KActionMenu> stack;
+ StandardBookList::iterator it;
+ for (it = bookPaths.begin(); it != bookPaths.end(); ++it) {
+ KURL url;
+ url.setPath((*it).filename);
+
+ QString namePath = "x/"+(*it).path;
+ QStringList dirs = QStringList::split("/", namePath);
+
+ QStringList::iterator it1=currentNamePath.begin();
+ QStringList::iterator it2=dirs.begin();
+ for (; (it1 != currentNamePath.end())
+ && (it1 != dirs.end()) && (*it1 == *it2); ++it1, ++it2);
+ for (; it1 != currentNamePath.end(); ++it1)
+ parent = stack.pop();
+ for (; it2 != dirs.end(); ++it2) {
+ stack.push (parent);
+ KActionMenu *newParent = new KActionMenu (*it2);
+ parent->insert(newParent);
+ if (parent == fileImportStandardBook)
+ newParent->plug(toolbarImport->popupMenu());
+ parent = newParent;
+ }
+ currentNamePath = dirs;
+
+ KAction *book = new StandardPhraseBookInsertAction (
+ url, (*it).name, this, SLOT(slotImportPhrasebook (const KURL &)), actionCollection());
+ parent->insert(book);
+ if (parent == fileImportStandardBook)
+ book->plug(toolbarImport->popupMenu());
+ }
+}
+
+PhraseTreeItem *selectedItem (QListView *treeView) {
+ PhraseTreeItem *currentItem = (PhraseTreeItem *)treeView->currentItem();
+ if ((currentItem == 0) || (!currentItem->isSelected()))
+ return 0;
+
+ QListViewItemIterator it(treeView);
+ while (it.current()) {
+ QListViewItem *item = it.current();
+ if (item->isSelected() && (item != currentItem))
+ return 0;
+ ++it;
+ }
+ return currentItem;
+}
+
+void PhraseBookDialog::selectionChanged () {
+ bool modified = phrasebookChanged;
+ PhraseTreeItem *currentItem = selectedItem (treeView);
+ if (currentItem == 0) {
+ buttonBox->textLabel->setText (i18n("Text of the &phrase:"));
+ buttonBox->textLabel->setEnabled(false);
+ buttonBox->group->setEnabled(false);
+ buttonBox->lineEdit->setText("");
+ buttonBox->lineEdit->setEnabled(false);
+ buttonBox->shortcutLabel->setEnabled(false);
+ buttonBox->keyButton->setShortcut("", false);
+ buttonBox->keyButton->setEnabled(false);
+ buttonBox->noKey->setChecked (false);
+ buttonBox->noKey->setEnabled (false);
+ buttonBox->customKey->setChecked (false);
+ buttonBox->customKey->setEnabled (false);
+ }
+ else if (currentItem->isPhrase()) {
+ buttonBox->textLabel->setText (i18n("Text of the &phrase:"));
+ buttonBox->textLabel->setEnabled(true);
+ buttonBox->group->setEnabled(true);
+ buttonBox->lineEdit->setText(currentItem->text(0));
+ buttonBox->lineEdit->setEnabled(true);
+ buttonBox->shortcutLabel->setEnabled(true);
+ QString shortcut = currentItem->text(1);
+ buttonBox->keyButton->setShortcut(currentItem->cut(), false);
+ if (shortcut.isEmpty() || shortcut.isNull()) {
+ buttonBox->noKey->setChecked (true);
+ buttonBox->customKey->setChecked (false);
+ }
+ else {
+ buttonBox->noKey->setChecked (false);
+ buttonBox->customKey->setChecked (true);
+ }
+ buttonBox->keyButton->setEnabled(true);
+ buttonBox->noKey->setEnabled(true);
+ buttonBox->customKey->setEnabled(true);
+ }
+ else {
+ buttonBox->textLabel->setText (i18n("Name of the &phrase book:"));
+ buttonBox->textLabel->setEnabled(true);
+ buttonBox->group->setEnabled(true);
+ buttonBox->lineEdit->setText(currentItem->text(0));
+ buttonBox->lineEdit->setEnabled(true);
+ buttonBox->shortcutLabel->setEnabled(false);
+ buttonBox->keyButton->setShortcut("", false);
+ buttonBox->keyButton->setEnabled(false);
+ buttonBox->noKey->setChecked (false);
+ buttonBox->noKey->setEnabled (false);
+ buttonBox->customKey->setChecked (false);
+ buttonBox->customKey->setEnabled (false);
+ }
+ phrasebookChanged = modified;
+}
+
+bool PhraseBookDialog::queryClose() {
+ if (phrasebookChanged) {
+ int answer = KMessageBox::questionYesNoCancel (this,
+ i18n("<qt>There are unsaved changes.<br>Do you want to apply the changes before closing the \"phrase book\" window or discard the changes?</qt>"),
+ i18n("Closing \"Phrase Book\" Window"),
+ KStdGuiItem::apply(), KStdGuiItem::discard(), "AutomaticSave");
+ if (answer == KMessageBox::Yes) {
+ slotSave();
+ return true;
+ }
+ return (answer == KMessageBox::No);
+ }
+ return true;
+}
+
+void PhraseBookDialog::slotTextChanged (const QString &s) {
+ PhraseTreeItem *currentItem = selectedItem (treeView);
+ if (currentItem != 0)
+ currentItem->setText(0, s);
+ phrasebookChanged = true;
+}
+
+void PhraseBookDialog::slotNoKey() {
+ buttonBox->noKey->setChecked (true);
+ buttonBox->customKey->setChecked (false);
+
+ PhraseTreeItem *currentItem = selectedItem (treeView);
+ if (currentItem != 0) {
+ currentItem->setCut (KShortcut(QString::null));
+ buttonBox->keyButton->setShortcut(currentItem->cut(), false);
+ }
+ phrasebookChanged = true;
+}
+
+void PhraseBookDialog::slotCustomKey() {
+ buttonBox->keyButton->captureShortcut();
+}
+
+void PhraseBookDialog::capturedShortcut (const KShortcut& cut) {
+ if (cut.isNull()) {
+ slotNoKey();
+ }
+ else
+ setShortcut (cut);
+ phrasebookChanged = true;
+}
+
+void PhraseBookDialog::setShortcut( const KShortcut& cut ) {
+ // Check whether the shortcut is valid
+ for (uint i = 0; i < cut.count(); i++) {
+ const KKeySequence& seq = cut.seq(i);
+ const KKey& key = seq.key(0);
+
+ if (key.modFlags() == 0 && key.sym() < 0x3000
+ && QChar(key.sym()).isLetterOrNumber())
+ {
+ QString s = i18n("In order to use the '%1' key as a shortcut, "
+ "it must be combined with the "
+ "Win, Alt, Ctrl, and/or Shift keys.").arg(QChar(key.sym()));
+ KMessageBox::sorry( this, s, i18n("Invalid Shortcut Key") );
+ return;
+ }
+ }
+
+ PhraseTreeItem *currentItem = selectedItem (treeView);
+ // If key isn't already in use,
+ if (!treeView->isKeyPresent (cut, currentItem, true)) {
+ // Set new key code
+ currentItem->setCut (cut);
+ // Update display
+ buttonBox->noKey->setChecked (false);
+ buttonBox->customKey->setChecked (true);
+ buttonBox->keyButton->setShortcut(currentItem->cut(), false);
+ }
+}
+
+QListViewItem *PhraseBookDialog::addBook (QListViewItem *parent, QListViewItem *after, PhraseBook *book) {
+ QListViewItem *newItem = treeView->addBook(parent, after, book);
+ if (newItem != 0) {
+ treeView->clearSelection();
+ treeView->ensureItemVisible(newItem);
+ treeView->setCurrentItem (newItem);
+ treeView->setSelected (newItem, true);
+ phrasebookChanged = true;
+ }
+ return newItem;
+}
+
+QListViewItem *PhraseBookDialog::addBook (QListViewItem *item, PhraseBook *book) {
+ if (item == 0)
+ return addBook(0, 0, book);
+ else if (((PhraseTreeItem *)item)->isPhrase() || !item->isOpen())
+ if (item->parent() != 0)
+ return addBook(item->parent(), item, book);
+ else
+ return addBook(0, item, book);
+ else
+ return addBook(item, 0, book);
+}
+
+void PhraseBookDialog::contextMenuRequested(QListViewItem *, const QPoint &pos, int) {
+ QString name;
+ if (treeView->hasSelectedItems())
+ name = "phrasebook_popup_sel";
+ else
+ name = "phrasebook_popup_nosel";
+
+ QPopupMenu *popup = (QPopupMenu *)factory()->container(name,this);
+ if (popup != 0) {
+ popup->popup(pos, 0);
+ }
+}
+
+void PhraseBookDialog::slotRemove () {
+ if (treeView->hasSelectedItems() != 0)
+ treeView->deleteSelectedItems();
+ selectionChanged();
+ phrasebookChanged = true;
+}
+
+void PhraseBookDialog::slotCut () {
+ slotCopy();
+ slotRemove();
+}
+
+void PhraseBookDialog::slotCopy () {
+ PhraseBook book;
+ treeView->fillBook (&book, true);
+ QApplication::clipboard()->setData(new PhraseBookDrag(&book));
+}
+
+void PhraseBookDialog::slotPaste () {
+ PhraseBook book;
+ if (PhraseBookDrag::decode(QApplication::clipboard()->data(), &book)) {
+ addBook (treeView->currentItem(), &book);
+ }
+}
+
+void PhraseBookDialog::slotDropped (QDropEvent *e, QListViewItem *parent, QListViewItem *after) {
+ PhraseBook book;
+ if (PhraseBookDrag::decode(e, &book)) {
+ addBook(parent, after, &book);
+ }
+}
+
+void PhraseBookDialog::slotMoved (QListViewItem *item, QListViewItem *, QListViewItem *) {
+ treeView->ensureItemVisible(item);
+ treeView->setSelected (item, true);
+ phrasebookChanged = true;
+}
+
+void PhraseBookDialog::slotAddPhrasebook () {
+ PhraseBook book;
+ Phrase phrase(i18n("(New Phrase Book)"), "");
+ book += PhraseBookEntry(phrase, 0, false);
+
+ QListViewItem *item = addBook (treeView->currentItem(), &book);
+ item->setOpen (true);
+ buttonBox->lineEdit->selectAll();
+ buttonBox->lineEdit->setFocus();
+}
+
+void PhraseBookDialog::slotAddPhrase () {
+ PhraseBook book;
+ Phrase phrase(i18n("(New Phrase)"), "");
+ book += PhraseBookEntry(phrase, 0, true);
+
+ addBook (treeView->currentItem(), &book);
+ buttonBox->lineEdit->selectAll();
+ buttonBox->lineEdit->setFocus();
+}
+
+void PhraseBookDialog::slotSave () {
+ book.clear();
+ treeView->fillBook (&book, false);
+ emit phrasebookConfirmed (book);
+ phrasebookChanged = false;
+}
+
+void PhraseBookDialog::slotImportPhrasebook () {
+ KURL url=KFileDialog::getOpenURL(QString::null,
+ i18n("*.phrasebook|Phrase Books (*.phrasebook)\n*.txt|Plain Text Files (*.txt)\n*|All Files"), this, i18n("Import Phrasebook"));
+
+ slotImportPhrasebook (url);
+}
+
+void PhraseBookDialog::slotImportPhrasebook (const KURL &url) {
+ if(!url.isEmpty()) {
+ PhraseBook book;
+ if (book.open (url))
+ addBook(treeView->currentItem(), &book);
+ else
+ KMessageBox::sorry(this,i18n("There was an error loading file\n%1").arg( url.url() ));
+ }
+}
+
+void PhraseBookDialog::slotExportPhrasebook () {
+ PhraseBook book;
+ treeView->fillBook (&book, treeView->hasSelectedItems());
+
+ KURL url;
+ if (book.save (this, i18n("Export Phrase Book"), url) == -1)
+ KMessageBox::sorry(this,i18n("There was an error saving file\n%1").arg( url.url() ));
+}
+
+void PhraseBookDialog::slotPrint()
+{
+ KPrinter printer;
+ if (printer.setup(this)) {
+ PhraseBook book;
+ treeView->fillBook (&book, treeView->hasSelectedItems());
+
+ book.print(&printer);
+ }
+}
+
+#include "phrasebookdialog.moc"
diff --git a/kmouth/phrasebook/phrasebookdialog.h b/kmouth/phrasebook/phrasebookdialog.h
new file mode 100644
index 0000000..774387f
--- /dev/null
+++ b/kmouth/phrasebook/phrasebookdialog.h
@@ -0,0 +1,234 @@
+/***************************************************************************
+ phrasebookdialog.h - description
+ -------------------
+ begin : Don Sep 19 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHRASEBOOKDIALOG_H
+#define PHRASEBOOKDIALOG_H
+
+#include <qbutton.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qlabel.h>
+#include <qlistview.h>
+#include <kmainwindow.h>
+#include <klineedit.h>
+#include <kkeybutton.h>
+#include <kurl.h>
+#include "phrasebook.h"
+#include "buttonboxui.h"
+
+class QListViewItem;
+class PhraseTreeItem;
+class PhraseTree;
+class QStringList;
+class QString;
+class KListView;
+
+struct StandardBook {
+ QString name;
+ QString path;
+ QString filename;
+};
+typedef QValueList<StandardBook> StandardBookList;
+
+/**The class PhraseTreeItem is an ListViewItem for either a phrase or a phrase book.
+ *@author Gunnar Schmi Dt
+ */
+
+class CheckBookItem : public QCheckListItem {
+public:
+ CheckBookItem (QListViewItem *parent, QListViewItem *last,
+ const QString &text, const QString &name, const QString &filename);
+ CheckBookItem (QListView *parent, QListViewItem *last,
+ const QString &text, const QString &name, const QString &filename);
+ ~CheckBookItem();
+
+protected:
+ virtual void activate ();
+ virtual void stateChange (bool);
+ virtual void propagateStateChange ();
+ virtual void childChange (int numberDiff, int selDiff);
+
+private:
+ int numberOfBooks;
+ int selectedBooks;
+};
+
+/**
+ * This class represents a widget for configuring the initial phrasebook.
+ * @author Gunnar Schmi Dt
+ */
+
+class InitialPhraseBookWidget : public QWidget {
+ Q_OBJECT
+public:
+ InitialPhraseBookWidget(QWidget *parent, const char *name);
+ ~InitialPhraseBookWidget();
+
+ void createBook();
+
+private:
+ /** initializes the list of standard phrase books */
+ void initStandardPhraseBooks ();
+
+ KListView *books;
+};
+
+/**
+ * The class StandardPhraseBookInsertAction implements an Action for
+ * inserting a standard phrase book.
+ * @author Gunnar Schmi Dt
+ */
+class StandardPhraseBookInsertAction : public KAction {
+ Q_OBJECT
+public:
+ StandardPhraseBookInsertAction (const KURL &url, const QString& name, const QObject* receiver, const char* slot, KActionCollection* parent)
+ : KAction (name, "phrasebook", 0, 0, 0, parent, 0) {
+ this->url = url;
+ connect (this, SIGNAL(slotActivated (const KURL &)), receiver, slot);
+ };
+ ~StandardPhraseBookInsertAction () {
+ };
+
+public slots:
+ void slotActivated () {
+ KAction::slotActivated();
+ emit slotActivated (url);
+ };
+
+signals:
+ void slotActivated (const KURL &url);
+
+private:
+ KURL url;
+};
+
+/**
+ * This class represents a widget holding the buttons of the phrase book
+ * edit window.
+ * @author Gunnar Schmi Dt
+ */
+class ButtonBoxWidget : public ButtonBoxUI {
+public:
+ ButtonBoxWidget (QWidget *parent = 0, const char *name = 0);
+ ~ButtonBoxWidget ();
+
+ KKeyButton *keyButton;
+ QButtonGroup *group;
+
+protected:
+ QGridLayout *keyButtonPlaceLayout;
+};
+
+/**
+ * The class PhraseBookDialog implements a dialog for editing phrase books.
+ * @author Gunnar Schmi Dt
+ */
+
+class PhraseBookDialog : public KMainWindow {
+ friend class InitialPhraseBookWidget;
+ Q_OBJECT
+private:
+ /** Constructor. It is private because this class implements the singleton
+ * pattern. For creating the instance of the dialog, use the get() method.
+ */
+ PhraseBookDialog ();
+
+ static QString displayPath (QString path);
+
+public:
+ /** Returns a pointer to the instance of this dialog. As a part off the
+ * singleton pattern it will make sure that there is at most one instance
+ * of the dialog at a given time.
+ */
+ static PhraseBookDialog *get();
+
+ /** Destructor. */
+ ~PhraseBookDialog();
+
+ bool queryClose ();
+
+public slots:
+ void slotTextChanged (const QString &s);
+ void slotNoKey();
+ void slotCustomKey();
+ void capturedShortcut (const KShortcut& cut);
+
+ void selectionChanged ();
+ void contextMenuRequested(QListViewItem *, const QPoint &pos, int);
+
+ void slotRemove ();
+ void slotCut ();
+ void slotCopy ();
+ void slotPaste ();
+
+ void slotAddPhrasebook ();
+ void slotAddPhrase ();
+
+ void slotSave ();
+ void slotImportPhrasebook ();
+ void slotImportPhrasebook (const KURL &url);
+ void slotExportPhrasebook ();
+ void slotPrint ();
+
+ void slotDropped (QDropEvent *e, QListViewItem *parent, QListViewItem *after);
+ void slotMoved (QListViewItem *item, QListViewItem *, QListViewItem *);
+
+signals:
+ void phrasebookConfirmed (PhraseBook &book);
+
+private:
+ static StandardBookList standardPhraseBooks ();
+
+ void initGUI();
+ /** initializes the KActions of the window */
+ void initActions();
+ /** initializes the list of standard phrase books */
+ void initStandardPhraseBooks ();
+
+ QListViewItem *addBook (QListViewItem *parent, QListViewItem *after, PhraseBook *book);
+ QListViewItem *addBook (QListViewItem *item, PhraseBook *book);
+
+ void setShortcut (const KShortcut &cut);
+
+ void _warning (const KKeySequence &cut, QString sAction, QString sTitle);
+
+ bool isGlobalKeyPresent (const KShortcut& cut, bool warnUser);
+ bool isPhraseKeyPresent (const KShortcut& cut, bool warnUser);
+ bool isKeyPresent (const KShortcut& cut, bool warnUser);
+
+ PhraseBook book;
+ bool phrasebookChanged;
+
+ PhraseTree *treeView;
+ ButtonBoxWidget *buttonBox;
+
+ KAction* fileNewPhrase;
+ KAction* fileNewBook;
+ KAction* fileSave;
+ KAction* fileImport;
+ KToolBarPopupAction* toolbarImport;
+ KActionMenu* fileImportStandardBook;
+ KAction* fileExport;
+ KAction* filePrint;
+ KAction* fileClose;
+ KAction* editCut;
+ KAction* editCopy;
+ KAction* editPaste;
+ KAction* editDelete;
+};
+
+#endif
diff --git a/kmouth/phrasebook/phrasebookdialogui.rc b/kmouth/phrasebook/phrasebookdialogui.rc
new file mode 100644
index 0000000..c5150fe
--- /dev/null
+++ b/kmouth/phrasebook/phrasebookdialogui.rc
@@ -0,0 +1,64 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="kmouth" version="1">
+
+<MenuBar>
+ <Menu name="file" noMerge="1"><text>&amp;File</text>
+ <Action name="file_new_phrase"/>
+ <Action name="file_new_book"/>
+ <Separator />
+ <Action name="file_save"/>
+ <Separator />
+ <Action name="file_import"/>
+ <Action name="file_import_standard_book"/>
+ <Action name="file_export"/>
+ <Separator />
+ <Action name="file_print"/>
+ <Separator />
+ <Action name="file_close"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="edit_delete"/>
+ </Menu>
+</MenuBar>
+
+<Menu name="phrasebook_popup_nosel" noMerge="1">
+ <Action name="file_new_phrase"/>
+ <Action name="file_new_book"/>
+ <Separator />
+ <Action name="file_import"/>
+ <Action name="file_import_standard_book"/>
+ <Action name="file_export"/>
+ <Separator />
+ <Action name="edit_paste"/>
+</Menu>
+
+<Menu name="phrasebook_popup_sel" noMerge="1">
+ <Action name="file_new_phrase"/>
+ <Action name="file_new_book"/>
+ <Separator />
+ <Action name="file_import"/>
+ <Action name="file_import_standard_book"/>
+ <Action name="file_export"/>
+ <Separator />
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator />
+ <Action name="edit_delete"/>
+</Menu>
+
+<ToolBar name="mainToolBar" noMerge="1">
+ <Action name="file_new_phrase"/>
+ <Action name="file_new_book"/>
+ <Action name="file_save"/>
+ <Action name="toolbar_import"/>
+ <Action name="file_export"/>
+ <Action name="file_print"/>
+ <Separator />
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_delete"/>
+</ToolBar>
+
+</kpartgui>
diff --git a/kmouth/phrasebook/phrasebookparser.cpp b/kmouth/phrasebook/phrasebookparser.cpp
new file mode 100644
index 0000000..9883e49
--- /dev/null
+++ b/kmouth/phrasebook/phrasebookparser.cpp
@@ -0,0 +1,112 @@
+/***************************************************************************
+ phrasebookparser.cpp - description
+ -------------------
+ begin : Don Sep 12 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "phrasebookparser.h"
+
+PhraseBookParser::PhraseBookParser() {
+}
+
+PhraseBookParser::~PhraseBookParser() {
+}
+
+bool PhraseBookParser::warning (const QXmlParseException &) {
+ return false;
+}
+
+bool PhraseBookParser::error (const QXmlParseException &) {
+ return false;
+}
+
+bool PhraseBookParser::fatalError (const QXmlParseException &) {
+ return false;
+}
+
+QString PhraseBookParser::errorString() {
+ return "";
+}
+
+bool PhraseBookParser::startDocument() {
+ list.clear ();
+ isInPhrase = false;
+ level = 0;
+ offset = 0;
+ starting = true;
+ return true;
+}
+
+bool PhraseBookParser::startElement (const QString &, const QString &,
+ const QString &name,
+ const QXmlAttributes &attributes)
+{
+ if (name == "phrase") {
+ if (isInPhrase)
+ return false;
+
+ phrase.phrase = "";
+ phrase.shortcut = attributes.value("shortcut");
+ isInPhrase = true;
+ }
+ else if (name == "phrasebook") {
+ if (isInPhrase)
+ return false;
+
+ phrase.phrase = attributes.value("name");
+ phrase.shortcut = "";
+ if ((phrase.phrase.isNull() || phrase.phrase.isEmpty()) && starting)
+ offset = -1;
+ else {
+ list += PhraseBookEntry (phrase, level, false);
+ level++;
+ }
+ starting = false;
+ }
+ return true;
+}
+
+bool PhraseBookParser::characters (const QString &ch) {
+ phrase.phrase += ch;
+ return true;
+}
+
+bool PhraseBookParser::ignorableWhitespace (const QString &ch) {
+ phrase.phrase += ch;
+ return true;
+}
+
+bool PhraseBookParser::endElement (const QString &, const QString &,
+ const QString &name)
+{
+ if (name == "phrase") {
+ list += PhraseBookEntry (phrase, level, true);
+ isInPhrase = false;
+ }
+ else if (name == "phrasebook") {
+ if (level == offset)
+ return false;
+
+ level--;
+ }
+ return true;
+}
+
+bool PhraseBookParser::endDocument() {
+ return (level == offset);
+}
+
+PhraseBookEntryList PhraseBookParser::getPhraseList() {
+ return list;
+}
diff --git a/kmouth/phrasebook/phrasebookparser.h b/kmouth/phrasebook/phrasebookparser.h
new file mode 100644
index 0000000..a6e436a
--- /dev/null
+++ b/kmouth/phrasebook/phrasebookparser.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ phrasebookparser.h - description
+ -------------------
+ begin : Don Sep 12 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHRASEBOOKPARSER_H
+#define PHRASEBOOKPARSER_H
+
+#include <qxml.h>
+#include <qvaluestack.h>
+#include "phrasebook.h"
+
+/**
+ * This class implements a parser for both the phrase list and for phrase
+ * books. It is intended to be used together with the Qt SAX2 framework.
+ * @author Gunnar Schmi Dt
+ */
+
+class PhraseBookParser : public QXmlDefaultHandler {
+public:
+ PhraseBookParser();
+ ~PhraseBookParser();
+
+ bool warning (const QXmlParseException &exception);
+ bool error (const QXmlParseException &exception);
+ bool fatalError (const QXmlParseException &exception);
+ QString errorString();
+
+ /** Processes the start of the document. */
+ bool startDocument();
+
+ /** Processes the start tag of an element. */
+ bool startElement (const QString &, const QString &, const QString &name,
+ const QXmlAttributes &attributes);
+
+ /** Processes a chunk of normal character data. */
+ bool characters (const QString &ch);
+
+ /** Processes whitespace. */
+ bool ignorableWhitespace (const QString &ch);
+
+ /** Processes the end tag of an element. */
+ bool endElement (const QString &, const QString &, const QString &name);
+
+ /** Processes the end of the document. */
+ bool endDocument();
+
+ /** returns a list of phrase book entries */
+ PhraseBookEntryList getPhraseList();
+
+private:
+ bool isInPhrase;
+ bool starting;
+ int offset;
+ Phrase phrase;
+
+ PhraseBookEntryList list;
+ int level;
+};
+
+#endif
diff --git a/kmouth/phrasebook/phrasetree.cpp b/kmouth/phrasebook/phrasetree.cpp
new file mode 100644
index 0000000..57d4f5e
--- /dev/null
+++ b/kmouth/phrasebook/phrasetree.cpp
@@ -0,0 +1,556 @@
+/***************************************************************************
+ phrasetree.cpp - description
+ -------------------
+ begin : Don Okt 24 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kaction.h>
+#include <kstdaccel.h>
+#include <kshortcutlist.h>
+#include <kactionshortcutlist.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+#include "phrasetree.h"
+#include "phrasebookdialog.h"
+#include "phrasebook.h"
+
+PhraseTreeItem::PhraseTreeItem (QListView *parent, QListViewItem *after, QString phrase, KShortcut shortcut, QPixmap icon)
+ : KListViewItem (parent, after, phrase)
+{
+ isPhraseValue = true;
+ cutValue = shortcut;
+ setText(1, cutValue.toString());
+ setPixmap(0, icon);
+ setExpandable (false);
+}
+
+PhraseTreeItem::PhraseTreeItem (QListViewItem *parent, QListViewItem *after, QString phrase, KShortcut shortcut, QPixmap icon)
+ : KListViewItem (parent, after, phrase)
+{
+ isPhraseValue = true;
+ cutValue = shortcut;
+ setText(1, cutValue.toString());
+ setPixmap(0, icon);
+ setExpandable (false);
+}
+PhraseTreeItem::PhraseTreeItem (QListView *parent, QListViewItem *after, QString name, QPixmap icon)
+ : KListViewItem (parent, after, name)
+{
+ isPhraseValue = false;
+ setPixmap(0, icon);
+ setExpandable (true);
+}
+PhraseTreeItem::PhraseTreeItem (QListViewItem *parent, QListViewItem *after, QString name, QPixmap icon)
+ : KListViewItem (parent, after, name)
+{
+ isPhraseValue = false;
+ setPixmap(0, icon);
+ setExpandable (true);
+}
+bool PhraseTreeItem::isPhrase () {
+ return isPhraseValue;
+}
+KShortcut PhraseTreeItem::cut () {
+ return cutValue;
+}
+void PhraseTreeItem::setCut (KShortcut cut) {
+ cutValue = cut;
+ setText(1, cut.toString());
+}
+
+// ***************************************************************************
+
+PhraseTree::PhraseTree (QWidget *parent, const char *name)
+ : KListView (parent, name)
+{
+ phrasebook_open = KGlobal::iconLoader()->loadIcon("phrasebook", KIcon::Small);
+ phrasebook_closed = KGlobal::iconLoader()->loadIcon("phrasebook_closed", KIcon::Small);
+ phrase = KGlobal::iconLoader()->loadIcon("phrase", KIcon::Small);
+
+ connect (this, SIGNAL(expanded (QListViewItem *)), this, SLOT(itemExpanded (QListViewItem *)));
+ connect (this, SIGNAL(collapsed (QListViewItem *)), this, SLOT(itemCollapsed (QListViewItem *)));
+}
+
+PhraseTree::~PhraseTree (){
+}
+
+namespace PhraseTreePrivate {
+ QListViewItem *prevSibling (QListViewItem *item) {
+ QListViewItem *parent = item->parent();
+ QListViewItem *above = item->itemAbove();
+
+ if (above == parent)
+ return 0;
+
+ while (above->parent() != parent)
+ above = above->parent();
+
+ return above;
+ }
+
+ bool findAbovePosition (QListViewItem *item,
+ QListViewItem **newParent,
+ QListViewItem **newAbove)
+ {
+ if (item == 0)
+ return false;
+
+ QListViewItem *parent = item->parent();
+ QListViewItem *above = item->itemAbove();
+
+ if (above == 0)
+ return false;
+ else if (above == parent) {
+ *newParent = parent->parent();
+ *newAbove = prevSibling (parent);
+ return true;
+ }
+ else if (above->parent() == parent) {
+ *newParent = parent;
+ *newAbove = prevSibling (above);
+ return true;
+ }
+ else {
+ while (above->parent()->parent() != parent)
+ above = above->parent();
+ *newParent = above->parent();
+ *newAbove = above;
+ return true;
+ }
+ }
+
+ bool findBelowPosition (QListViewItem *item,
+ QListViewItem **newParent,
+ QListViewItem **newAbove)
+ {
+ if (item == 0)
+ return false;
+
+ QListViewItem *parent = item->parent();
+ QListViewItem *below = item->nextSibling();
+
+ if (parent == 0 && below == 0)
+ return false;
+ else if (parent != 0 && below == 0) {
+ *newParent = parent->parent();
+ *newAbove = parent;
+ return true;
+ }
+ else if (below->isOpen()) {
+ *newParent = below;
+ *newAbove = 0;
+ return true;
+ }
+ else {
+ *newParent = parent;
+ *newAbove = below;
+ return true;
+ }
+ }
+
+ bool findRightPosition (QListViewItem *item,
+ QListViewItem **newParent,
+ QListViewItem **newAbove)
+ {
+ if (item == 0)
+ return false;
+
+ QListViewItem *above = prevSibling (item);
+
+ if (above == 0)
+ return false;
+ else if (((PhraseTreeItem *)above)->isPhrase())
+ return false;
+ else {
+ above->setOpen(true);
+ *newParent = above;
+ *newAbove = 0;
+ above = (*newParent)->firstChild();
+ while (above != 0) {
+ *newAbove = above;
+ above = above->nextSibling();
+ }
+ return true;
+ }
+ }
+
+ bool findLeftPosition (QListViewItem *item,
+ QListViewItem **newParent,
+ QListViewItem **newAbove)
+ {
+ if (item == 0)
+ return false;
+
+ QListViewItem *parent = item->parent();
+
+ if (parent == 0)
+ return false;
+ else {
+ *newParent = parent->parent();
+ *newAbove = parent;
+ return true;
+ }
+ }
+}
+
+void PhraseTree::moveItem (QListViewItem *item,
+ QListViewItem *parent,
+ QListViewItem *above)
+{
+ if (item != 0) {
+ if (item->parent() == 0)
+ takeItem (item);
+ else
+ item->parent()->takeItem (item);
+
+ if (parent == 0)
+ insertItem (item);
+ else
+ parent->insertItem (item);
+
+ item->moveItem(above);
+ }
+}
+
+bool PhraseTree::hasSelectedItems() {
+ QListViewItem *i = firstChild();
+ if ( !i )
+ return false;
+ int level = 0;
+ do {
+ if (i->isSelected())
+ return true;
+
+ if (i->firstChild() != 0) {
+ i = i->firstChild();
+ level++;
+ }
+ else {
+ while ((i != 0) && (i->nextSibling() == 0)) {
+ i = i->parent();
+ level--;
+ }
+ if (i != 0)
+ i = i->nextSibling();
+ }
+ }
+ while (i != 0);
+
+ return false;
+}
+
+void PhraseTree::deleteSelectedItems() {
+ QListViewItem *i = firstChild();
+ if ( !i )
+ return;
+ QListViewItem *deleteItem = 0;
+ do {
+ if (i->isSelected())
+ deleteItem = i;
+
+ if ((i->firstChild() != 0) && (!i->isSelected())) {
+ i = i->firstChild();
+ }
+ else {
+ while ((i != 0) && (i->nextSibling() == 0)) {
+ i = i->parent();
+ }
+ if (i != 0)
+ i = i->nextSibling();
+ }
+ if (deleteItem != 0) {
+ delete deleteItem;
+ deleteItem = 0;
+ }
+ }
+ while (i != 0);
+}
+
+void PhraseTree::keyPressEvent (QKeyEvent *e) {
+ if ((e->state() & Qt::KeyButtonMask) == Qt::AltButton) {
+ if (e->key() == Qt::Key_Up) {
+ QListViewItem *item = currentItem();
+ if ((item != 0) && (item->isSelected())) {
+ QListViewItem *parent;
+ QListViewItem *above;
+
+ if (PhraseTreePrivate::findAbovePosition (item, &parent, &above)) {
+ moveItem(item, parent, above);
+ setCurrentItem (item);
+ item->setSelected(true);
+ }
+ }
+ e->accept();
+ return;
+ }
+ else if (e->key() == Qt::Key_Down) {
+ QListViewItem *item = currentItem();
+ if ((item != 0) && (item->isSelected())) {
+ QListViewItem *parent;
+ QListViewItem *above;
+
+ if (PhraseTreePrivate::findBelowPosition (item, &parent, &above)) {
+ moveItem(item, parent, above);
+ setCurrentItem (item);
+ item->setSelected(true);
+ }
+ }
+ e->accept();
+ return;
+ }
+ else if (e->key() == Qt::Key_Left) {
+ QListViewItem *item = currentItem();
+ if ((item != 0) && (item->isSelected())) {
+ QListViewItem *parent;
+ QListViewItem *above;
+
+ if (PhraseTreePrivate::findLeftPosition (item, &parent, &above)) {
+ moveItem(item, parent, above);
+ setCurrentItem (item);
+ item->setSelected(true);
+ }
+ }
+ e->accept();
+ return;
+ }
+ else if (e->key() == Qt::Key_Right) {
+ QListViewItem *item = currentItem();
+ if ((item != 0) && (item->isSelected())) {
+ QListViewItem *parent;
+ QListViewItem *above;
+
+ if (PhraseTreePrivate::findRightPosition (item, &parent, &above)) {
+ moveItem(item, parent, above);
+ setCurrentItem (item);
+ item->setSelected(true);
+ }
+ }
+ e->accept();
+ return;
+ }
+ }
+ KListView::keyPressEvent(e);
+}
+
+PhraseTreeItem *PhraseTree::insertPhrase (QListViewItem *parent, QListViewItem *after, QString phrase, QString shortcut) {
+ KShortcut cut = KShortcut(shortcut);
+ if (isKeyPresent (cut, 0, false))
+ cut = KShortcut(QString::null);
+
+ if (parent == 0)
+ return new PhraseTreeItem (this, after, phrase, cut, this->phrase);
+ else
+ return new PhraseTreeItem (parent, after, phrase, cut, this->phrase);
+}
+
+PhraseTreeItem *PhraseTree::insertBook (QListViewItem *parent, QListViewItem *after, QString name) {
+ if (parent == 0)
+ return new PhraseTreeItem (this, after, name, phrasebook_closed);
+ else
+ return new PhraseTreeItem (parent, after, name, phrasebook_closed);
+}
+
+QListViewItem *PhraseTree::addBook (QListViewItem *parent, QListViewItem *after, PhraseBook *book) {
+ QListViewItem *last = after;
+ int level = 0;
+ PhraseBookEntryList::iterator it;
+ for (it = book->begin(); it != book->end(); ++it) {
+ int newLevel = (*it).getLevel();
+ while (level < newLevel) {
+ parent = insertBook(parent, last, "");
+ last = 0;
+ level++;
+ }
+ while (level > newLevel) {
+ last = parent;
+ if (parent != 0)
+ parent = parent->parent();
+ level--;
+ }
+
+ if ((*it).isPhrase()) {
+ Phrase phrase = (*it).getPhrase();
+ last = insertPhrase (parent, last, phrase.getPhrase(), phrase.getShortcut());
+ }
+ else {
+ Phrase phrase = (*it).getPhrase();
+ parent = insertBook(parent, last, phrase.getPhrase());
+ last = 0;
+ level++;
+ }
+ }
+ while (level > 0) {
+ last = parent;
+ if (parent != 0)
+ parent = parent->parent();
+ level--;
+ }
+ return last;
+}
+
+void PhraseTree::fillBook (PhraseBook *book, bool respectSelection) {
+ QListViewItem *i = firstChild();
+ int level = 0;
+ if ( !i )
+ return;
+ do {
+ if (i->isSelected() || !respectSelection || level > 0) {
+ PhraseTreeItem *it = (PhraseTreeItem *)i;
+ Phrase phrase(it->text(0), it->cut().toStringInternal());
+ *book += PhraseBookEntry(phrase, level, it->isPhrase());
+ }
+
+ if (i->firstChild() != 0) {
+ if (i->isSelected() || !respectSelection || level > 0)
+ level++;
+ i = i->firstChild();
+ }
+ else {
+ while ((i != 0) && (i->nextSibling() == 0)) {
+ i = i->parent();
+ if (level > 0)
+ level--;
+ }
+ if (i != 0)
+ i = i->nextSibling();
+ }
+ }
+ while (i != 0);
+}
+
+QDragObject *PhraseTree::dragObject () {
+ return dragObject (true);
+}
+
+QDragObject *PhraseTree::dragObject (bool isDependent) {
+ PhraseBook book;
+ fillBook (&book, true);
+ if (isDependent)
+ return new PhraseBookDrag(&book, viewport());
+ return new PhraseBookDrag(&book);
+}
+
+bool PhraseTree::acceptDrag (QDropEvent* event) const {
+ if (KListView::acceptDrag (event))
+ return true;
+ else
+ return PhraseBookDrag::canDecode(event);
+}
+
+// Returns iSeq index if cut2 has a sequence of equal or higher priority
+// to a sequence in cut, else -1
+static int keyConflict (const KShortcut& cut, const KShortcut& cut2) {
+ for (uint iSeq = 0; iSeq < cut.count(); iSeq++) {
+ for (uint iSeq2 = 0; iSeq2 <= iSeq && iSeq2 < cut2.count(); iSeq2++) {
+ if (cut.seq(iSeq) == cut2.seq(iSeq2))
+ return iSeq;
+ }
+ }
+ return -1;
+}
+
+void PhraseTree::_warning (const KKeySequence& cut, QString sAction, QString sTitle) {
+ sAction = sAction.stripWhiteSpace();
+
+ QString s =
+ i18n("The '%1' key combination has already been allocated "
+ "to %2.\n"
+ "Please choose a unique key combination.").
+ arg(cut.toString()).arg(sAction);
+
+ KMessageBox::sorry( this, s, sTitle );
+}
+
+bool PhraseTree::isStdAccelPresent (const KShortcut& cut, bool warnUser) {
+ for (uint iSeq = 0; iSeq < cut.count(); iSeq++) {
+ const KKeySequence& seq = cut.seq(iSeq);
+
+ KStdAccel::StdAccel id = KStdAccel::findStdAccel( seq );
+ if( id != KStdAccel::AccelNone
+ && keyConflict (cut, KStdAccel::shortcut(id)) > -1)
+ {
+ if (warnUser)
+ _warning (cut.seq(iSeq),
+ i18n("the standard \"%1\" action").arg(KStdAccel::label(id)),
+ i18n("Conflict with Standard Application Shortcut"));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PhraseTree::isGlobalKeyPresent (const KShortcut& cut, bool warnUser) {
+ QMap<QString, QString> mapEntry = KGlobal::config()->entryMap ("Global Shortcuts");
+ QMap<QString, QString>::Iterator it;
+ for (it = mapEntry.begin(); it != mapEntry.end(); ++it) {
+ int iSeq = keyConflict (cut, KShortcut(*it));
+ if (iSeq > -1) {
+ if (warnUser)
+ _warning (cut.seq(iSeq),
+ i18n("the global \"%1\" action").arg(it.key()),
+ i18n("Conflict with Global Shortcuts"));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PhraseTree::isPhraseKeyPresent (const KShortcut& cut, PhraseTreeItem* cutItem, bool warnUser) {
+ for (QListViewItemIterator it(this); it.current(); ++it) {
+ PhraseTreeItem* item = dynamic_cast<PhraseTreeItem*>(it.current());
+ if ((item != 0) && (item != cutItem)) {
+ int iSeq = keyConflict (cut, item->cut());
+ if (iSeq > -1) {
+ if (warnUser)
+ _warning (cut.seq(iSeq),
+ i18n("an other phrase"),
+ i18n("Key Conflict"));
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool PhraseTree::isKeyPresent (const KShortcut& cut, PhraseTreeItem* cutItem, bool warnUser) {
+ if (isStdAccelPresent (cut, warnUser))
+ return true;
+
+ if (isGlobalKeyPresent (cut, warnUser))
+ return true;
+
+ if (isPhraseKeyPresent (cut, cutItem, warnUser))
+ return true;
+
+ return false;
+}
+
+void PhraseTree::itemExpanded (QListViewItem *item) {
+ PhraseTreeItem *i = (PhraseTreeItem *)item;
+ if (!i->isPhrase())
+ i->setPixmap(0, phrasebook_open);
+}
+
+void PhraseTree::itemCollapsed (QListViewItem *item) {
+ PhraseTreeItem *i = (PhraseTreeItem *)item;
+ if (!i->isPhrase())
+ i->setPixmap(0, phrasebook_closed);
+}
+
+// ***************************************************************************
+
+#include "phrasetree.moc"
diff --git a/kmouth/phrasebook/phrasetree.h b/kmouth/phrasebook/phrasetree.h
new file mode 100644
index 0000000..bd0e1f5
--- /dev/null
+++ b/kmouth/phrasebook/phrasetree.h
@@ -0,0 +1,108 @@
+/***************************************************************************
+ phrasetree.h - description
+ -------------------
+ begin : Don Okt 24 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHRASETREE_H
+#define PHRASETREE_H
+
+#include <qpixmap.h>
+#include <kshortcut.h>
+#include <klistview.h>
+
+class PhraseBook;
+class PhraseShortcutRequest;
+
+/**The class PhraseTreeItem is an ListViewItem for either a phrase or a phrase book.
+ *@author Gunnar Schmi Dt
+ */
+
+class PhraseTreeItem : public KListViewItem {
+ friend class PhraseTree;
+private:
+ /** Creates a phrase item within a sub phrase book */
+ PhraseTreeItem (QListView *parent, QListViewItem *after, QString phrase, KShortcut shortcut, QPixmap icon);
+ /** Creates a phrase item at the top level */
+ PhraseTreeItem (QListViewItem *parent, QListViewItem *after, QString phrase, KShortcut shortcut, QPixmap icon);
+ /** Creates a phrase book item within a sub phrase book */
+ PhraseTreeItem (QListView *parent, QListViewItem *after, QString name, QPixmap icon);
+ /** Creates a phrase book item at the top level */
+ PhraseTreeItem (QListViewItem *parent, QListViewItem *after, QString name, QPixmap icon);
+
+public:
+ bool isPhrase();
+ KShortcut cut();
+ void setCut(KShortcut cut);
+
+private:
+ bool isPhraseValue;
+ KShortcut cutValue;
+};
+
+/**
+ * The class PhraseTree represents the ListView of the phrase book edit
+ * dialog. It extends KListView for providing better drag-and-drop support.
+ * @author Gunnar Schmi Dt
+ */
+
+class PhraseTree : public KListView {
+ friend class PhraseTreeItem;
+ Q_OBJECT
+public:
+ PhraseTree (QWidget *parent = 0, const char *name = 0);
+ ~PhraseTree ();
+
+ void keyPressEvent (QKeyEvent *e);
+
+ PhraseTreeItem *insertPhrase (QListViewItem *parent, QListViewItem *after, QString phrase, QString shortcut);
+ PhraseTreeItem *insertBook (QListViewItem *parent, QListViewItem *after, QString name);
+
+ QListViewItem *addBook (QListViewItem *parent, QListViewItem *after, PhraseBook *book);
+ void fillBook (PhraseBook *book, bool respectSelection);
+
+ QDragObject *dragObject ();
+ QDragObject *dragObject (bool isDependent);
+
+ void moveItem (QListViewItem *item, QListViewItem *parent, QListViewItem *above);
+
+ bool hasSelectedItems();
+ void deleteSelectedItems();
+
+protected:
+ bool acceptDrag (QDropEvent* event) const;
+
+private:
+ void _warning (const KKeySequence& cut, QString sAction, QString sTitle);
+ bool isStdAccelPresent (const KShortcut& cut, bool warnUser);
+ bool isGlobalKeyPresent (const KShortcut& cut, bool warnUser);
+ bool isApplicationKeyPresent (const KShortcut& cut, bool warnUser);
+ bool isPhraseKeyPresent (const KShortcut& cut, PhraseTreeItem* cutItem, bool warnUser);
+public:
+ bool isKeyPresent (const KShortcut& cut, PhraseTreeItem* cutItem, bool warnUser);
+
+public slots:
+ void itemExpanded (QListViewItem *item);
+ void itemCollapsed (QListViewItem *item);
+
+signals:
+ void shortcutRequest (PhraseShortcutRequest *request);
+
+private:
+ QPixmap phrasebook_open;
+ QPixmap phrasebook_closed;
+ QPixmap phrase;
+};
+
+#endif
diff --git a/kmouth/phraseedit.cpp b/kmouth/phraseedit.cpp
new file mode 100644
index 0000000..0f2e319
--- /dev/null
+++ b/kmouth/phraseedit.cpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ phraseedit.cpp - description
+ -------------------
+ begin : Don Sep 26 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "phraseedit.h"
+
+PhraseEdit::PhraseEdit(const QString &string, QWidget *parent)
+ : KLineEdit (string, parent) {
+}
+
+PhraseEdit::~PhraseEdit() {
+}
+
+void PhraseEdit::keyPressEvent (QKeyEvent *e) {
+ if ((e->state() & Qt::KeyButtonMask) == Qt::ControlButton) {
+ if (e->key() == Qt::Key_C) {
+ if (!this->hasSelectedText()) {
+ e->ignore();
+ return;
+ }
+ }
+ else if (e->key() == Qt::Key_Insert) {
+ if (!hasSelectedText()) {
+ e->ignore();
+ return;
+ }
+ }
+ else if (e->key() == Qt::Key_X) {
+ if (!hasSelectedText()) {
+ e->ignore();
+ return;
+ }
+ }
+ }
+ else if ((e->state() & Qt::KeyButtonMask) == Qt::ShiftButton) {
+ if (e->key() == Qt::Key_Delete) {
+ if (!hasSelectedText()) {
+ e->ignore();
+ return;
+ }
+ }
+ }
+ KLineEdit::keyPressEvent(e);
+}
diff --git a/kmouth/phraseedit.h b/kmouth/phraseedit.h
new file mode 100644
index 0000000..a7a065e
--- /dev/null
+++ b/kmouth/phraseedit.h
@@ -0,0 +1,36 @@
+/***************************************************************************
+ phraseedit.h - description
+ -------------------
+ begin : Don Sep 26 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHRASEEDIT_H
+#define PHRASEEDIT_H
+
+#include <klineedit.h>
+
+/**
+ * This class extends a KLineEdit by consuming fewer unused key presses.
+ *@author Gunnar Schmi Dt
+ */
+
+class PhraseEdit : public KLineEdit {
+public:
+ PhraseEdit(const QString &string, QWidget *parent);
+ virtual ~PhraseEdit();
+
+ void keyPressEvent (QKeyEvent *e);
+};
+
+#endif
diff --git a/kmouth/phraselist.cpp b/kmouth/phraselist.cpp
new file mode 100644
index 0000000..d57682a
--- /dev/null
+++ b/kmouth/phraselist.cpp
@@ -0,0 +1,478 @@
+/***************************************************************************
+ phraselist.cpp - description
+ -------------------
+ begin : Mit Sep 11 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// include files for Qt
+#include <qprinter.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qpopupmenu.h>
+#include <qclipboard.h>
+
+// include files for KDE
+#include <klistbox.h>
+#include <klineedit.h>
+#include <kaudioplayer.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kcombobox.h>
+#include <kmessagebox.h>
+
+#include <stdlib.h>
+
+// application specific includes
+#include "phraselistitem.h"
+#include "phraselist.h"
+#include "phraseedit.h"
+#include "kmouth.h"
+#include "texttospeechsystem.h"
+#include "phrasebook/phrasebook.h"
+#include "wordcompletion/wordcompletion.h"
+
+PhraseList::PhraseList(QWidget *parent, const char *name) : QWidget(parent,name) {
+ isInSlot = false;
+ setBackgroundMode(PaletteBase);
+ QVBoxLayout *layout = new QVBoxLayout (this);
+
+ listBox = new KListBox (this);
+ listBox->setFocusPolicy(QWidget::NoFocus);
+ listBox->setSelectionMode (QListBox::Extended);
+ QWhatsThis::add (listBox, i18n("This list contains the history of spoken sentences. You can select sentences and press the speak button for re-speaking."));
+ layout->addWidget(listBox);
+
+ QHBoxLayout *rowLayout = new QHBoxLayout ();
+ layout->addLayout(rowLayout);
+
+ completion = new WordCompletion();
+
+ dictionaryCombo = new KComboBox (this, "Dictionary Combo");
+ configureCompletionCombo(completion->wordLists());
+ rowLayout->addWidget(dictionaryCombo);
+
+ lineEdit = new PhraseEdit ("", this);
+ lineEdit->setFocusPolicy(QWidget::StrongFocus);
+ lineEdit->setFrame(true);
+ lineEdit->setEchoMode(QLineEdit::Normal);
+ lineEdit->setCompletionObject (completion);
+ lineEdit->setAutoDeleteCompletionObject(true);
+ QWhatsThis::add (lineEdit, i18n("Into this edit field you can type a phrase. Click on the speak button in order to speak the entered phrase."));
+ rowLayout->addWidget(lineEdit);
+ lineEdit->setFocus();
+
+ QIconSet icon = KGlobal::iconLoader()->loadIconSet("speak", KIcon::Small);
+ speakButton = new QPushButton (icon, i18n("&Speak"), this);
+ speakButton->setFocusPolicy(QWidget::NoFocus);
+ speakButton->setAutoDefault(false);
+ QWhatsThis::add (speakButton, i18n("Speaks the currently active sentence(s). If there is some text in the edit field it is spoken. Otherwise the selected sentences in the history (if any) are spoken."));
+ rowLayout->addWidget(speakButton);
+
+ connect(dictionaryCombo, SIGNAL (activated (const QString &)), completion, SLOT (setWordList(const QString &)));
+ connect(completion, SIGNAL (wordListsChanged (const QStringList &)), this, SLOT (configureCompletionCombo (const QStringList &)));
+ connect(listBox, SIGNAL(selectionChanged()), SLOT(selectionChanged()));
+ connect(listBox, SIGNAL(contextMenuRequested (QListBoxItem *, const QPoint &)), SLOT(contextMenuRequested (QListBoxItem *, const QPoint &)));
+ connect(lineEdit, SIGNAL(returnPressed(const QString &)), SLOT(lineEntered(const QString &)));
+ connect(lineEdit, SIGNAL(textChanged (const QString &)), SLOT(textChanged(const QString &)));
+ connect(speakButton, SIGNAL( clicked ()), SLOT(speak()));
+}
+
+PhraseList::~PhraseList() {
+ delete speakButton;
+ delete listBox;
+ delete lineEdit;
+}
+
+void PhraseList::print(KPrinter *pPrinter) {
+ PhraseBook book;
+ for (QListBoxItem *item = listBox->firstItem(); item != 0; item = item->next()) {
+ book += PhraseBookEntry(Phrase(item->text()));
+ }
+
+ book.print (pPrinter);
+}
+
+QStringList PhraseList::getListSelection() {
+ QStringList res = QStringList();
+
+ for (QListBoxItem *item = listBox->firstItem(); item != 0; item = item->next()) {
+ if (item->isSelected())
+ res += item->text();
+ }
+
+ return res;
+}
+
+bool PhraseList::existListSelection() {
+ for (QListBoxItem *item = listBox->firstItem(); item != 0; item = item->next()) {
+ if (item->isSelected())
+ return true;
+ }
+
+ return false;
+}
+
+bool PhraseList::existEditSelection() {
+ return lineEdit->hasSelectedText();
+}
+
+void PhraseList::enableMenuEntries() {
+ bool deselected = false;
+ bool selected = false;
+ for (QListBoxItem *item = listBox->firstItem(); item != 0; item = item->next()) {
+ if (item->isSelected())
+ selected = true;
+ else
+ deselected = true;
+ }
+ KMouthApp *theApp=(KMouthApp *) parentWidget();
+ theApp->enableMenuEntries (selected, deselected);
+}
+
+void PhraseList::configureCompletion() {
+ completion->configure();
+}
+
+void PhraseList::configureCompletionCombo(const QStringList &list) {
+ QString current = completion->currentWordList();
+ dictionaryCombo->clear();
+ if (list.isEmpty())
+ dictionaryCombo->hide();
+ else if (list.count() == 1) {
+ dictionaryCombo->insertStringList (list);
+ dictionaryCombo->setCurrentItem (0);
+ dictionaryCombo->hide();
+ }
+ else {
+ dictionaryCombo->insertStringList (list);
+ dictionaryCombo->show();
+
+ QStringList::ConstIterator it;
+ int i = 0;
+ for (it = list.begin(), i = 0; it != list.end(); ++it, ++i) {
+ if (current == *it) {
+ dictionaryCombo->setCurrentItem (i);
+ return;
+ }
+ }
+ }
+}
+
+void PhraseList::saveCompletionOptions(KConfig *config) {
+ config->setGroup("General Options");
+ config->writeEntry("Show speak button", speakButton->isVisible() || !lineEdit->isVisible());
+
+ config->setGroup("Completion");
+ config->writeEntry("Mode", static_cast<int>(lineEdit->completionMode()));
+ config->writeEntry("List", completion->currentWordList());
+}
+
+void PhraseList::readCompletionOptions(KConfig *config) {
+ config->setGroup("General Options");
+ if (!config->readBoolEntry("Show speak button", true))
+ speakButton->hide();
+
+ if (config->hasGroup ("Completion")) {
+ config->setGroup("Completion");
+ int mode = config->readNumEntry ("Mode", KGlobalSettings::completionMode());
+ lineEdit->setCompletionMode (static_cast<KGlobalSettings::Completion>(mode));
+
+ QString current = config->readEntry ("List", QString::null);
+ QStringList list = completion->wordLists();
+ QStringList::ConstIterator it;
+ int i = 0;
+ for (it = list.begin(), i = 0; it != list.end(); ++it, ++i) {
+ if (current == *it) {
+ dictionaryCombo->setCurrentItem (i);
+ return;
+ }
+ }
+ }
+}
+
+void PhraseList::saveWordCompletion () {
+ completion->save();
+}
+
+
+void PhraseList::selectAllEntries () {
+ listBox->selectAll (true);
+}
+
+void PhraseList::deselectAllEntries () {
+ listBox->selectAll (false);
+}
+
+void PhraseList::speak () {
+ QString phrase = lineEdit->text();
+ if (phrase.isNull() || phrase.isEmpty())
+ speakListSelection();
+ else {
+ insertIntoPhraseList (phrase, true);
+ speakPhrase (phrase);
+ }
+}
+
+void PhraseList::cut() {
+ if (lineEdit->hasSelectedText())
+ lineEdit->cut();
+ else
+ cutListSelection();
+}
+
+void PhraseList::copy() {
+ if (lineEdit->hasSelectedText())
+ lineEdit->copy();
+ else
+ copyListSelection();
+}
+
+void PhraseList::paste() {
+ lineEdit->paste();
+}
+
+void PhraseList::insert (const QString &s) {
+ setEditLineText(s);
+}
+
+void PhraseList::speakListSelection () {
+ speakPhrase(getListSelection().join ("\n"));
+}
+
+void PhraseList::removeListSelection () {
+ QListBoxItem *next;
+ for (QListBoxItem *item = listBox->firstItem(); item != 0; item = next) {
+ next = item->next();
+
+ if (item->isSelected()) {
+ listBox->removeItem(listBox->index(item));
+ }
+ }
+ enableMenuEntries ();
+}
+
+void PhraseList::cutListSelection () {
+ copyListSelection ();
+ removeListSelection ();
+}
+
+void PhraseList::copyListSelection () {
+ QApplication::clipboard()->setText (getListSelection().join ("\n"));
+}
+
+void PhraseList::lineEntered (const QString &phrase) {
+ if (phrase.isNull() || phrase.isEmpty())
+ speakListSelection();
+ else {
+ insertIntoPhraseList (phrase, true);
+ speakPhrase (phrase);
+ }
+}
+
+void PhraseList::speakPhrase (const QString &phrase) {
+ QApplication::setOverrideCursor (KCursor::WaitCursor, false);
+ KMouthApp *theApp=(KMouthApp *) parentWidget();
+ QString language = completion->languageOfWordList (completion->currentWordList());
+ theApp->getTTSSystem()->speak(phrase, language);
+ QApplication::restoreOverrideCursor ();
+}
+
+void PhraseList::insertIntoPhraseList (const QString &phrase, bool clearEditLine) {
+ int lastLine = listBox->count() - 1;
+ if ((lastLine == -1) || (phrase != listBox->text(lastLine))) {
+ listBox->insertItem(new PhraseListItem(phrase));
+ if (clearEditLine)
+ completion->addSentence (phrase);
+ }
+
+ if (clearEditLine) {
+ lineEdit->selectAll();
+ line = "";
+ }
+ enableMenuEntries ();
+}
+
+void PhraseList::contextMenuRequested (QListBoxItem *, const QPoint &pos) {
+ QString name;
+ if (existListSelection())
+ name = "phraselist_selection_popup";
+ else
+ name = "phraselist_popup";
+
+ KMouthApp *theApp=(KMouthApp *) parentWidget();
+ KXMLGUIFactory *factory = theApp->factory();
+ QPopupMenu *popup = (QPopupMenu *)factory->container(name,theApp);
+ if (popup != 0) {
+ popup->popup(pos, 0);
+ }
+}
+
+void PhraseList::textChanged (const QString &s) {
+ if (!isInSlot) {
+ isInSlot = true;
+ line = s;
+ listBox->setCurrentItem (listBox->count() - 1);
+ listBox->clearSelection ();
+ isInSlot = false;
+ }
+}
+
+void PhraseList::selectionChanged () {
+ if (!isInSlot) {
+ isInSlot = true;
+
+ QStringList sel = getListSelection();
+
+ if (sel.empty())
+ setEditLineText(line);
+ else if (sel.count() == 1)
+ setEditLineText(sel.first());
+ else {
+ setEditLineText("");
+ }
+ isInSlot = false;
+ }
+ enableMenuEntries ();
+}
+
+void PhraseList::setEditLineText(const QString &s) {
+ lineEdit->end(false);
+ while (!(lineEdit->text().isNull() || lineEdit->text().isEmpty()))
+ lineEdit->backspace();
+ lineEdit->insert(s);
+}
+
+void PhraseList::keyPressEvent (QKeyEvent *e) {
+ if (e->key() == Qt::Key_Up) {
+ bool selected = false;
+ for (QListBoxItem *item = listBox->firstItem(); item != 0; item = item->next()) {
+ if (item->isSelected()) {
+ selected = true;
+ }
+ }
+
+ if (!selected) {
+ listBox->setCurrentItem (listBox->count() - 1);
+ listBox->setSelected (listBox->count() - 1, true);
+ listBox->ensureCurrentVisible ();
+ }
+ else {
+ int curr = listBox->currentItem();
+
+ if (curr == -1) {
+ isInSlot = true;
+ listBox->clearSelection();
+ isInSlot = false;
+ curr = listBox->count() - 1;
+ listBox->setCurrentItem (curr);
+ listBox->setSelected (curr, true);
+ listBox->ensureCurrentVisible ();
+ }
+ else if (curr != 0) {
+ isInSlot = true;
+ listBox->clearSelection();
+ isInSlot = false;
+ listBox->setCurrentItem (curr - 1);
+ listBox->setSelected (curr - 1, true);
+ listBox->ensureCurrentVisible ();
+ }
+ }
+
+ e->accept();
+ }
+ else if (e->key() == Qt::Key_Down) {
+ bool selected = false;
+ for (QListBoxItem *item = listBox->firstItem(); item != 0; item = item->next()) {
+ if (item->isSelected()) {
+ selected = true;
+ }
+ }
+
+ if (selected) {
+ int curr = listBox->currentItem();
+
+ if (curr == (int)listBox->count() - 1) {
+ listBox->clearSelection();
+ }
+ else if (curr != -1) {
+ isInSlot = true;
+ listBox->clearSelection();
+ isInSlot = false;
+ listBox->setCurrentItem (curr + 1);
+ listBox->setSelected (curr + 1, true);
+ listBox->ensureCurrentVisible ();
+ }
+ }
+ e->accept();
+ }
+ else if ((e->state() & Qt::KeyButtonMask) == Qt::ControlButton) {
+ if (e->key() == Qt::Key_C) {
+ copy();
+ e->accept();
+ }
+ else if (e->key() == Qt::Key_X) {
+ cut();
+ e->accept();
+ }
+ }
+ else
+ e->ignore();
+}
+
+void PhraseList::save () {
+ // We want to save a history of spoken sentences here. However, as
+ // the class PhraseBook does already provide a method for saving
+ // phrase books in both the phrase book format and plain text file
+ // format we use that method here.
+
+ PhraseBook book;
+ for (QListBoxItem *item = listBox->firstItem(); item != 0; item = item->next()) {
+ book += PhraseBookEntry(Phrase(item->text()));
+ }
+
+ KURL url;
+ if (book.save (this, i18n("Save As"), url, false) == -1)
+ KMessageBox::sorry(this,i18n("There was an error saving file\n%1").arg( url.url() ));
+}
+
+void PhraseList::open () {
+ KURL url=KFileDialog::getOpenURL(QString::null,
+ i18n("*|All Files\n*.phrasebook|Phrase Books (*.phrasebook)\n*.txt|Plain Text Files (*.txt)"), this, i18n("Open File as History"));
+
+ if(!url.isEmpty())
+ open (url);
+}
+
+void PhraseList::open (KURL url) {
+ // We want to open a history of spoken sentences here. However, as
+ // the class PhraseBook does already provide a method for opening
+ // both phrase books and plain text files we use that method here.
+
+ PhraseBook book;
+ if (book.open (url)) {
+ // convert PhraseBookEntryList -> QStringList
+ QStringList list = book.toStringList();
+ listBox->clear();
+ QStringList::iterator it;
+ for (it = list.begin(); it != list.end(); ++it)
+ insertIntoPhraseList (*it, false);
+ }
+ else
+ KMessageBox::sorry(this,i18n("There was an error loading file\n%1").arg( url.url() ));
+}
+
+#include "phraselist.moc"
diff --git a/kmouth/phraselist.h b/kmouth/phraselist.h
new file mode 100644
index 0000000..7f56306
--- /dev/null
+++ b/kmouth/phraselist.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+ phraselist.h - description
+ -------------------
+ begin : Mon Aug 26 15:41:23 CEST 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHRASELIST_H
+#define PHRASELIST_H
+
+// include files for KDE
+#include <klistbox.h>
+#include <klineedit.h>
+#include <kprinter.h>
+
+// include files for Qt
+#include <qwidget.h>
+#include <qpushbutton.h>
+
+class WordCompletion;
+
+/**
+ * This class represents a phrase list. It contains methods for manipulating
+ * the phraselist and also methods for viewing the list.
+ * The phrase list consists of an edit field for entering phrases and a list
+ * box for the spoken phrases.
+ *
+ * @author Gunnar Schmi Dt
+ */
+
+class PhraseList : public QWidget {
+ Q_OBJECT
+public:
+ PhraseList(QWidget *parent=0, const char *name=0);
+ ~PhraseList();
+
+ /** contains the implementation for printing functionality */
+ void print(KPrinter *pPrinter);
+
+ QStringList getListSelection();
+
+ bool existListSelection();
+ bool existEditSelection();
+
+public slots:
+ /** Called whenever the user wants the contents of the edit line to be spoken. */
+ void speak ();
+
+ void cut();
+ void copy();
+ void paste();
+
+ /** Insert s into the edit field. */
+ void insert (const QString &s);
+
+ /** Called whenever the user wants the selected list entries to be spoken. */
+ void speakListSelection ();
+
+ void removeListSelection ();
+ void cutListSelection ();
+ void copyListSelection ();
+
+ void save ();
+ void open ();
+ void open (KURL url);
+
+ void selectAllEntries ();
+ void deselectAllEntries ();
+
+ void configureCompletion();
+ void saveWordCompletion();
+ void saveCompletionOptions(KConfig *config);
+ void readCompletionOptions(KConfig *config);
+
+protected slots:
+ void lineEntered (const QString &phrase);
+ void contextMenuRequested (QListBoxItem *, const QPoint &pos);
+ void textChanged (const QString &s);
+ void selectionChanged ();
+ void keyPressEvent (QKeyEvent *e);
+ void configureCompletionCombo(const QStringList &list);
+
+private:
+ KListBox *listBox;
+ KComboBox *dictionaryCombo;
+ KLineEdit *lineEdit;
+ QPushButton *speakButton;
+ QString line;
+ WordCompletion *completion;
+
+ bool isInSlot;
+
+ void speakPhrase (const QString &phrase);
+ void setEditLineText(const QString &s);
+ void insertIntoPhraseList (const QString &phrase, bool clearEditLine);
+
+ void enableMenuEntries ();
+};
+
+#endif
diff --git a/kmouth/phraselistitem.cpp b/kmouth/phraselistitem.cpp
new file mode 100644
index 0000000..6156054
--- /dev/null
+++ b/kmouth/phraselistitem.cpp
@@ -0,0 +1,52 @@
+/***************************************************************************
+ phraselistitem.cpp - description
+ -------------------
+ begin : Fre Sep 6 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "phraselistitem.h"
+#include <qstyle.h>
+#include <qpainter.h>
+
+PhraseListItem::PhraseListItem (const QString & text)
+ : QListBoxText::QListBoxText(text) {
+}
+
+PhraseListItem::~PhraseListItem() {
+}
+
+bool PhraseListItem::drawCursor() const {
+ if ((QListBoxItem *)this != listBox()->item (listBox()->currentItem()))
+ return false;
+
+ for (QListBoxItem *item = listBox()->firstItem(); item != 0; item = item->next() ) {
+ if (item->isSelected())
+ return true;
+ }
+ return false;
+}
+
+int PhraseListItem::rtti() const {
+ return RTTI;
+}
+
+void PhraseListItem::paint (QPainter *p) {
+ QListBoxText::paint (p);
+
+ if (drawCursor()) {
+ QRect r (0, 0, listBox()->maxItemWidth(), height (listBox()));
+ listBox()->style().drawPrimitive (QStyle::PE_FocusRect, p, r,
+ listBox()->colorGroup());
+ }
+}
diff --git a/kmouth/phraselistitem.h b/kmouth/phraselistitem.h
new file mode 100644
index 0000000..24d5e49
--- /dev/null
+++ b/kmouth/phraselistitem.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ phraselistitem.h - description
+ -------------------
+ begin : Fre Sep 6 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PHRASELISTITEM_H
+#define PHRASELISTITEM_H
+
+#include <qlistbox.h>
+
+/**
+ * This class represents a phrase in the list of spoken phrases. It extends
+ * QListBoxText for providing support for a visible list cursor.
+ * @author Gunnar Schmi Dt
+ */
+
+class PhraseListItem : public QListBoxText {
+public:
+ PhraseListItem (const QString & text);
+ ~PhraseListItem();
+
+ bool drawCursor() const;
+
+ int rtti() const;
+ static const int RTTI = 982734;
+
+protected:
+ void paint( QPainter * );
+};
+
+#endif
diff --git a/kmouth/preferencesui.ui b/kmouth/preferencesui.ui
new file mode 100644
index 0000000..a718b9d
--- /dev/null
+++ b/kmouth/preferencesui.ui
@@ -0,0 +1,162 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>PreferencesUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>PreferencesUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>339</width>
+ <height>148</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Preferences</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>speakLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Selection of phrases in the phrase book:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>speakCombo</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies whether selected phrases of the phrase book are immediately spoken or just inserted into the edit field.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <item>
+ <property name="text">
+ <string>Speak Immediately</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Insert Into Edit Field</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>speakCombo</cstring>
+ </property>
+ <property name="currentItem">
+ <number>1</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies whether selected phrases of the phrase book are immediately spoken or just inserted into the edit field.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>closeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Closing the phrase &amp;book edit window:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>closeCombo</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies whether the phrase book is automatically saved when the edit window is closed.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <item>
+ <property name="text">
+ <string>Save Phrase Book</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Discard Changes</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Ask Whether to Save</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>closeCombo</cstring>
+ </property>
+ <property name="currentItem">
+ <number>2</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies whether the phrase book is automatically saved when the edit window is closed.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kmouth/speech.cpp b/kmouth/speech.cpp
new file mode 100644
index 0000000..d2f7db8
--- /dev/null
+++ b/kmouth/speech.cpp
@@ -0,0 +1,242 @@
+/***************************************************************************
+ speech.cpp - description
+ -------------------
+ begin : Son Sep 8 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "speech.h"
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qvaluestack.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qtextcodec.h>
+#include <qfile.h>
+#include <kdebug.h>
+
+#include <kdeversion.h>
+#ifdef KDE_IS_VERSION
+#if KDE_IS_VERSION(3,2,0)
+ #define macroExpander
+ #include <kmacroexpander.h>
+#endif
+#endif
+
+Speech::Speech() {
+}
+
+Speech::~Speech() {
+}
+
+QString Speech::prepareCommand (QString command, const QString &text,
+ const QString &filename, const QString &language) {
+#ifdef macroExpander
+ QMap<QChar,QString> map;
+ map['t'] = text;
+ map['f'] = filename;
+ map['l'] = language;
+ return KMacroExpander::expandMacrosShellQuote (command, map);
+#else
+ QValueStack<bool> stack; // saved isdoublequote values during parsing of braces
+ bool issinglequote=false; // inside '...' ?
+ bool isdoublequote=false; // inside "..." ?
+ int noreplace=0; // nested braces when within ${...}
+ QString escText = KShellProcess::quote(text);
+
+ // character sequences that change the state or need to be otherwise processed
+ QRegExp re_singlequote("('|%%|%t|%f|%l)");
+ QRegExp re_doublequote("(\"|\\\\|`|\\$\\(|\\$\\{|%%|%t|%f|%l)");
+ QRegExp re_noquote ("('|\"|\\\\|`|\\$\\(|\\$\\{|\\(|\\{|\\)|\\}|%%|%t|%f|%l)");
+
+ // parse the command:
+ for (int i = re_noquote.search(command);
+ i != -1;
+ i = (issinglequote?re_singlequote.search(command,i)
+ :isdoublequote?re_doublequote.search(command,i)
+ :re_noquote.search(command,i))
+ )
+ // while there are character sequences that need to be processed
+ {
+ if ((command[i]=='(') || (command[i]=='{')) { // (...) or {...}
+ // assert(isdoublequote == false)
+ stack.push(isdoublequote);
+ if (noreplace > 0)
+ // count nested braces when within ${...}
+ noreplace++;
+ i++;
+ }
+ else if (command[i]=='$') { // $(...) or ${...}
+ stack.push(isdoublequote);
+ isdoublequote = false;
+ if ((noreplace > 0) || (command[i+1]=='{'))
+ // count nested braces when within ${...}
+ noreplace++;
+ i+=2;
+ }
+ else if ((command[i]==')') || (command[i]=='}')) {
+ // $(...) or (...) or ${...} or {...}
+ if (!stack.isEmpty())
+ isdoublequote = stack.pop();
+ else
+ qWarning("Parse error.");
+ if (noreplace > 0)
+ // count nested braces when within ${...}
+ noreplace--;
+ i++;
+ }
+ else if (command[i]=='\'') {
+ issinglequote=!issinglequote;
+ i++;
+ }
+ else if (command[i]=='"') {
+ isdoublequote=!isdoublequote;
+ i++;
+ }
+ else if (command[i]=='\\')
+ i+=2;
+ else if (command[i]=='`') {
+ // Replace all `...` with safer $(...)
+ command.replace (i, 1, "$(");
+ QRegExp re_backticks("(`|\\\\`|\\\\\\\\|\\\\\\$)");
+ for (int i2=re_backticks.search(command,i+2);
+ i2!=-1;
+ i2=re_backticks.search(command,i2)
+ )
+ {
+ if (command[i2] == '`') {
+ command.replace (i2, 1, ")");
+ i2=command.length(); // leave loop
+ }
+ else {
+ // remove backslash and ignore following character
+ command.remove (i2, 1);
+ i2++;
+ }
+ }
+ // Leave i unchanged! We need to process "$("
+ }
+ else if (noreplace > 0) { // do not replace macros within ${...}
+ if (issinglequote)
+ i+=re_singlequote.matchedLength();
+ else if (isdoublequote)
+ i+=re_doublequote.matchedLength();
+ else
+ i+=re_noquote.matchedLength();
+ }
+ else { // replace macro
+ QString match, v;
+
+ // get match
+ if (issinglequote)
+ match=re_singlequote.cap();
+ else if (isdoublequote)
+ match=re_doublequote.cap();
+ else
+ match=re_noquote.cap();
+
+ // substitute %variables
+ if (match=="%t")
+ v = escText;
+ else if (match=="%f")
+ v = filename;
+ else if (match=="%%")
+ v = "%";
+ else if (match=="%l")
+ v = language;
+
+ // %variable inside of a quote?
+ if (isdoublequote)
+ v='"'+v+'"';
+ else if (issinglequote)
+ v="'"+v+"'";
+
+ command.replace (i, match.length(), v);
+ i+=v.length();
+ }
+ }
+ return command;
+#endif
+}
+
+void Speech::speak(QString command, bool stdIn, const QString &text, const QString &language, int encoding, QTextCodec *codec) {
+ if (text.length () > 0) {
+ // 1. prepare the text:
+ // 1.a) encode the text
+ QTextStream ts (encText, IO_WriteOnly);
+ if (encoding == Local)
+ ts.setEncoding (QTextStream::Locale);
+ else if (encoding == Latin1)
+ ts.setEncoding (QTextStream::Latin1);
+ else if (encoding == Unicode)
+ ts.setEncoding (QTextStream::Unicode);
+ else
+ ts.setCodec (codec);
+ ts << text;
+
+ // 1.b) create a temporary file for the text
+ tempFile.setAutoDelete(true);
+ QTextStream* fs = tempFile.textStream();
+ if (encoding == Local)
+ fs->setEncoding (QTextStream::Locale);
+ else if (encoding == Latin1)
+ fs->setEncoding (QTextStream::Latin1);
+ else if (encoding == Unicode)
+ fs->setEncoding (QTextStream::Unicode);
+ else
+ fs->setCodec (codec);
+ *fs << text;
+ *fs << endl;
+ QString filename = tempFile.file()->name();
+ tempFile.close();
+
+ // 2. prepare the command:
+ command = prepareCommand (command, encText, filename, language);
+
+
+ // 3. create a new process
+ process << command;
+ connect(&process, SIGNAL(processExited(KProcess *)), this, SLOT(processExited(KProcess *)));
+ connect(&process, SIGNAL(wroteStdin(KProcess *)), this, SLOT(wroteStdin(KProcess *)));
+ connect(&process, SIGNAL(receivedStdout(KProcess *, char *, int)), this, SLOT(receivedStdout(KProcess *, char *, int)));
+ connect(&process, SIGNAL(receivedStderr(KProcess *, char *, int)), this, SLOT(receivedStderr(KProcess *, char *, int)));
+
+ // 4. start the process
+ if (stdIn) {
+ process.start(KProcess::NotifyOnExit, KProcess::All);
+ if (encText.size() > 0)
+ process.writeStdin(encText, encText.size());
+ else
+ process.closeStdin();
+ }
+ else
+ process.start(KProcess::NotifyOnExit, KProcess::AllOutput);
+ }
+}
+
+void Speech::receivedStdout (KProcess *, char *buffer, int buflen) {
+ kdDebug() << QString::fromLatin1(buffer, buflen) + "\n";
+}
+void Speech::receivedStderr (KProcess *, char *buffer, int buflen) {
+ kdDebug() << QString::fromLatin1(buffer, buflen) + "\n";
+}
+
+void Speech::wroteStdin(KProcess *) {
+ process.closeStdin();
+}
+
+void Speech::processExited(KProcess *) {
+ delete this;
+}
+
+#include "speech.moc"
diff --git a/kmouth/speech.h b/kmouth/speech.h
new file mode 100644
index 0000000..83c728c
--- /dev/null
+++ b/kmouth/speech.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ speech.h - description
+ -------------------
+ begin : Son Sep 8 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef SPEECH_H
+#define SPEECH_H
+
+#include <qobject.h>
+#include <qstring.h>
+#include <kprocess.h>
+#include <ktempfile.h>
+
+/**This class is used internally by TextToSpeechSystem in order to do the actual speaking.
+ *@author Gunnar Schmi Dt
+ */
+
+class Speech : public QObject {
+ Q_OBJECT
+public:
+ enum CharacterCodec {
+ Local = 0,
+ Latin1 = 1,
+ Unicode = 2,
+ UseCodec = 3
+ };
+
+ Speech();
+ ~Speech();
+
+ /**
+ * Speaks the given text.
+ * @param command the program that shall be executed for speaking
+ * @param stdin true if the program shall receive its data via standard input
+ * @param text The text that shall be spoken
+ */
+ void speak(QString command, bool use_stdin, const QString &text, const QString &language, int encoding, QTextCodec *codec);
+
+ /**
+ * Prepares a command for being executed. During the preparation the
+ * command is parsed and occurrences of "%t" are replaced by text.
+ * @param command the command that shall be executed for speaking
+ * @param text the quoted text that can be inserted into the command
+ */
+ QString prepareCommand (QString command, const QString &text,
+ const QString &filename, const QString &language);
+
+public slots:
+ void wroteStdin (KProcess *p);
+ void processExited (KProcess *p);
+ void receivedStdout (KProcess *proc, char *buffer, int buflen);
+ void receivedStderr (KProcess *proc, char *buffer, int buflen);
+
+private:
+ KShellProcess process;
+ QByteArray encText;
+ KTempFile tempFile;
+};
+
+#endif
diff --git a/kmouth/texttospeechconfigurationui.ui b/kmouth/texttospeechconfigurationui.ui
new file mode 100644
index 0000000..de393ce
--- /dev/null
+++ b/kmouth/texttospeechconfigurationui.ui
@@ -0,0 +1,170 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>texttospeechconfigurationui</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>texttospeechconfigurationui</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>391</width>
+ <height>222</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Text-to-Speech</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>urlLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>C&amp;ommand for speaking texts:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>urlReq</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This field specifies both the command used for speaking texts and its parameters. KMouth knows the following placeholders:
+%t -- the text that should be spoken
+%f -- the name of a file containing the text
+%l -- the language code
+%% -- a percent sign</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>urlReq</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This field specifies both the command used for speaking texts and its parameters. KMouth knows the following placeholders:
+%t -- the text that should be spoken
+%f -- the name of a file containing the text
+%l -- the language code
+%% -- a percent sign</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>characterCodingLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Character &amp;encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies which character encoding is used for passing the text.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies which character encoding is used for passing the text.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>stdInButton</cstring>
+ </property>
+ <property name="text">
+ <string>Send the data as standard &amp;input</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This check box specifies whether the text is sent as standard input to the speech synthesizer.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>useKttsd</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Use KTTSD speech service if possible</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This check box specifies KMouth tries to use the KTTSD speech service prior to calling the speech synthesizer directly. The KTTSD speech service is a KDE daemon which gives KDE applications a standardized interface for speech synthesis and is currently developed in CVS.</string>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<signals>
+ <signal>configurationChanged()</signal>
+</signals>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/kmouth/texttospeechconfigurationwidget.cpp b/kmouth/texttospeechconfigurationwidget.cpp
new file mode 100644
index 0000000..f697061
--- /dev/null
+++ b/kmouth/texttospeechconfigurationwidget.cpp
@@ -0,0 +1,86 @@
+/***************************************************************************
+ texttospeechconfigurationdialog.cpp - description
+ -------------------
+ begin : Son Sep 8 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include "texttospeechconfigurationwidget.h"
+#include <kconfig.h>
+#include <qtextcodec.h>
+#include <qptrlist.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <kcombobox.h>
+#include <klocale.h>
+#include <qlabel.h>
+#include "speech.h"
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <kurlrequester.h>
+
+TextToSpeechConfigurationWidget::TextToSpeechConfigurationWidget (QWidget *parent, const char *name)
+ : texttospeechconfigurationui (parent, name)
+{
+ ttsSystem = new TextToSpeechSystem();
+
+ urlReq->setShowLocalProtocol (false);
+ buildCodecList();
+}
+
+TextToSpeechConfigurationWidget::~TextToSpeechConfigurationWidget() {
+}
+
+void TextToSpeechConfigurationWidget::buildCodecList () {
+ QString local = i18n("Local")+" (";
+ local += QTextCodec::codecForLocale()->name();
+ local += ")";
+ characterCodingBox->insertItem (local, Speech::Local);
+ characterCodingBox->insertItem (i18n("Latin1"), Speech::Latin1);
+ characterCodingBox->insertItem (i18n("Unicode"), Speech::Unicode);
+ for (uint i = 0; i < ttsSystem->codecList->count(); i++ )
+ characterCodingBox->insertItem (ttsSystem->codecList->at(i)->name(), Speech::UseCodec + i);
+}
+
+void TextToSpeechConfigurationWidget::cancel() {
+ urlReq->setURL (ttsSystem->ttsCommand);
+ stdInButton->setChecked (ttsSystem->stdIn);
+ characterCodingBox->setCurrentItem(ttsSystem->codec);
+ useKttsd->setChecked (ttsSystem->useKttsd);
+}
+
+void TextToSpeechConfigurationWidget::ok() {
+ ttsSystem->ttsCommand = urlReq->url();
+ ttsSystem->stdIn = stdInButton->isChecked();
+ ttsSystem->codec = characterCodingBox->currentItem();
+ ttsSystem->useKttsd = useKttsd->isChecked();
+}
+
+TextToSpeechSystem *TextToSpeechConfigurationWidget::getTTSSystem() const {
+ return ttsSystem;
+}
+
+void TextToSpeechConfigurationWidget::readOptions (KConfig *config, const QString &langGroup) {
+ ttsSystem->readOptions (config, langGroup);
+ urlReq->setURL (ttsSystem->ttsCommand);
+ stdInButton->setChecked (ttsSystem->stdIn);
+ characterCodingBox->setCurrentItem(ttsSystem->codec);
+ useKttsd->setChecked (ttsSystem->useKttsd);
+}
+
+void TextToSpeechConfigurationWidget::saveOptions (KConfig *config, const QString &langGroup) {
+ ttsSystem->saveOptions (config, langGroup);
+}
+
diff --git a/kmouth/texttospeechconfigurationwidget.h b/kmouth/texttospeechconfigurationwidget.h
new file mode 100644
index 0000000..439ae4f
--- /dev/null
+++ b/kmouth/texttospeechconfigurationwidget.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ texttospeechconfigurationdialog.h - description
+ -------------------
+ begin : Son Sep 8 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef TEXTTOSPEECHCONFIGURATIONDIALOG_H
+#define TEXTTOSPEECHCONFIGURATIONDIALOG_H
+
+#include <kdialogbase.h>
+#include "texttospeechconfigurationui.h"
+#include "texttospeechsystem.h"
+
+/**This class represents a configuration widget for the text-to-speech system.
+ *@author Gunnar Schmi Dt
+ */
+
+class TextToSpeechConfigurationWidget : public texttospeechconfigurationui {
+ friend class TextToSpeechConfigurationDialog;
+public:
+ TextToSpeechConfigurationWidget(QWidget *parent, const char *name);
+ ~TextToSpeechConfigurationWidget();
+
+ TextToSpeechSystem *getTTSSystem() const;
+
+ void readOptions (KConfig *config, const QString &langGroup);
+ void saveOptions (KConfig *config, const QString &langGroup);
+
+ void ok();
+ void cancel();
+
+private:
+ void buildCodecList ();
+
+ TextToSpeechSystem *ttsSystem;
+};
+
+#endif
+
diff --git a/kmouth/texttospeechsystem.cpp b/kmouth/texttospeechsystem.cpp
new file mode 100644
index 0000000..4aeb0f9
--- /dev/null
+++ b/kmouth/texttospeechsystem.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+ texttospeechsystem.cpp - description
+ -------------------
+ begin : Son Sep 8 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include "texttospeechsystem.h"
+#include <qregexp.h>
+#include <qtextcodec.h>
+#include <qptrlist.h>
+#include <stdlib.h>
+
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <kconfig.h>
+
+#include "speech.h"
+
+TextToSpeechSystem::TextToSpeechSystem() {
+ ttsCommand = "";
+ stdIn = true;
+ useKttsd = true;
+ codec = Speech::Local; // local encoding;
+ buildCodecList();
+}
+
+TextToSpeechSystem::~TextToSpeechSystem() {
+ delete codecList;
+}
+
+bool kttsdSay (const QString &text, const QString &language) {
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray data;
+ QCString replyType;
+ QByteArray replyData;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << text << language;
+ return client->call("kttsd", "KSpeech", "sayWarning(QString,QString)",
+ data, replyType, replyData, true);
+}
+
+void TextToSpeechSystem::speak (const QString &text, const QString &language) {
+ if (text.length() > 0) {
+ if (useKttsd) {
+ if (kttsdSay(text, language))
+ return;
+ }
+
+ if (codec < Speech::UseCodec)
+ (new Speech())->speak(ttsCommand, stdIn, text, language, codec, 0);
+ else
+ (new Speech())->speak(ttsCommand, stdIn, text, language, Speech::UseCodec,
+ codecList->at (codec - Speech::UseCodec));
+ }
+}
+
+void TextToSpeechSystem::readOptions (KConfig *config, const QString &langGroup) {
+ config->setGroup(langGroup);
+ ttsCommand = config->readPathEntry("Command");
+ stdIn = config->readBoolEntry("StdIn", true);
+ useKttsd = config->readBoolEntry("useKttsd", true);
+
+ QString codecString = config->readEntry("Codec", "Local");
+ if (codecString == "Local")
+ codec = Speech::Local;
+ else if (codecString == "Latin1")
+ codec = Speech::Latin1;
+ else if (codecString == "Unicode")
+ codec = Speech::Unicode;
+ else {
+ codec = Speech::Local;
+ for (uint i = 0; i < codecList->count(); i++ )
+ if (codecString == codecList->at(i)->name())
+ codec = Speech::UseCodec + i;
+ }
+}
+
+void TextToSpeechSystem::saveOptions (KConfig *config, const QString &langGroup) {
+ config->setGroup(langGroup);
+ config->writePathEntry("Command", ttsCommand);
+ config->writeEntry("StdIn", stdIn);
+ config->writeEntry("useKttsd", useKttsd);
+ if (codec == Speech::Local)
+ config->writeEntry("Codec", "Local");
+ else if (codec == Speech::Latin1)
+ config->writeEntry("Codec", "Latin1");
+ else if (codec == Speech::Unicode)
+ config->writeEntry("Codec", "Unicode");
+ else config->writeEntry("Codec",
+ codecList->at (codec-Speech::UseCodec)->name());
+
+}
+
+void TextToSpeechSystem::buildCodecList () {
+ codecList = new QPtrList<QTextCodec>;
+ QTextCodec *codec;
+ int i;
+ for (i = 0; (codec = QTextCodec::codecForIndex(i)); i++)
+ codecList->append (codec);
+}
+
+#include "texttospeechsystem.moc"
diff --git a/kmouth/texttospeechsystem.h b/kmouth/texttospeechsystem.h
new file mode 100644
index 0000000..fc9b018
--- /dev/null
+++ b/kmouth/texttospeechsystem.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ texttospeechsystem.h - description
+ -------------------
+ begin : Son Sep 8 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef TEXTTOSPEECHSYSTEM_H
+#define TEXTTOSPEECHSYSTEM_H
+
+#include <qstring.h>
+#include <qobject.h>
+#include <qptrlist.h>
+
+class KConfig;
+
+/**This class represents a text-to-speech system.
+ *@author Gunnar Schmi Dt
+ */
+
+class TextToSpeechSystem : public QObject{
+ Q_OBJECT
+ friend class TextToSpeechConfigurationWidget;
+public:
+ TextToSpeechSystem();
+ ~TextToSpeechSystem();
+
+ void readOptions (KConfig *config, const QString &langGroup);
+ void saveOptions (KConfig *config, const QString &langGroup);
+
+public slots:
+ void speak (const QString &text, const QString &language);
+
+private:
+ void buildCodecList ();
+
+ QPtrList<QTextCodec> *codecList;
+ int codec;
+ QString ttsCommand;
+ bool stdIn;
+ bool useKttsd;
+};
+
+#endif
diff --git a/kmouth/version.h b/kmouth/version.h
new file mode 100644
index 0000000..0f5fa60
--- /dev/null
+++ b/kmouth/version.h
@@ -0,0 +1,8 @@
+// KMouth Version Information
+//
+#ifndef kmouth_version_h
+#define kmouth_version_h
+
+#define KMOUTH_VERSION "1.1.1"
+
+#endif /*version_h*/
diff --git a/kmouth/wordcompletion/Makefile.am b/kmouth/wordcompletion/Makefile.am
new file mode 100644
index 0000000..8926f41
--- /dev/null
+++ b/kmouth/wordcompletion/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LIBRARIES = libwordcompletion.a
+
+INCLUDES = $(all_includes)
+
+libwordcompletion_a_METASOURCES = AUTO
+
+libwordcompletion_a_SOURCES = wordcompletionui.ui creationsourceui.ui creationsourcedetailsui.ui kdedocsourceui.ui \
+ wordlist.cpp wordcompletion.cpp wordcompletionwidget.cpp dictionarycreationwizard.cpp klanguagebutton.cpp klanguagebuttonhelper.cpp
+
+EXTRA_DIST = wordcompletionui.ui creationsourceui.ui creationsourcedetailsui.ui kdedocsourceui.ui \
+ creationsourceui.ui.h creationsourcedetailsui.ui.h kdedocsourceui.ui.h \
+ wordlist.cpp wordcompletion.cpp wordcompletionwidget.cpp dictionarycreationwizard.cpp klanguagebutton.cpp klanguagebuttonhelper.cpp \
+ wordlist.h wordcompletion.h wordcompletionwidget.h dictionarycreationwizard.h klanguagebutton.h klanguagebuttonhelper.h
diff --git a/kmouth/wordcompletion/creationsourcedetailsui.ui b/kmouth/wordcompletion/creationsourcedetailsui.ui
new file mode 100644
index 0000000..1a1f61b
--- /dev/null
+++ b/kmouth/wordcompletion/creationsourcedetailsui.ui
@@ -0,0 +1,184 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>CreationSourceDetailsUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CreationSourceDetailsUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>421</width>
+ <height>189</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spellCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Compare to OpenOffice.org dictionary:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this check box the words are spell-checked before they are inserted into the new dictionary.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>encodingLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Character &amp;encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>encodingCombo</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this combo box you select the character encoding used to load text files. This combo box is not used for XML files or for dictionary files.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>urlLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Filename:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>url</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this input field you specify which file you want to load for creating the new dictionary.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>url</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this input field you specify which file you want to load for creating the new dictionary.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>encodingCombo</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this combo box you select the character encoding used to load text files. This combo box is not used for XML files or for dictionary files.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="4" column="1">
+ <property name="name">
+ <cstring>ooDictURL</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this input field you select the OpenOffice.org directory that will be used to spellcheck the words of the new dictionary.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Language:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this combo box you decide which language should be associated with the new dictionary.</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>spellCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>ooDictURL</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in implementation">kinputdialog.h</include>
+ <include location="local" impldecl="in implementation">klanguagebutton.h</include>
+ <include location="local" impldecl="in implementation">klanguagebuttonhelper.h</include>
+ <include location="local" impldecl="in implementation">creationsourcedetailsui.ui.h</include>
+</includes>
+<forwards>
+ <forward>class KLanguageButton</forward>
+</forwards>
+<variables>
+ <variable access="public">KLanguageButton *languageButton;</variable>
+</variables>
+<slots>
+ <slot access="protected" specifier="non virtual">languageButton_activated( int index )</slot>
+</slots>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kinputdialog.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>kinputdialog.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kmouth/wordcompletion/creationsourcedetailsui.ui.h b/kmouth/wordcompletion/creationsourcedetailsui.ui.h
new file mode 100644
index 0000000..956f021
--- /dev/null
+++ b/kmouth/wordcompletion/creationsourcedetailsui.ui.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void CreationSourceDetailsUI::init() {
+ languageButton = new KLanguageButton (this, "languageButton");
+ CreationSourceDetailsUILayout->addWidget (languageButton, 2, 1);
+ languageLabel->setBuddy (languageButton);
+ QWhatsThis::add (languageButton, i18n("With this combo box you decide which language should be associated with the new dictionary."));
+
+ loadLanguageList(languageButton);
+ languageButton->insertLanguage("??", i18n("Other"), QString::fromLatin1("l10n/"), QString::null);
+
+ connect (languageButton, SIGNAL(activated(int)), this, SLOT(languageButton_activated(int)));
+}
+
+void CreationSourceDetailsUI::languageButton_activated (int) {
+ if (languageButton->currentTag() == "??") {
+ QString customLanguage = KInputDialog::getText(i18n("Create Custom Language"), i18n("Please enter the code for the custom language:"));
+
+ if (languageButton->containsTag(customLanguage)) {
+ languageButton->setCurrentItem(customLanguage);
+ }
+ else {
+ languageButton->insertLanguage(customLanguage, i18n("without name"), QString::fromLatin1("l10n/"), QString::null);
+ languageButton->setCurrentItem(customLanguage);
+ }
+ }
+}
+
+
diff --git a/kmouth/wordcompletion/creationsourceui.ui b/kmouth/wordcompletion/creationsourceui.ui
new file mode 100644
index 0000000..13a7c06
--- /dev/null
+++ b/kmouth/wordcompletion/creationsourceui.ui
@@ -0,0 +1,179 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>CreationSourceUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CreationSourceUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>318</width>
+ <height>223</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>createButton</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;reate new dictionary:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this box a new dictionary is created by either loading a dictionary file or by counting the individual words in a text.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>mergeButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Merge dictionaries</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this box a new dictionary is created by merging existing dictionaries.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="1">
+ <property name="name">
+ <cstring>fileButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>From &amp;file</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this box a new dictionary is created by loading a file. You may either select an XML file, a standard text file or a file containing a word completion dictionary. If you select a standard text file or an XML file the frequentness of the individual words is detected by simply counting the occurrences of each word.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="1">
+ <property name="name">
+ <cstring>kdeDocButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>From &amp;KDE documentation</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this box a new dictionary is created by parsing the KDE documentation. The frequentness of the individual words is detect by simply counting the occurrences of each word.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="1">
+ <property name="name">
+ <cstring>directoryButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>From f&amp;older</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this box a new dictionary is created by loading all files in a folder and its subdirectories.</string>
+ </property>
+ </widget>
+ <spacer row="1" column="0" rowspan="3" colspan="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QRadioButton" row="5" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>emptyButton</cstring>
+ </property>
+ <property name="text">
+ <string>Create an &amp;empty wordlist</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this box a blank dictionary without any entries is created. As KMouth automatically adds newly typed words to the dictionaries it will learn your vocabulary with the time.</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>createButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kdeDocButton</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>createButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fileButton</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>createButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>directoryButton</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in implementation">qbuttongroup.h</include>
+ <include location="local" impldecl="in implementation">creationsourceui.ui.h</include>
+</includes>
+<forwards>
+ <forward>class QButtonGroup</forward>
+</forwards>
+<variables>
+ <variable access="public">QButtonGroup *group2;</variable>
+ <variable access="public">QButtonGroup *group1;</variable>
+</variables>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+ <function access="private" specifier="non virtual">destroy()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kmouth/wordcompletion/creationsourceui.ui.h b/kmouth/wordcompletion/creationsourceui.ui.h
new file mode 100644
index 0000000..d78a439
--- /dev/null
+++ b/kmouth/wordcompletion/creationsourceui.ui.h
@@ -0,0 +1,26 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void CreationSourceUI::init() {
+ group1 = new QButtonGroup (0);
+ group1->insert (createButton);
+ group1->insert (mergeButton);
+ group1->insert (emptyButton);
+ group2 = new QButtonGroup (0);
+ group2->insert (kdeDocButton);
+ group2->insert (fileButton);
+ group2->insert (directoryButton);
+}
+
+
+void CreationSourceUI::destroy() {
+ delete group1;
+ delete group2;
+}
diff --git a/kmouth/wordcompletion/dictionarycreationwizard.cpp b/kmouth/wordcompletion/dictionarycreationwizard.cpp
new file mode 100644
index 0000000..a0711ce
--- /dev/null
+++ b/kmouth/wordcompletion/dictionarycreationwizard.cpp
@@ -0,0 +1,376 @@
+/***************************************************************************
+ wordcompletionwidget.cpp - description
+ -------------------
+ begin : Tue Apr 29 2003
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qtextcodec.h>
+#include <qwhatsthis.h>
+
+#include <klistview.h>
+#include <klineedit.h>
+#include <kurlrequester.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <ksconfig.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+#include <kconfig.h>
+
+#include "dictionarycreationwizard.h"
+#include "klanguagebutton.h"
+#include "creationsourceui.h"
+#include "creationsourcedetailsui.h"
+#include "kdedocsourceui.h"
+#include "wordlist.h"
+
+DictionaryCreationWizard::DictionaryCreationWizard (QWidget *parent, const char *name,
+ QStringList dictionaryNames, QStringList dictionaryFiles,
+ QStringList dictionaryLanguages)
+ : KWizard (parent, name)
+{
+ buildCodecList ();
+
+ creationSource = new CreationSourceUI (this, "source page");
+ addPage (creationSource, i18n("Source of New Dictionary (1)"));
+ setHelpEnabled (creationSource, false);
+ setFinishEnabled (creationSource, false);
+
+ fileWidget= new CreationSourceDetailsUI (this, "file source page");
+ addPage (fileWidget, i18n("Source of New Dictionary (2)"));
+ buildCodecCombo (fileWidget->encodingCombo);
+
+ dirWidget= new CreationSourceDetailsUI (this, "directory source page");
+ addPage (dirWidget, i18n("Source of New Dictionary (2)"));
+ dirWidget->urlLabel->setText (i18n("&Directory:"));
+ QWhatsThis::add (dirWidget->urlLabel, i18n("With this input field you specify which directory you want to load for creating the new dictionary."));
+ dirWidget->url->setMode(KFile::Directory);
+ QWhatsThis::add (dirWidget->url, i18n("With this input field you specify which directory you want to load for creating the new dictionary."));
+ buildCodecCombo (dirWidget->encodingCombo);
+
+ kdeDocWidget= new KDEDocSourceUI (this, "KDE documentation source page");
+ addPage (kdeDocWidget, i18n("Source of New Dictionary (2)"));
+
+ mergeWidget = new MergeWidget (this, "merge source page", dictionaryNames, dictionaryFiles, dictionaryLanguages);
+ addPage (mergeWidget, i18n("Source of New Dictionary (2)"));
+
+ connect (creationSource->fileButton, SIGNAL (toggled(bool)), this, SLOT(calculateAppropriate(bool)) );
+ connect (creationSource->directoryButton,SIGNAL(toggled(bool)), this, SLOT(calculateAppropriate(bool)) );
+ connect (creationSource->kdeDocButton, SIGNAL (toggled(bool)), this, SLOT(calculateAppropriate(bool)) );
+ connect (creationSource->mergeButton, SIGNAL (toggled(bool)), this, SLOT(calculateAppropriate(bool)) );
+ connect (creationSource->emptyButton, SIGNAL (toggled(bool)), this, SLOT(calculateAppropriate(bool)) );
+
+ calculateAppropriate (true);
+}
+
+DictionaryCreationWizard::~DictionaryCreationWizard () {
+ delete codecList;
+ removePage (fileWidget); delete fileWidget;
+ removePage (dirWidget); delete dirWidget;
+ removePage (kdeDocWidget); delete kdeDocWidget;
+ removePage (mergeWidget); delete mergeWidget;
+}
+
+void DictionaryCreationWizard::buildCodecList () {
+ codecList = new QPtrList<QTextCodec>;
+ QTextCodec *codec;
+ int i;
+ for (i = 0; (codec = QTextCodec::codecForIndex(i)); i++)
+ codecList->append (codec);
+}
+
+void DictionaryCreationWizard::buildCodecCombo (QComboBox *combo) {
+ QString local = i18n("Local")+" (";
+ local += QTextCodec::codecForLocale()->name();
+ local += ")";
+ combo->insertItem (local, 0);
+ combo->insertItem (i18n("Latin1"), 1);
+ combo->insertItem (i18n("Unicode"), 2);
+ for (uint i = 0; i < codecList->count(); i++ )
+ combo->insertItem (codecList->at(i)->name(), i+3);
+}
+
+void DictionaryCreationWizard::calculateAppropriate (bool) {
+ if (creationSource->mergeButton->isChecked()) {
+ setFinishEnabled (creationSource, false);
+ removePage (fileWidget);
+ removePage (dirWidget);
+ removePage (kdeDocWidget);
+ addPage (mergeWidget, i18n("Source of New Dictionary (2)"));
+ setHelpEnabled (mergeWidget, false);
+ setFinishEnabled (mergeWidget, true);
+ }
+ else if (creationSource->emptyButton->isChecked()) {
+ removePage (fileWidget);
+ removePage (dirWidget);
+ removePage (kdeDocWidget);
+ removePage (mergeWidget);
+ setFinishEnabled (creationSource, true);
+ }
+ else if (creationSource->fileButton->isChecked()) {
+ setFinishEnabled (creationSource, false);
+ removePage (dirWidget);
+ removePage (kdeDocWidget);
+ removePage (mergeWidget);
+ addPage (fileWidget, i18n("Source of New Dictionary (2)"));
+ setHelpEnabled (fileWidget, false);
+ setFinishEnabled (fileWidget, true);
+ }
+ else if (creationSource->directoryButton->isChecked()) {
+ setFinishEnabled (creationSource, false);
+ removePage (fileWidget);
+ removePage (kdeDocWidget);
+ removePage (mergeWidget);
+ addPage (dirWidget, i18n("Source of New Dictionary (2)"));
+ setHelpEnabled (dirWidget, false);
+ setFinishEnabled (dirWidget, true);
+ }
+ else { // creationSource->kdeDocButton must be checked
+ setFinishEnabled (creationSource, false);
+ removePage (fileWidget);
+ removePage (dirWidget);
+ removePage (mergeWidget);
+ addPage (kdeDocWidget, i18n("Source of New Dictionary (2)"));
+ setHelpEnabled (kdeDocWidget, false);
+ setFinishEnabled (kdeDocWidget, true);
+ }
+}
+
+QString DictionaryCreationWizard::createDictionary() {
+ WordList::WordMap map;
+ QString dicFile = "";
+ KProgressDialog *pdlg = WordList::progressDialog();
+
+ if (creationSource->mergeButton->isChecked()) {
+ map = WordList::mergeFiles (mergeWidget->mergeParameters(), pdlg);
+ dicFile = QString::null;
+ }
+ else if (creationSource->emptyButton->isChecked()) {
+ dicFile = QString::null;
+ }
+ else if (creationSource->fileButton->isChecked()) {
+ QString filename = fileWidget->url->url();
+ int encoding = fileWidget->encodingCombo->currentItem();
+ if (fileWidget->spellCheckBox->isChecked())
+ dicFile = fileWidget->ooDictURL->url();
+ switch (encoding) {
+ case 0:
+ map = WordList::parseFile (filename, QTextStream::Locale, 0, pdlg);
+ break;
+ case 1:
+ map = WordList::parseFile (filename, QTextStream::Latin1, 0, pdlg);
+ break;
+ case 2:
+ map = WordList::parseFile (filename, QTextStream::Unicode, 0, pdlg);
+ break;
+ default:
+ map = WordList::parseFile (filename, (QTextStream::Encoding)0, codecList->at(encoding-3), pdlg);
+ }
+ }
+ else if (creationSource->directoryButton->isChecked()) {
+ QString directory = dirWidget->url->url();
+ int encoding = dirWidget->encodingCombo->currentItem();
+ if (dirWidget->spellCheckBox->isChecked())
+ dicFile = dirWidget->ooDictURL->url();
+ switch (encoding) {
+ case 0:
+ map = WordList::parseDir (directory, QTextStream::Locale, 0, pdlg);
+ break;
+ case 1:
+ map = WordList::parseDir (directory, QTextStream::Latin1, 0, pdlg);
+ break;
+ case 2:
+ map = WordList::parseDir (directory, QTextStream::Unicode, 0, pdlg);
+ break;
+ default:
+ map = WordList::parseDir (directory, (QTextStream::Encoding)0, codecList->at(encoding-3), pdlg);
+ }
+ }
+ else { // creationSource->kdeDocButton must be checked
+ QString language = kdeDocWidget->languageButton->currentTag();
+ if (kdeDocWidget->spellCheckBox->isChecked())
+ dicFile = kdeDocWidget->ooDictURL->url();
+ map = WordList::parseKDEDoc (language, pdlg);
+ }
+
+ if (!dicFile.isEmpty() && !dicFile.isNull())
+ map = WordList::spellCheck (map, dicFile, pdlg);
+ pdlg->close();
+ delete pdlg;
+
+ int dictnumber = 0;
+ QString filename;
+ QString dictionaryFile;
+ do {
+ dictnumber++;
+ filename = QString("wordcompletion%1.dict").arg(dictnumber);
+ dictionaryFile = KApplication::kApplication()->dirs()->findResource("appdata", filename);
+ }
+ while (KStandardDirs::exists(dictionaryFile));
+
+ dictionaryFile = KApplication::kApplication()->dirs()->saveLocation ("appdata", "/") + filename;
+ if (WordList::saveWordList (map, dictionaryFile))
+ return filename;
+ else
+ return "";
+}
+
+QString DictionaryCreationWizard::name() {
+ if (creationSource->mergeButton->isChecked()) {
+ return i18n("Merge result");
+ }
+ else if (creationSource->emptyButton->isChecked()) {
+ return i18n("In the sense of a blank word list", "Empty list");
+ }
+ else if (creationSource->fileButton->isChecked()) {
+ return fileWidget->url->url();
+ }
+ else if (creationSource->directoryButton->isChecked()) {
+ return dirWidget->url->url();
+ }
+ else { // creationSource->kdeDocButton must be checked
+ return i18n("KDE Documentation");
+ }
+}
+
+QString DictionaryCreationWizard::language() {
+ if (creationSource->mergeButton->isChecked()) {
+ return mergeWidget->language();
+ }
+ else if (creationSource->emptyButton->isChecked()) {
+ if (KGlobal::locale())
+ return KGlobal::locale()->language();
+ else
+ return KLocale::defaultLanguage();
+ }
+ else if (creationSource->fileButton->isChecked()) {
+ return fileWidget->languageButton->currentTag();
+ }
+ else if (creationSource->directoryButton->isChecked()) {
+ return dirWidget->languageButton->currentTag();
+ }
+ else { // creationSource->kdeDocButton must be checked
+ return kdeDocWidget->languageButton->currentTag();
+ }
+}
+
+/***************************************************************************/
+
+MergeWidget::MergeWidget(KWizard *parent, const char *name,
+ QStringList dictionaryNames, QStringList dictionaryFiles,
+ QStringList dictionaryLanguages)
+: QScrollView (parent, name) {
+ dictionaries.setAutoDelete (false);
+ weights.setAutoDelete (false);
+
+ QWidget *contents = new QWidget(viewport());
+ addChild(contents);
+ QGridLayout *layout = new QGridLayout (contents);
+ setResizePolicy (QScrollView::AutoOneFit);
+ layout->setColStretch (0, 0);
+ layout->setColStretch (1, 1);
+
+ int row = 0;
+ QStringList::Iterator nIt = dictionaryNames.begin();
+ QStringList::Iterator fIt = dictionaryFiles.begin();
+ QStringList::Iterator lIt = dictionaryLanguages.begin();
+ for (; nIt != dictionaryNames.end(); ++nIt, ++fIt, ++lIt) {
+ QCheckBox *checkbox = new QCheckBox(*nIt, contents);
+ KIntNumInput *numInput = new KIntNumInput(contents);
+ layout->addWidget (checkbox, row, 0);
+ layout->addWidget (numInput, row, 1);
+
+ checkbox->setChecked (true);
+ numInput->setRange (1, 100, 10, true);
+ numInput->setValue (100);
+ connect (checkbox, SIGNAL (toggled(bool)), numInput, SLOT(setEnabled(bool)));
+
+ dictionaries.insert(*fIt, checkbox);
+ weights.insert(*fIt, numInput);
+ languages [*fIt] = *lIt;
+ row++;
+ }
+}
+
+MergeWidget::~MergeWidget() {
+}
+
+QMap <QString, int> MergeWidget::mergeParameters () {
+ QMap <QString, int> files;
+ QDictIterator<QCheckBox> it(dictionaries);
+ for (; it.current(); ++it) {
+ if (it.current()->isChecked()) {
+ QString name = it.currentKey();
+ QString dictionaryFile = KApplication::kApplication()->dirs()->findResource("appdata", name);
+ files[dictionaryFile] = weights[name]->value();
+ }
+ }
+
+ return files;
+}
+
+QString MergeWidget::language () {
+ QDictIterator<QCheckBox> it(dictionaries);
+ for (; it.current(); ++it) {
+ if (it.current()->isChecked()) {
+ return languages [it.currentKey()];
+ }
+ }
+
+ return QString::null;
+}
+
+/***************************************************************************/
+
+CompletionWizardWidget::CompletionWizardWidget (KWizard *parent, const char *name)
+ : KDEDocSourceUI (parent, name) {
+}
+
+CompletionWizardWidget::~CompletionWizardWidget() {
+}
+
+void CompletionWizardWidget::ok (KConfig *config) {
+ WordList::WordMap map;
+ KProgressDialog *pdlg = WordList::progressDialog();
+
+ QString language = languageButton->currentTag();
+ map = WordList::parseKDEDoc (language, pdlg);
+
+ if (spellCheckBox->isChecked())
+ map = WordList::spellCheck (map, ooDictURL->url(), pdlg);
+
+ pdlg->close();
+ delete pdlg;
+
+ QString filename;
+ QString dictionaryFile;
+
+ dictionaryFile = KApplication::kApplication()->dirs()->saveLocation ("appdata", "/") + "wordcompletion1.dict";
+ if (WordList::saveWordList (map, dictionaryFile)) {
+ config->setGroup("Dictionary 0");
+ config->writeEntry ("Filename", "wordcompletion1.dict");
+ config->writeEntry ("Name", i18n("Default"));
+ config->writeEntry ("Language", language);
+ config->sync();
+ }
+}
+
+#include "dictionarycreationwizard.moc"
diff --git a/kmouth/wordcompletion/dictionarycreationwizard.h b/kmouth/wordcompletion/dictionarycreationwizard.h
new file mode 100644
index 0000000..18928e1
--- /dev/null
+++ b/kmouth/wordcompletion/dictionarycreationwizard.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+ dictionarycreationwizard.h - description
+ -------------------
+ begin : Tue Apr 29 2003
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// $Id$
+
+#ifndef DICTIONARYCREATIONWIZARD_H
+#define DICTIONARYCREATIONWIZARD_H
+
+#include <qptrlist.h>
+#include <qmap.h>
+
+#include <kwizard.h>
+#include <knuminput.h>
+#include "kdedocsourceui.h"
+
+class CreationSourceUI;
+class CompletionWizardWidget;
+class CreationSourceDetailsUI;
+class KDEDocSourceUI;
+class QTextCodec;
+class QComboBox;
+class MergeWidget;
+
+/**
+ * This class represents a wizard that is used in order to gather all
+ * necessary information for creating a new dictionary for the word
+ * completion.
+ */
+class DictionaryCreationWizard : public KWizard {
+ Q_OBJECT
+public:
+ DictionaryCreationWizard (QWidget *parent, const char *name,
+ QStringList dictionaryNames,
+ QStringList dictionaryFiles,
+ QStringList dictionaryLanguages);
+ ~DictionaryCreationWizard();
+
+ QString createDictionary();
+ QString name();
+ QString language();
+
+private slots:
+ void calculateAppropriate (bool);
+
+private:
+ void buildCodecList ();
+ void buildCodecCombo (QComboBox *combo);
+
+ CreationSourceUI *creationSource;
+ CreationSourceDetailsUI *fileWidget;
+ CreationSourceDetailsUI *dirWidget;
+ KDEDocSourceUI *kdeDocWidget;
+ MergeWidget *mergeWidget;
+
+ QPtrList<QTextCodec> *codecList;
+};
+
+/**
+ * This class represents a widget for creating an initial dictionary from the
+ * KDE documentation.
+ * @author Gunnar Schmi Dt
+ */
+class MergeWidget : public QScrollView {
+ Q_OBJECT
+public:
+ MergeWidget(KWizard *parent, const char *name,
+ QStringList dictionaryNames,
+ QStringList dictionaryFiles,
+ QStringList dictionaryLanguages);
+ ~MergeWidget();
+
+ QMap <QString, int> mergeParameters ();
+ QString language ();
+
+private:
+ QDict<QCheckBox> dictionaries;
+ QDict<KIntNumInput> weights;
+ QMap<QString,QString> languages;
+};
+
+/**
+ * This class represents a widget for creating an initial dictionary from the
+ * KDE documentation.
+ * @author Gunnar Schmi Dt
+ */
+class CompletionWizardWidget : public KDEDocSourceUI {
+ Q_OBJECT
+ friend class ConfigWizard;
+public:
+ CompletionWizardWidget(KWizard *parent, const char *name);
+ ~CompletionWizardWidget();
+
+ void ok (KConfig *config);
+};
+
+#endif
diff --git a/kmouth/wordcompletion/kdedocsourceui.ui b/kmouth/wordcompletion/kdedocsourceui.ui
new file mode 100644
index 0000000..21ce02a
--- /dev/null
+++ b/kmouth/wordcompletion/kdedocsourceui.ui
@@ -0,0 +1,101 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>KDEDocSourceUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KDEDocSourceUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>272</width>
+ <height>100</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spellCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Compare to OpenOffice.org dictionary:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If you select this check box the words from the KDE documentation are spell-checked before they are inserted into the new dictionary.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="2" column="1">
+ <property name="name">
+ <cstring>ooDictURL</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this input field you select the OpenOffice.org directory that will be used to spellcheck the words of the new dictionary.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Language:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this combo box you select which of the installed languages is used for creating the new dictionary. KMouth will only parse documentation files of this language.</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>spellCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>ooDictURL</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">klanguagebutton.h</include>
+ <include location="local" impldecl="in implementation">klanguagebuttonhelper.h</include>
+ <include location="local" impldecl="in implementation">kdedocsourceui.ui.h</include>
+</includes>
+<forwards>
+ <forward>class KLanguageButton</forward>
+</forwards>
+<variables>
+ <variable access="public">KLanguageButton *languageButton;</variable>
+</variables>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kmouth/wordcompletion/kdedocsourceui.ui.h b/kmouth/wordcompletion/kdedocsourceui.ui.h
new file mode 100644
index 0000000..4c42b32
--- /dev/null
+++ b/kmouth/wordcompletion/kdedocsourceui.ui.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void KDEDocSourceUI::init() {
+ languageButton = new KLanguageButton (this, "languageButton");
+ KDEDocSourceUILayout->addWidget (languageButton, 0, 1);
+ languageLabel->setBuddy (languageButton);
+ QWhatsThis::add (languageButton, i18n("With this combo box you select which of the installed languages is used for creating the new dictionary. KMouth will only parse documentation files of this language."));
+
+ loadLanguageList(languageButton);
+
+ ooDictURL->setFilter ("*.dic");
+}
diff --git a/kmouth/wordcompletion/klanguagebutton.cpp b/kmouth/wordcompletion/klanguagebutton.cpp
new file mode 100644
index 0000000..72182d4
--- /dev/null
+++ b/kmouth/wordcompletion/klanguagebutton.cpp
@@ -0,0 +1,238 @@
+/*
+ * klanguagebutton.cpp - Adds some methods for inserting languages.
+ *
+ * Copyright (c) 1999-2000 Hans Petter Bieker <bieker@kde.org>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.trolltech.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#define INCLUDE_MENUITEM_DEF
+#include <qpopupmenu.h>
+#include <kstandarddirs.h>
+
+#include "klanguagebutton.h"
+
+#include <kdebug.h>
+
+
+static inline void checkInsertPos( QPopupMenu *popup, const QString & str,
+ int &index )
+{
+ if ( index == -2 )
+ index = popup->count();
+ if ( index != -1 )
+ return;
+
+ int a = 0;
+ int b = popup->count();
+ while ( a <= b )
+ {
+ int w = ( a + b ) / 2;
+
+ int id = popup->idAt( w );
+ int j = str.localeAwareCompare( popup->text( id ) );
+
+ if ( j > 0 )
+ a = w + 1;
+ else
+ b = w - 1;
+ }
+
+ index = a; // it doesn't really matter ... a == b here.
+}
+
+static inline QPopupMenu * checkInsertIndex( QPopupMenu *popup,
+ const QStringList *tags, const QString &submenu )
+{
+ int pos = tags->findIndex( submenu );
+
+ QPopupMenu *pi = 0;
+ if ( pos != -1 )
+ {
+ QMenuItem *p = popup->findItem( pos );
+ pi = p ? p->popup() : 0;
+ }
+ if ( !pi )
+ pi = popup;
+
+ return pi;
+}
+
+
+KLanguageButton::~KLanguageButton()
+{
+ delete m_tags;
+}
+
+KLanguageButton::KLanguageButton( QWidget * parent, const char *name )
+: QPushButton( parent, name ),
+ m_popup( 0 ),
+ m_oldPopup( 0 )
+{
+ m_tags = new QStringList;
+
+ clear();
+}
+
+void KLanguageButton::insertItem( const QIconSet& icon, const QString &text,
+ const QString &tag, const QString &submenu, int index )
+{
+ QPopupMenu *pi = checkInsertIndex( m_popup, m_tags, submenu );
+ checkInsertPos( pi, text, index );
+ pi->insertItem( icon, text, count(), index );
+ m_tags->append( tag );
+}
+
+void KLanguageButton::insertItem( const QString &text, const QString &tag,
+ const QString &submenu, int index )
+{
+ QPopupMenu *pi = checkInsertIndex( m_popup, m_tags, submenu );
+ checkInsertPos( pi, text, index );
+ pi->insertItem( text, count(), index );
+ m_tags->append( tag );
+}
+
+void KLanguageButton::insertSeparator( const QString &submenu, int index )
+{
+ QPopupMenu *pi = checkInsertIndex( m_popup, m_tags, submenu );
+ pi->insertSeparator( index );
+ m_tags->append( QString::null );
+}
+
+void KLanguageButton::insertSubmenu( const QString &text, const QString &tag,
+ const QString &submenu, int index )
+{
+ QPopupMenu *pi = checkInsertIndex( m_popup, m_tags, submenu );
+ QPopupMenu *p = new QPopupMenu( pi );
+ checkInsertPos( pi, text, index );
+ pi->insertItem( text, p, count(), index );
+ m_tags->append( tag );
+ connect( p, SIGNAL( activated( int ) ),
+ SLOT( slotActivated( int ) ) );
+ connect( p, SIGNAL( highlighted( int ) ), this,
+ SIGNAL( highlighted( int ) ) );
+}
+
+void KLanguageButton::insertLanguage( const QString& path, const QString& name,
+ const QString& sub, const QString &submenu, int index )
+{
+ QString output = name + QString::fromLatin1( " (" ) + path +
+ QString::fromLatin1( ")" );
+#if 0
+ // Nooooo ! Country != language
+ QPixmap flag( locate( "locale", sub + path +
+ QString::fromLatin1( "/flag.png" ) ) );
+#endif
+ insertItem( output, path, submenu, index );
+}
+
+void KLanguageButton::slotActivated( int index )
+{
+ // Update caption and iconset:
+ if ( m_current == index )
+ return;
+
+ setCurrentItem( index );
+
+ // Forward event from popup menu as if it was emitted from this widget:
+ emit activated( index );
+}
+
+int KLanguageButton::count() const
+{
+ return m_tags->count();
+}
+
+void KLanguageButton::clear()
+{
+ m_tags->clear();
+
+ delete m_oldPopup;
+ m_oldPopup = m_popup;
+ m_popup = new QPopupMenu( this );
+
+ setPopup( m_popup );
+
+ connect( m_popup, SIGNAL( activated( int ) ),
+ SLOT( slotActivated( int ) ) );
+ connect( m_popup, SIGNAL( highlighted( int ) ),
+ SIGNAL( highlighted( int ) ) );
+
+ setText( QString::null );
+ setIconSet( QIconSet() );
+}
+
+/*void KLanguageButton::changeLanguage( const QString& name, int i )
+{
+ if ( i < 0 || i >= count() )
+ return;
+ QString output = name + QString::fromLatin1( " (" ) + tag( i ) +
+ QString::fromLatin1( ")" );
+ changeItem( output, i );
+}*/
+
+bool KLanguageButton::containsTag( const QString &str ) const
+{
+ return m_tags->contains( str ) > 0;
+}
+
+QString KLanguageButton::currentTag() const
+{
+ return *m_tags->at( currentItem() );
+}
+
+QString KLanguageButton::tag( int i ) const
+{
+ if ( i < 0 || i >= count() )
+ {
+ kdDebug() << "KLanguageButton::tag(), unknown tag " << i << endl;
+ return QString::null;
+ }
+ return *m_tags->at( i );
+}
+
+int KLanguageButton::currentItem() const
+{
+ return m_current;
+}
+
+void KLanguageButton::setCurrentItem( int i )
+{
+ if ( i < 0 || i >= count() )
+ return;
+ m_current = i;
+
+ setText( m_popup->text( m_current ) );
+ QIconSet *icon = m_popup->iconSet( m_current );
+ if( icon )
+ setIconSet( *icon );
+ else
+ setIconSet( QPixmap() );
+}
+
+void KLanguageButton::setCurrentItem( const QString &code )
+{
+ int i = m_tags->findIndex( code );
+ if ( code.isNull() )
+ i = 0;
+ if ( i != -1 )
+ setCurrentItem( i );
+}
+
+#include "klanguagebutton.moc"
diff --git a/kmouth/wordcompletion/klanguagebutton.h b/kmouth/wordcompletion/klanguagebutton.h
new file mode 100644
index 0000000..ee1d58f
--- /dev/null
+++ b/kmouth/wordcompletion/klanguagebutton.h
@@ -0,0 +1,93 @@
+/*
+ * klangbutton.h - Button with language selection drop down menu.
+ * Derived from the KLangCombo class by Hans Petter Bieker.
+ *
+ * Copyright (c) 1999-2000 Hans Petter Bieker <bieker@kde.org>
+ * (c) 2001 Martijn Klingens <mklingens@yahoo.com>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef __KLANGBUTTON_H__
+#define __KLANGBUTTON_H__
+
+#include "kpushbutton.h"
+
+/*
+ * Extended QPushButton that shows a menu with submenu for language selection.
+ * Essentially just a combo box with a 2-D dataset, but using a real
+ * QComboBox will produce ugly results.
+ *
+ * Combined version of KTagCombo and KLanguageCombo but using a QPushButton
+ * instead.
+ */
+class KLanguageButton : public QPushButton
+{
+ Q_OBJECT
+
+public:
+ KLanguageButton(QWidget *parent=0, const char *name=0);
+ ~KLanguageButton();
+
+ void insertItem( const QIconSet& icon, const QString &text,
+ const QString &tag, const QString &submenu = QString::null,
+ int index = -1 );
+ void insertItem( const QString &text, const QString &tag,
+ const QString &submenu = QString::null, int index = -1 );
+ void insertSeparator( const QString &submenu = QString::null,
+ int index = -1 );
+ void insertSubmenu( const QString &text, const QString &tag,
+ const QString &submenu = QString::null, int index = -1);
+
+ int count() const;
+ void clear();
+
+ void insertLanguage( const QString& path, const QString& name,
+ const QString& sub = QString::null,
+ const QString &submenu = QString::null, int index = -1);
+
+ /*
+ * Tag of the selected item
+ */
+ QString currentTag() const;
+ QString tag( int i ) const;
+ bool containsTag( const QString &str ) const;
+
+ /*
+ * Set the current item
+ */
+ int currentItem() const;
+ void setCurrentItem( int i );
+ void setCurrentItem( const QString &code );
+
+signals:
+ void activated( int index );
+ void highlighted( int index );
+
+private slots:
+ void slotActivated( int );
+
+private:
+ // work space for the new class
+ QStringList *m_tags;
+ QPopupMenu *m_popup, *m_oldPopup;
+ int m_current;
+};
+
+#endif
diff --git a/kmouth/wordcompletion/klanguagebuttonhelper.cpp b/kmouth/wordcompletion/klanguagebuttonhelper.cpp
new file mode 100644
index 0000000..918553e
--- /dev/null
+++ b/kmouth/wordcompletion/klanguagebuttonhelper.cpp
@@ -0,0 +1,64 @@
+/*
+ * klanguagebuttonhelper.cpp - Methods that help filling the KLanguageButton with data.
+ *
+ * Copyright (c) 2003 Gunnar Schmi Dt <gunnar@schmi-dt.de>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.trolltech.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "klanguagebuttonhelper.h"
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <ksimpleconfig.h>
+#include "klanguagebutton.h"
+
+QString languageName (QString languageCode) {
+ QString filename = KGlobal::dirs()->findResource("locale",
+ languageCode + QString::fromLatin1("/entry.desktop"));
+
+ KSimpleConfig entry(filename);
+ entry.setGroup(QString::fromLatin1("KCM Locale"));
+ return entry.readEntry(QString::fromLatin1("Name"), i18n("without name"));
+}
+
+void loadLanguageList(KLanguageButton *combo)
+// This function was taken from kdebase/kcontrol/kdm/kdm-appear.cpp
+{
+ QStringList langlist = KGlobal::dirs()->findAllResources("locale",
+ QString::fromLatin1("*/entry.desktop"));
+ langlist.sort();
+ for ( QStringList::ConstIterator it = langlist.begin();
+ it != langlist.end(); ++it )
+ {
+ QString fpath = (*it).left((*it).length() - 14);
+ int index = fpath.findRev('/');
+ QString nid = fpath.mid(index + 1);
+
+ KSimpleConfig entry(*it);
+ entry.setGroup(QString::fromLatin1("KCM Locale"));
+ QString name = entry.readEntry(QString::fromLatin1("Name"), i18n("without name"));
+ combo->insertLanguage(nid, name, QString::fromLatin1("l10n/"), QString::null);
+ }
+
+ if (KGlobal::locale())
+ combo->setCurrentItem (KGlobal::locale()->language());
+ else
+ combo->setCurrentItem (KLocale::defaultLanguage());
+}
diff --git a/kmouth/wordcompletion/klanguagebuttonhelper.h b/kmouth/wordcompletion/klanguagebuttonhelper.h
new file mode 100644
index 0000000..9bee5f7
--- /dev/null
+++ b/kmouth/wordcompletion/klanguagebuttonhelper.h
@@ -0,0 +1,28 @@
+/*
+ * klanguagebuttonhelper.h - Methods that help filling the KLanguageButton with data.
+ *
+ * Copyright (c) 2003 Gunnar Schmi Dt <gunnar@schmi-dt.de>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+class QString;
+class KLanguageButton;
+
+QString languageName (QString languageCode);
+void loadLanguageList(KLanguageButton *combo);
diff --git a/kmouth/wordcompletion/wordcompletion.cpp b/kmouth/wordcompletion/wordcompletion.cpp
new file mode 100644
index 0000000..d4ae651
--- /dev/null
+++ b/kmouth/wordcompletion/wordcompletion.cpp
@@ -0,0 +1,224 @@
+#include <qregexp.h>
+#include <qfile.h>
+
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <kconfig.h>
+
+#include "wordcompletion.h"
+
+class WordCompletion::WordCompletionPrivate {
+friend class WordCompletion;
+private:
+ typedef QMap<QString,int> WordMap;
+ struct DictionaryDetails {
+ QString filename;
+ QString language;
+ };
+
+ QString lastText;
+ QMap<QString,int> map;
+ QMap<QString,int> addedWords;
+ QMap<QString,DictionaryDetails> dictDetails;
+ QStringList dictionaries;
+ QString current;
+ bool blockCurrentListSignal;
+ bool wordsToSave;
+};
+
+WordCompletion::WordCompletion() : KCompletion () {
+ d = new WordCompletionPrivate();
+ d->blockCurrentListSignal = false;
+ d->wordsToSave = false;
+ configure ();
+}
+
+WordCompletion::~WordCompletion() {
+ save ();
+ delete d;
+}
+
+typedef QPair<int,QString> Match;
+typedef QValueList<Match> MatchList;
+
+QString WordCompletion::makeCompletion(const QString &text) {
+ if (d->lastText != text) {
+ d->lastText = text;
+ KCompletion::clear();
+
+ int border = text.findRev(QRegExp("\\W"));
+ QString suffix = text.right (text.length() - border - 1).lower();
+ QString prefix = text.left (border + 1);
+
+ if (suffix.length() > 0) {
+ MatchList matches;
+ QMap<QString,int>::ConstIterator it;
+ for (it = d->map.begin(); it != d->map.end(); ++it)
+ if (it.key().startsWith(suffix))
+ matches += Match (-it.data(), it.key());
+ qHeapSort(matches);
+
+ MatchList::ConstIterator iter = matches.begin();
+ for (int count = 0; (iter != matches.end()) && (count < 10); ++iter, ++count) {
+ int length = (*iter).second.length() + prefix.length() - text.length();
+ KCompletion::addItem(text + (*iter).second.right(length), -(*iter).first);
+ }
+ }
+ }
+
+ // call the KCompletion::makeCompletion(...) method
+ return KCompletion::makeCompletion (text);
+}
+
+QStringList WordCompletion::wordLists() {
+ return d->dictionaries;
+}
+
+QStringList WordCompletion::wordLists(const QString &language) {
+ QStringList result;
+ for (QStringList::Iterator it = d->dictionaries.begin();
+ it != d->dictionaries.end(); ++it)
+ if (d->dictDetails[*it].language == language)
+ result += *it;
+ return result;
+}
+
+QString WordCompletion::languageOfWordList(const QString &wordlist) {
+ if (d->dictDetails.contains(wordlist))
+ return d->dictDetails[wordlist].language;
+ else
+ return QString::null;
+}
+
+QString WordCompletion::currentWordList() {
+ return d->current;
+}
+
+bool WordCompletion::isConfigured() {
+ KConfig *config = new KConfig("kmouthrc");
+ bool result = config->hasGroup("Dictionary 0");
+ delete config;
+
+ return result;
+}
+
+void WordCompletion::configure() {
+ if (d->wordsToSave)
+ save ();
+ d->wordsToSave = false;
+
+ d->dictionaries.clear();
+ d->dictDetails.clear();
+
+ KConfig *config = new KConfig("kmouthrc");
+ QStringList groups = config->groupList();
+ for (QStringList::Iterator it = groups.begin(); it != groups.end(); ++it)
+ if ((*it).startsWith ("Dictionary ")) {
+ config->setGroup(*it);
+ WordCompletionPrivate::DictionaryDetails details;
+ details.filename = config->readEntry("Filename");
+ details.language = config->readEntry("Language");
+ QString name = config->readEntry("Name");
+ d->dictDetails[name] = details;
+ d->dictionaries += name;
+ }
+ delete config;
+
+ d->blockCurrentListSignal = true;
+ setWordList(d->current);
+ d->blockCurrentListSignal = false;
+ emit wordListsChanged (wordLists());
+ emit currentListChanged (d->current);
+}
+
+bool WordCompletion::setWordList(const QString &wordlist) {
+ if (d->wordsToSave)
+ save ();
+ d->wordsToSave = false;
+
+ d->map.clear();
+ bool result = d->dictDetails.contains (wordlist);
+ if (result)
+ d->current = wordlist;
+ else
+ d->current = d->dictionaries[0];
+
+ QString filename = d->dictDetails[d->current].filename;
+ QString dictionaryFile = KApplication::kApplication()->dirs()->findResource("appdata", filename);
+ QFile file(dictionaryFile);
+ if (file.exists() && file.open(IO_ReadOnly)) {
+ QTextStream stream(&file);
+ stream.setEncoding (QTextStream::UnicodeUTF8);
+ if (!stream.atEnd()) {
+ if (stream.readLine() == "WPDictFile") {
+ while (!stream.atEnd()) {
+ QString s = stream.readLine();
+ if (!(s.isNull() || s.isEmpty())) {
+ QStringList list = QStringList::split("\t", s);
+ bool ok;
+ int weight = list[1].toInt(&ok);
+ if (ok && (weight > 0))
+ d->map [list[0]] = weight;
+ }
+ }
+ }
+ }
+ file.close();
+ }
+ if (!d->blockCurrentListSignal)
+ emit currentListChanged (d->current);
+ d->lastText = "";
+ d->wordsToSave = false;
+ return result;
+}
+
+void WordCompletion::addSentence (const QString &sentence) {
+ QStringList words = QStringList::split(QRegExp("\\W"), sentence);
+
+ QStringList::ConstIterator it;
+ for (it = words.begin(); it != words.end(); ++it) {
+ if (!(*it).contains(QRegExp("\\d|_"))) {
+ QString key = (*it).lower();
+ if (d->map.contains(key))
+ d->map[key] += 1;
+ else
+ d->map[key] = 1;
+ if (d->addedWords.contains(key))
+ d->addedWords[key] += 1;
+ else
+ d->addedWords[key] = 1;
+ }
+ }
+ d->wordsToSave = true;
+}
+
+void WordCompletion::save () {
+ if (d->wordsToSave) {
+ QString filename = d->dictDetails[d->current].filename;
+ QString dictionaryFile = KApplication::kApplication()->dirs()->findResource("appdata", filename);
+ QFile file(dictionaryFile);
+ if (!file.exists())
+ return;
+ if (!file.open(IO_WriteOnly))
+ return;
+
+ QTextStream stream(&file);
+ stream.setEncoding (QTextStream::UnicodeUTF8);
+
+ stream << "WPDictFile\n";
+ QMap<QString,int>::ConstIterator it;
+ for (it = d->map.begin(); it != d->map.end(); ++it) {
+ if (d->addedWords.contains(it.key())) {
+ stream << it.key() << "\t" << d->addedWords[it.key()] << "\t1\n";
+ stream << it.key() << "\t" << it.data() - d->addedWords[it.key()] << "\t2\n";
+ }
+ else
+ stream << it.key() << "\t" << it.data() << "\t2\n";
+ }
+ file.close();
+ d->wordsToSave = false;
+ }
+}
+
+#include "wordcompletion.moc"
+
diff --git a/kmouth/wordcompletion/wordcompletion.h b/kmouth/wordcompletion/wordcompletion.h
new file mode 100644
index 0000000..f0cb812
--- /dev/null
+++ b/kmouth/wordcompletion/wordcompletion.h
@@ -0,0 +1,77 @@
+#ifndef WORDCOMPLETION_H
+#define WORDCOMPLETION_H
+
+#include <kcompletion.h>
+
+/**
+ * This class does completion based on a dictionary of words.
+ */
+class WordCompletion : public KCompletion {
+ friend class WordListWidget;
+ Q_OBJECT
+public:
+ WordCompletion();
+ virtual ~WordCompletion();
+
+ /**
+ * Returns the names for the available word lists
+ */
+ QStringList wordLists();
+
+ /**
+ * Returns the names for those word lists that contain
+ * words of a given language.
+ */
+ QStringList wordLists(const QString &language);
+
+ /**
+ * Returns the language of a given word list.
+ */
+ QString languageOfWordList(const QString &wordlist);
+
+ /**
+ * Returns the name of the currently active word list.
+ */
+ QString currentWordList();
+
+ /**
+ * Finds completions to the given text.
+ */
+ virtual QString makeCompletion(const QString&);
+
+ static bool isConfigured();
+
+ /**
+ * Adds the words from the given sentence to the list of words.
+ */
+ void addSentence (const QString &sentence);
+
+public slots:
+ /**
+ * Re-reads the configuration.
+ */
+ void configure();
+
+ /**
+ * Specify which word list gets used for the actual word completion.
+ * If there is no word list with the given name the first configured
+ * list gets used.
+ * The method returns true if the specified word list was found.
+ */
+ bool setWordList(const QString &wordlist);
+
+ /**
+ * Saves the added words to disk.
+ */
+ void save ();
+
+signals:
+ void wordListsChanged (const QStringList &wordLists);
+ void currentListChanged (const QString &wordList);
+
+private:
+ class WordCompletionPrivate;
+ WordCompletionPrivate *d;
+};
+
+#endif // KURLCOMPLETION_H
diff --git a/kmouth/wordcompletion/wordcompletionui.ui b/kmouth/wordcompletion/wordcompletionui.ui
new file mode 100644
index 0000000..8036272
--- /dev/null
+++ b/kmouth/wordcompletion/wordcompletionui.ui
@@ -0,0 +1,293 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>WordCompletionUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>WordCompletionUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>552</width>
+ <height>252</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Add D&amp;ictionary...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this button you can add a new dictionary to the list of available dictionaries.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>deleteButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Delete Dictionary</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this button you delete the selected dictionary.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>moveUpButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Move &amp;Up</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this button you move the selected dictionary up.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>moveDownButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Move Down</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this button you move the selected dictionary down.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>exportButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Export Dictionary...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this button you export the selected dictionary to a file.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>240</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Dictionary</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Language</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>dictionaryList</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This list contains all available dictionaries for the word completion. KMouth will display a combo box next to the edit field in the main window if this list contains more than one dictionary. You can use this combo box in order to select the dictionary that actually gets used for the word completion.</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>selectedDictionaryDetails</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>&amp;Selected Dictionary</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Language:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this combo box you select the language associated with the selected dictionary.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>dictionaryNameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>dictionaryName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this input field you specify the name of the selected dictionary.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>dictionaryName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>With this input field you specify the name of the selected dictionary.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>dictionaryList</tabstop>
+ <tabstop>addButton</tabstop>
+ <tabstop>deleteButton</tabstop>
+ <tabstop>moveUpButton</tabstop>
+ <tabstop>moveDownButton</tabstop>
+ <tabstop>exportButton</tabstop>
+ <tabstop>selectedDictionaryDetails</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in implementation">kinputdialog.h</include>
+ <include location="local" impldecl="in implementation">klanguagebutton.h</include>
+ <include location="local" impldecl="in implementation">klanguagebuttonhelper.h</include>
+ <include location="local" impldecl="in implementation">wordcompletionui.ui.h</include>
+</includes>
+<forwards>
+ <forward>class KLanguageButton</forward>
+</forwards>
+<variables>
+ <variable access="public">KLanguageButton *languageButton;</variable>
+</variables>
+<slots>
+ <slot access="protected" specifier="non virtual">languageButton_activated( int index )</slot>
+</slots>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kinputdialog.h</includehint>
+</includehints>
+</UI>
diff --git a/kmouth/wordcompletion/wordcompletionui.ui.h b/kmouth/wordcompletion/wordcompletionui.ui.h
new file mode 100644
index 0000000..96878da
--- /dev/null
+++ b/kmouth/wordcompletion/wordcompletionui.ui.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void WordCompletionUI::init() {
+ languageButton = new KLanguageButton (selectedDictionaryDetails, "languageButton");
+ selectedDictionaryDetailsLayout->addWidget (languageButton, 1, 1);
+ languageLabel->setBuddy (languageButton);
+ QWhatsThis::add (languageButton, i18n("With this combo box you select the language associated with the selected dictionary."));
+
+ loadLanguageList(languageButton);
+ languageButton->insertLanguage("??", i18n("Other"), QString::fromLatin1("l10n/"), QString::null);
+
+ connect (languageButton, SIGNAL(activated(int)), this, SLOT(languageButton_activated(int)));
+}
+
+void WordCompletionUI::languageButton_activated (int) {
+ if (languageButton->currentTag() == "??") {
+ QString customLanguage = KInputDialog::getText(i18n("Create Custom Language"), i18n("Please enter the code for the custom language:"));
+
+ if (languageButton->containsTag(customLanguage)) {
+ languageButton->setCurrentItem(customLanguage);
+ }
+ else {
+ languageButton->insertLanguage(customLanguage, i18n("without name"), QString::fromLatin1("l10n/"), QString::null);
+ languageButton->setCurrentItem(customLanguage);
+ }
+ }
+}
diff --git a/kmouth/wordcompletion/wordcompletionwidget.cpp b/kmouth/wordcompletion/wordcompletionwidget.cpp
new file mode 100644
index 0000000..e5eab23
--- /dev/null
+++ b/kmouth/wordcompletion/wordcompletionwidget.cpp
@@ -0,0 +1,325 @@
+/***************************************************************************
+ wordcompletionwidget.cpp - description
+ -------------------
+ begin : Tue Apr 29 2003
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qlineedit.h>
+
+#include <klistview.h>
+#include <klineedit.h>
+#include <kurlrequester.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kconfig.h>
+#include <ksimpleconfig.h>
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+
+#include "dictionarycreationwizard.h"
+#include "wordcompletionwidget.h"
+#include "wordcompletion.h"
+#include "klanguagebutton.h"
+
+class DictionaryListItem : public KListViewItem {
+public:
+ DictionaryListItem (QListView *parent, QString filename, QString name, QString language, QString languageCode)
+ : KListViewItem (parent, name) {
+ setFilename (filename);
+ setLanguage (language, languageCode);
+ };
+ DictionaryListItem (QListView *parent, QString filename, QString name, QString languageCode)
+ : KListViewItem (parent, name) {
+ setFilename (filename);
+ setLanguage (languageCode);
+ };
+ DictionaryListItem (QListView *parent, QListViewItem *after, QString filename, QString name, QString languageCode)
+ : KListViewItem (parent, after, name) {
+ setFilename (filename);
+ setLanguage (languageCode);
+ };
+ ~DictionaryListItem () {
+ };
+
+ QString filename() {
+ return myFilename;
+ }
+
+ QString languageCode() {
+ return myLanguageCode;
+ }
+
+ void setFilename(QString filename) {
+ myFilename = filename;
+ }
+
+ void setLanguage (QString languageCode) {
+ QString filename = KGlobal::dirs()->findResource("locale",
+ languageCode + QString::fromLatin1("/entry.desktop"));
+
+ KSimpleConfig entry(filename);
+ entry.setGroup(QString::fromLatin1("KCM Locale"));
+ QString name = entry.readEntry(QString::fromLatin1("Name"), i18n("without name"));
+ setLanguage (name + " (" + languageCode + ")", languageCode);
+ }
+
+ void setLanguage (QString name, QString languageCode) {
+ myLanguageCode = languageCode;
+ setText (1, name);
+ }
+
+private:
+ QString myFilename;
+ QString myLanguageCode;
+};
+
+/***************************************************************************/
+
+WordCompletionWidget::WordCompletionWidget(QWidget *parent, const char *name) : WordCompletionUI (parent, name) {
+ dictionaryList->setSorting (-1); // no sorted list
+
+ // Connect the signals from hte KCMKTTSDWidget to this class
+ connect (addButton, SIGNAL (clicked()), this, SLOT(addDictionary()) );
+ connect (deleteButton, SIGNAL (clicked()), this, SLOT (deleteDictionary()) );
+ connect (moveUpButton, SIGNAL (clicked()), this, SLOT (moveUp()) );
+ connect (moveDownButton, SIGNAL (clicked()), this, SLOT (moveDown()) );
+ connect (exportButton, SIGNAL (clicked()), this, SLOT (exportDictionary()) );
+
+ connect (dictionaryList, SIGNAL (selectionChanged()), this, SLOT (selectionChanged()) );
+ connect (dictionaryName, SIGNAL (textChanged (const QString &)), this, SLOT (nameChanged (const QString &)) );
+ connect (languageButton, SIGNAL (activated (int)), this, SLOT (languageSelected(int)) );
+
+ // Object for the KCMKTTSD configuration
+ config = new KConfig("kmouthrc");
+
+ // Load the configuration from the file
+ load();
+}
+
+/**
+ * Destructor
+ */
+WordCompletionWidget::~WordCompletionWidget() {
+ delete config;
+}
+
+/***************************************************************************/
+
+void WordCompletionWidget::load() {
+ dictionaryList->clear();
+
+ // Set the group general for the configuration of kttsd itself (no plug ins)
+ QStringList groups = config->groupList();
+ DictionaryListItem *last = 0;
+ for (QStringList::Iterator it = groups.begin(); it != groups.end(); ++it)
+ if ((*it).startsWith ("Dictionary ")) {
+ config->setGroup(*it);
+ QString languageTag = config->readEntry("Language");
+ last = new DictionaryListItem (dictionaryList, last,
+ config->readEntry("Filename"),
+ config->readEntry("Name"),
+ languageTag);
+ if (!languageButton->containsTag(languageTag))
+ languageButton->insertLanguage(languageTag, i18n("without name"), QString::fromLatin1("l10n/"), QString::null);
+ }
+
+ // Clean up disc space
+ for (QStringList::Iterator it = newDictionaryFiles.begin(); it != newDictionaryFiles.end(); ++it) {
+ QString filename = KGlobal::dirs()->findResource ("appdata", *it);
+ if (!filename.isEmpty() && !filename.isNull())
+ QFile::remove (filename);
+ }
+ newDictionaryFiles.clear();
+}
+
+void WordCompletionWidget::save() {
+ QStringList groups = config->groupList();
+ for (QStringList::Iterator it = groups.begin(); it != groups.end(); ++it)
+ if ((*it).startsWith ("Dictionary "))
+ config->deleteGroup (*it);
+
+ int number = 0;
+ QListViewItemIterator it(dictionaryList);
+ while (it.current()) {
+ DictionaryListItem *item = dynamic_cast<DictionaryListItem*>(it.current());
+ if (item != 0) {
+ config->setGroup(QString("Dictionary %1").arg(number));
+ config->writeEntry ("Filename", item->filename());
+ config->writeEntry ("Name", item->text (0));
+ config->writeEntry ("Language", item->languageCode());
+ number++;
+ }
+ ++it;
+ }
+ config->sync();
+
+ // Clean up disc space
+ for (QStringList::Iterator it = removedDictionaryFiles.begin(); it != removedDictionaryFiles.end(); ++it) {
+ QString filename = KGlobal::dirs()->findResource ("appdata", *it);
+ if (!filename.isEmpty() && !filename.isNull())
+ QFile::remove (filename);
+ }
+ removedDictionaryFiles.clear();
+}
+
+/***************************************************************************/
+
+void WordCompletionWidget::addDictionary() {
+ QStringList dictionaryNames;
+ QStringList dictionaryFiles;
+ QStringList dictionaryLanguages;
+ QListViewItemIterator it(dictionaryList);
+ while (it.current()) {
+ DictionaryListItem *item = dynamic_cast<DictionaryListItem*>(it.current());
+ if (item != 0) {
+ dictionaryNames += item->text (0);
+ dictionaryFiles += item->filename();
+ dictionaryLanguages += item->languageCode();
+ }
+ ++it;
+ }
+ DictionaryCreationWizard *wizard = new DictionaryCreationWizard (this, "Dictionary creation wizard", dictionaryNames, dictionaryFiles, dictionaryLanguages);
+ if (wizard->exec() == QDialog::Accepted) {
+ QString filename = wizard->createDictionary();
+ newDictionaryFiles += filename;
+ QString languageTag = wizard->language();
+ if (!languageButton->containsTag(languageTag)) {
+ languageButton->insertLanguage(languageTag, i18n("without name"), QString::fromLatin1("l10n/"), QString::null);
+ }
+ KListViewItem *item = new DictionaryListItem (dictionaryList,
+ filename, wizard->name(), languageTag);
+ dictionaryList->setSelected(item, true);
+ }
+ delete wizard;
+}
+
+void WordCompletionWidget::deleteDictionary() {
+ DictionaryListItem *item = dynamic_cast<DictionaryListItem*>(dictionaryList->selectedItem ());
+
+ if (item != 0) {
+ removedDictionaryFiles += item->filename();
+ delete item;
+ }
+}
+
+void WordCompletionWidget::moveUp() {
+ QListViewItem *item = dictionaryList->selectedItem ();
+
+ if (item != 0) {
+ QListViewItem *above = item->itemAbove();
+
+ if (above != 0) {
+ above->moveItem (item);
+ }
+ }
+}
+
+void WordCompletionWidget::moveDown() {
+ QListViewItem *item = dictionaryList->selectedItem ();
+
+ if (item != 0) {
+ QListViewItem *next = item->itemBelow();
+
+ if (next != 0) {
+ item->moveItem (next);
+ }
+ }
+}
+
+void WordCompletionWidget::exportDictionary() {
+ DictionaryListItem *item = dynamic_cast<DictionaryListItem*>(dictionaryList->selectedItem ());
+
+ if (item != 0) {
+ KURL url = KFileDialog::getSaveURL(QString::null, QString::null, this, i18n("Export Dictionary"));
+ if (url.isEmpty() || !url.isValid())
+ return;
+
+ if (KIO::NetAccess::exists(url, false, this)) {
+ if (KMessageBox::warningContinueCancel(0,QString("<qt>%1</qt>").arg(i18n("The file %1 already exists. "
+ "Do you want to overwrite it?").arg(url.url())),i18n("File Exists"),i18n("&Overwrite"))==KMessageBox::Cancel) {
+ return;
+ }
+ }
+ KURL src;
+ src.setPath( KGlobal::dirs()->findResource ("appdata", item->filename()) );
+ KIO::NetAccess::copy (src, url, this);
+ }
+}
+
+void WordCompletionWidget::selectionChanged() {
+ DictionaryListItem *item = dynamic_cast<DictionaryListItem*>(dictionaryList->selectedItem ());
+
+ if (item != 0) {
+ deleteButton->setEnabled(true);
+ moveUpButton->setEnabled(true);
+ moveDownButton->setEnabled(true);
+ exportButton->setEnabled(true);
+ selectedDictionaryDetails->setEnabled(true);
+ languageLabel->setEnabled(true);
+ dictionaryNameLabel->setEnabled(true);
+ dictionaryName->setEnabled(true);
+ languageButton->setEnabled(true);
+
+ dictionaryName->setText(item->text(0));
+ languageButton->setCurrentItem(item->languageCode());
+ }
+ else {
+ deleteButton->setEnabled(false);
+ moveUpButton->setEnabled(false);
+ moveDownButton->setEnabled(false);
+ exportButton->setEnabled(false);
+ selectedDictionaryDetails->setEnabled(false);
+ languageLabel->setEnabled(false);
+ dictionaryNameLabel->setEnabled(false);
+ dictionaryName->setEnabled(false);
+ languageButton->setEnabled(false);
+
+ dictionaryName->setText("");
+ languageButton->setText("");
+ }
+}
+
+void WordCompletionWidget::nameChanged (const QString &text) {
+ QListViewItem *item = dictionaryList->selectedItem ();
+
+ if (item != 0) {
+ QString old = item->text(0);
+
+ if (old != text) {
+ item->setText(0, text);
+ emit changed(true);
+ }
+ }
+}
+
+void WordCompletionWidget::languageSelected (int) {
+ DictionaryListItem *item = dynamic_cast<DictionaryListItem*>(dictionaryList->selectedItem ());
+
+ if (item != 0) {
+ QString old = item->text(1);
+ QString text = languageButton->currentTag();
+
+ if (old != text) {
+ item->setLanguage(languageButton->text(), text);
+ emit changed(true);
+ }
+ }
+}
+
+#include "wordcompletionwidget.moc"
diff --git a/kmouth/wordcompletion/wordcompletionwidget.h b/kmouth/wordcompletion/wordcompletionwidget.h
new file mode 100644
index 0000000..574a4e9
--- /dev/null
+++ b/kmouth/wordcompletion/wordcompletionwidget.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ wordcompletionwidget.h - description
+ -------------------
+ begin : Tue Apr 29 2003
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// $Id$
+
+#ifndef WORDCOMPLETIONWIDGET_H
+#define WORDCOMPLETIONWIDGET_H
+
+#include "wordcompletionui.h"
+class WordCompletion;
+class KLanguageButton;
+
+/**
+ * This class represents a configuration widget for managing dictionaries.
+ * @author Gunnar Schmi Dt
+ */
+class WordCompletionWidget : public WordCompletionUI {
+ Q_OBJECT
+public:
+ WordCompletionWidget(QWidget *parent, const char *name);
+ ~WordCompletionWidget();
+
+ /**
+ * This method is invoked whenever the widget should read its configuration
+ * from a config file and update the user interface.
+ */
+ void load();
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files.
+ */
+ void save();
+
+signals:
+ void changed (bool);
+
+private slots:
+ void addDictionary();
+ void deleteDictionary();
+ void moveUp();
+ void moveDown();
+ void exportDictionary();
+
+ void selectionChanged();
+ void nameChanged (const QString &text);
+ void languageSelected (int);
+
+ /**
+ * This slot is used to emit the signal changed when any widget changes
+ * the configuration
+ */
+ void configChanged() {
+ emit changed(true);
+ };
+
+private:
+ /**
+ * Object holding all the configuration
+ */
+ KConfig *config;
+ QStringList newDictionaryFiles;
+ QStringList removedDictionaryFiles;
+};
+
+#endif
diff --git a/kmouth/wordcompletion/wordlist.cpp b/kmouth/wordcompletion/wordlist.cpp
new file mode 100644
index 0000000..67f05d8
--- /dev/null
+++ b/kmouth/wordcompletion/wordlist.cpp
@@ -0,0 +1,550 @@
+/***************************************************************************
+ wordlist.cpp - description
+ -------------------
+ begin : Don Sep 12 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// $Id$
+
+#include <qregexp.h>
+#include <qdir.h>
+
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+#include <klocale.h>
+
+#include "wordlist.h"
+
+namespace WordList {
+void addWords (WordMap &map, QString line);
+
+XMLParser::XMLParser() {
+}
+
+XMLParser::~XMLParser() {
+}
+
+bool XMLParser::warning (const QXmlParseException &) {
+ return false;
+}
+
+bool XMLParser::error (const QXmlParseException &) {
+ return false;
+}
+
+bool XMLParser::fatalError (const QXmlParseException &) {
+ return false;
+}
+
+QString XMLParser::errorString() {
+ return "";
+}
+
+bool XMLParser::startDocument() {
+ text = QString::null;
+ return true;
+}
+
+bool XMLParser::startElement (const QString &, const QString &,
+ const QString &,
+ const QXmlAttributes &)
+{
+ if (!text.isNull() && !text.isEmpty()) {
+ addWords (list, text);
+ text = QString::null;
+ }
+ return true;
+}
+
+bool XMLParser::characters (const QString &ch) {
+ text += ch;
+ return true;
+}
+
+bool XMLParser::ignorableWhitespace (const QString &) {
+ if (!text.isNull() && !text.isEmpty()) {
+ addWords (list, text);
+ text = QString::null;
+ }
+ return true;
+}
+
+bool XMLParser::endElement (const QString &, const QString &,
+ const QString &)
+{
+ if (!text.isNull() && !text.isEmpty()) {
+ addWords (list, text);
+ text = QString::null;
+ }
+ return true;
+}
+
+bool XMLParser::endDocument() {
+ if (!text.isNull() && !text.isEmpty()) {
+ addWords (list, text);
+ text = QString::null;
+ }
+ return true;
+}
+
+WordMap XMLParser::getList() {
+ return list;
+}
+
+/***************************************************************************/
+
+KProgressDialog *progressDialog() {
+ KProgressDialog *pdlg = new KProgressDialog(0, "progressDialog", i18n("Creating Word List"), i18n("Parsing the KDE documentation..."), false);
+ pdlg->setAllowCancel (false);
+ pdlg->showCancelButton (false);
+ pdlg->setAutoReset(false);
+ pdlg->setAutoClose(false);
+ pdlg->progressBar()->setTotalSteps(100);
+ pdlg->progressBar()->setProgress(0);
+ return pdlg;
+}
+
+bool saveWordList (WordMap map, QString filename) {
+ QFile file(filename);
+ if(!file.open(IO_WriteOnly))
+ return false;
+
+ QTextStream stream(&file);
+ stream.setEncoding (QTextStream::UnicodeUTF8);
+
+ stream << "WPDictFile\n";
+ WordMap::ConstIterator it;
+ for (it = map.begin(); it != map.end(); ++it)
+ stream << it.key() << "\t" << it.data() << "\t2\n";
+ file.close();
+ return true;
+}
+
+/***************************************************************************/
+
+void addWords (WordMap &map, QString line) {
+ QStringList words = QStringList::split(QRegExp("\\W"), line);
+
+ QStringList::ConstIterator it;
+ for (it = words.begin(); it != words.end(); ++it) {
+ if (!(*it).contains(QRegExp("\\d|_"))) {
+ QString key = (*it).lower();
+ if (map.contains(key))
+ map[key] += 1;
+ else
+ map[key] = 1;
+ }
+ }
+}
+
+void addWords (WordMap &map, WordMap add) {
+ WordList::WordMap::ConstIterator it;
+ for (it = add.begin(); it != add.end(); ++it)
+ if (map.contains(it.key()))
+ map[it.key()] += it.data();
+ else
+ map[it.key()] = it.data();
+}
+
+void addWordsFromFile (WordMap &map, QString filename, QTextStream::Encoding encoding, QTextCodec *codec) {
+ QFile xmlfile(filename);
+ QXmlInputSource source (&xmlfile);
+ XMLParser parser;
+ QXmlSimpleReader reader;
+ reader.setFeature ("http://trolltech.com/xml/features/report-start-end-entity", true);
+ reader.setContentHandler (&parser);
+
+ WordMap words;
+ if (reader.parse(source)) // try to load the file as an xml-file
+ addWords(map, parser.getList());
+ else {
+ QFile wpdfile(filename);
+ if (wpdfile.open(IO_ReadOnly)) {
+ QTextStream stream(&wpdfile);
+ stream.setEncoding (QTextStream::UnicodeUTF8);
+
+ if (!stream.atEnd()) {
+ QString s = stream.readLine();
+ if (s == "WPDictFile") { // Contains the file a weighted word list?
+ // We can assume that weighted word lists are always UTF8 coded.
+ while (!stream.atEnd()) {
+ QString s = stream.readLine();
+ if (!(s.isNull() || s.isEmpty())) {
+ QStringList list = QStringList::split("\t", s);
+ bool ok;
+ int weight = list[1].toInt(&ok);
+ if (ok && (weight > 0)) {
+ if (map.contains(list[0]))
+ map[list[0]] += weight;
+ else
+ map[list[0]] = weight;
+ }
+ }
+ }
+ }
+ else { // Count the words in an ordinary text file
+ QFile file(filename);
+ if (file.open(IO_ReadOnly)) {
+ QTextStream stream(&file);
+ if (codec != 0)
+ stream.setCodec (codec);
+ else
+ stream.setEncoding (encoding);
+ while (!stream.atEnd())
+ addWords (map, stream.readLine());
+ }
+ }
+ }
+ }
+ }
+}
+
+}
+#include <kdebug.h>
+namespace WordList {
+
+WordMap parseFiles (QStringList files, QTextStream::Encoding encoding, QTextCodec *codec, KProgressDialog *pdlg) {
+ int progress = 0;
+ int steps = files.count();
+ int percent = 0;
+
+ WordMap map;
+ QStringList::ConstIterator it;
+ for (progress = 1, it = files.begin(); it != files.end(); ++progress, ++it) {
+ addWordsFromFile (map, *it, encoding, codec);
+
+ if (steps != 0 && progress*100/steps > percent) {
+ percent = progress*100/steps;
+ pdlg->progressBar()->setProgress(percent);
+ qApp->processEvents (20);
+ }
+ }
+ return map;
+}
+
+WordMap mergeFiles (QMap<QString,int> files, KProgressDialog *pdlg) {
+ pdlg->setLabel (i18n("Merging dictionaries..."));
+ pdlg->show();
+ qApp->processEvents (20);
+
+ int progress = 0;
+ int steps = files.count();
+ int percent = 0;
+ float totalWeight = 0;
+ long long maxWeight = 0;
+
+ QMap<QString,float> map;
+ QMap<QString,int>::ConstIterator it;
+ for (progress = 1, it = files.begin(); it != files.end(); ++progress, ++it) {
+ WordMap fileMap;
+ addWordsFromFile (fileMap, it.key(), QTextStream::UnicodeUTF8, 0);
+
+ long long weight = 0;
+ WordMap::ConstIterator iter;
+ for (iter = fileMap.begin(); iter != fileMap.end(); ++iter)
+ weight += iter.data();
+ float factor = 1.0 * it.data() / weight;
+ totalWeight += it.data();
+ if (weight > maxWeight)
+ maxWeight = weight;
+
+ for (iter = fileMap.begin(); iter != fileMap.end(); ++iter)
+ if (map.contains(iter.key()))
+ map[iter.key()] += iter.data() * factor;
+ else
+ map[iter.key()] = iter.data() * factor;
+
+ if (steps != 0 && progress*100/steps > percent) {
+ percent = progress*100/steps;
+ pdlg->progressBar()->setProgress(percent);
+ qApp->processEvents (20);
+ }
+ }
+
+ float factor;
+ if (1.0 * maxWeight * totalWeight > 1000000000)
+ factor = 1000000000 / totalWeight;
+ else
+ factor = 1.0 * maxWeight;
+
+ WordMap resultMap;
+ QMap<QString,float>::ConstIterator iter;
+ for (iter = map.begin(); iter != map.end(); ++iter)
+ resultMap[iter.key()] = (int)(factor * iter.data() + 0.5);
+
+ return resultMap;
+}
+
+WordMap parseKDEDoc (QString language, KProgressDialog *pdlg) {
+ pdlg->setLabel (i18n("Parsing the KDE documentation..."));
+ pdlg->show();
+ qApp->processEvents (20);
+
+ QStringList files = KApplication::kApplication()->dirs()->findAllResources ("html", language + "/*.docbook", true, true);
+ if ((files.count() == 0) && (language.length() == 5)) {
+ language = language.left(2);
+ files = KApplication::kApplication()->dirs()->findAllResources ("html", language + "/*.docbook", true, true);
+ }
+
+ return parseFiles (files, QTextStream::UnicodeUTF8, 0, pdlg);
+}
+
+WordMap parseFile (QString filename, QTextStream::Encoding encoding, QTextCodec *codec, KProgressDialog *pdlg) {
+ pdlg->setLabel (i18n("Parsing file..."));
+ pdlg->show();
+ qApp->processEvents (20);
+
+ QStringList files = filename;
+
+ return parseFiles (files, encoding, codec, pdlg);
+}
+
+WordMap parseDir (QString directory, QTextStream::Encoding encoding, QTextCodec *codec, KProgressDialog *pdlg) {
+ pdlg->setLabel (i18n("Parsing directory..."));
+ pdlg->show();
+ qApp->processEvents (20);
+
+ QStringList directories;
+ directories += directory;
+ QStringList files;
+ for (QStringList::Iterator it = directories.begin(); it != directories.end(); it = directories.remove(it)) {
+ QDir dir(*it);
+ const QFileInfoList *entries = dir.entryInfoList ("*", QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::Readable);
+ if (entries != 0) {
+ QFileInfoListIterator iter (*entries);
+ while ((iter.current()) != 0) {
+ QString name = iter.current()->fileName();
+ if (name != "." && name != "..") {
+ if (iter.current()->isDir())
+ directories += iter.current()->filePath ();
+ else
+ files += iter.current()->filePath ();
+ }
+ ++iter;
+ }
+ }
+ }
+
+ return parseFiles (files, encoding, codec, pdlg);
+}
+
+/***************************************************************************/
+
+/* Structures used for storing *.aff files (part of OpenOffice.org dictionaries)
+ */
+struct AffEntry {
+ bool cross;
+ int charsToRemove;
+ QString add;
+ QStringList condition;
+};
+typedef QValueList<AffEntry> AffList;
+typedef QMap<QChar,AffList> AffMap;
+
+/** Loads an *.aff file (part of OpenOffice.org dictionaries)
+ */
+void loadAffFile(const QString &filename, AffMap &prefixes, AffMap &suffixes) {
+ bool cross = false;
+
+ QFile afile(filename);
+ if (afile.open(IO_ReadOnly)) {
+ QTextStream stream(&afile);
+ while (!stream.atEnd()) {
+ QString s = stream.readLine();
+ QStringList fields = QStringList::split(QRegExp("\\s"), s);
+
+ if (fields.count() == 4) {
+ cross = (fields[2] == "Y");
+ }
+ else {
+ if (fields.count() >= 5) {
+ AffEntry e;
+ e.cross = cross;
+ if (fields[2] == "0")
+ e.charsToRemove = 0;
+ else
+ e.charsToRemove = fields[2].length();
+ e.add = fields[3];
+
+ if (fields[4] != ".") {
+ QString condition = fields[4];
+ for (uint idx = 0; idx < condition.length(); ++idx) {
+ if (condition[idx] == '[') {
+ QString code;
+ for (++idx; (idx < condition.length()) && condition[idx] != ']'; ++idx)
+ code += condition[idx];
+ e.condition << code;
+ }
+ else
+ e.condition << QString(condition[idx]);
+ }
+ }
+
+ if (s.startsWith("PFX")) {
+ AffList list;
+ if (prefixes.contains (fields[1][0]))
+ list = prefixes[fields[1][0]];
+ list << e;
+ prefixes[fields[1][0]] = list;
+ }
+ else if (s.startsWith("SFX")) {
+ AffList list;
+ if (suffixes.contains (fields[1][0]))
+ list = suffixes[fields[1][0]];
+ list << e;
+ suffixes[fields[1][0]] = list;
+ }
+ }
+ }
+ }
+ }
+}
+
+/** Checks if the given word matches the given condition. Each entry of the
+ * QStringList "condition" describes one character of the word. (If the word
+ * has more characters than condition entries only the last characters are
+ * compared).
+ * Each entry contains either all valid characters (if it does _not_ start
+ * with "^") or all invalid characters (if it starts with "^").
+ */
+inline bool checkCondition (const QString &word, const QStringList &condition) {
+ if (condition.count() == 0)
+ return true;
+
+ if (word.length() < condition.count())
+ return false;
+
+ QStringList::ConstIterator it;
+ int idx;
+ for (it = condition.begin(), idx = word.length()-condition.count();
+ it != condition.end();
+ ++it, ++idx)
+ {
+ if ((*it).contains(word[idx]) == ((*it)[0] == '^'))
+ return false;
+ }
+ return true;
+}
+
+/** Constructs words by adding suffixes to the given word, and copies the
+ * resulting words from map to checkedMap.
+ * @param modifiers discribes which suffixes are valid
+ * @param cross true if the word has a prefix
+ */
+inline void checkWord(const QString &word, const QString &modifiers, bool cross, const WordMap &map, WordMap &checkedMap, const AffMap &suffixes) {
+ for (uint i = 0; i < modifiers.length(); i++) {
+ if (suffixes.contains(modifiers[i])) {
+ AffList sList = suffixes[modifiers[i]];
+
+ AffList::ConstIterator sIt;
+ for (sIt = sList.begin(); sIt != sList.end(); ++sIt) {
+ if (((*sIt).cross || !cross)
+ && (checkCondition(word, (*sIt).condition)))
+ {
+ QString sWord = word.left(word.length()-(*sIt).charsToRemove) + (*sIt).add;
+ if (map.contains(sWord))
+ checkedMap[sWord] = map[sWord];
+ }
+ }
+ }
+ }
+}
+
+/** Constructs words by adding pre- and suffixes to the given word, and
+ * copies the resulting words from map to checkedMap.
+ * @param modifiers discribes which pre- and suffixes are valid
+ */
+void checkWord (const QString &word, const QString &modifiers, const WordMap &map, WordMap &checkedMap, const AffMap &prefixes, const AffMap &suffixes) {
+ if (map.contains(word))
+ checkedMap[word] = map[word];
+
+ checkWord(word, modifiers, true, map, checkedMap, suffixes);
+
+ for (uint i = 0; i < modifiers.length(); i++) {
+ if (prefixes.contains(modifiers[i])) {
+ AffList pList = prefixes[modifiers[i]];
+
+ AffList::ConstIterator pIt;
+ for (pIt = pList.begin(); pIt != pList.end(); ++pIt) {
+ QString pWord = (*pIt).add + word;
+ if (map.contains(pWord))
+ checkedMap[pWord] = map[pWord];
+
+ checkWord(pWord, modifiers, false, map, checkedMap, suffixes);
+ }
+ }
+ }
+}
+
+WordMap spellCheck (WordMap map, QString dictionary, KProgressDialog *pdlg) {
+
+ if (dictionary.endsWith(".dic")) {
+ AffMap prefixes;
+ AffMap suffixes;
+ WordMap checkedMap;
+ loadAffFile (dictionary.left(dictionary.length()-4) + ".aff", prefixes, suffixes);
+
+ pdlg->progressBar()->reset();
+ pdlg->setAllowCancel (false);
+ pdlg->showCancelButton (false);
+ pdlg->setAutoReset(false);
+ pdlg->setAutoClose(false);
+ pdlg->setLabel (i18n("Performing spell check..."));
+ pdlg->progressBar()->setTotalSteps(100);
+ pdlg->progressBar()->setProgress(0);
+ qApp->processEvents (20);
+ int progress = 0;
+ int steps = 0;
+ int percent = 0;
+
+ QFile dfile(dictionary);
+ if (dfile.open(IO_ReadOnly)) {
+ QTextStream stream(&dfile);
+
+ if (!stream.atEnd()) {
+ QString s = stream.readLine(); // Number of words
+ steps = s.toInt();
+ }
+
+ while (!stream.atEnd()) {
+ QString s = stream.readLine();
+ if (s.contains("/")) {
+ QString word = s.left(s.find("/")).lower();
+ QString modifiers = s.right(s.length() - s.find("/"));
+
+ checkWord(word, modifiers, map, checkedMap, prefixes, suffixes);
+ }
+ else {
+ if (!s.isEmpty() && !s.isNull() && map.contains(s.lower()))
+ checkedMap[s.lower()] = map[s.lower()];
+ }
+
+ progress++;
+ if (steps != 0 && progress*100/steps > percent) {
+ percent = progress*100/steps;
+ pdlg->progressBar()->setProgress(percent);
+ qApp->processEvents (20);
+ }
+ }
+ }
+
+ return checkedMap;
+ }
+ else
+ return map;
+}
+
+}
+
diff --git a/kmouth/wordcompletion/wordlist.h b/kmouth/wordcompletion/wordlist.h
new file mode 100644
index 0000000..d2f85ac
--- /dev/null
+++ b/kmouth/wordcompletion/wordlist.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ wordlist.h - description
+ -------------------
+ begin : Don Sep 12 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// $Id$
+
+#ifndef WORDLIST_H
+#define WORDLIST_H
+
+#include <qxml.h>
+#include <qvaluestack.h>
+#include <qstring.h>
+#include <qobject.h>
+#include <qmap.h>
+
+class QTextCodec;
+class KProgressDialog;
+
+namespace WordList {
+
+typedef QMap<QString,int> WordMap;
+
+KProgressDialog *progressDialog();
+
+WordMap parseKDEDoc (QString language, KProgressDialog *pdlg);
+WordMap parseFile (QString filename, QTextStream::Encoding encoding, QTextCodec *codec, KProgressDialog *pdlg);
+WordMap parseDir (QString directory, QTextStream::Encoding encoding, QTextCodec *codec, KProgressDialog *pdlg);
+WordMap mergeFiles (QMap<QString,int> files, KProgressDialog *pdlg);
+
+WordMap spellCheck (WordMap wordlist, QString dictionary, KProgressDialog *pdlg);
+
+bool saveWordList (WordMap map, QString filename);
+
+/**
+ * This class implements a parser for reading docbooks and generating word
+ * lists. It is intended to be used together with the Qt SAX2 framework.
+ * @author Gunnar Schmi Dt
+ */
+
+class XMLParser : public QXmlDefaultHandler {
+public:
+ XMLParser();
+ ~XMLParser();
+
+ bool warning (const QXmlParseException &exception);
+ bool error (const QXmlParseException &exception);
+ bool fatalError (const QXmlParseException &exception);
+ QString errorString();
+
+ /** Processes the start of the document. */
+ bool startDocument();
+
+ /** Processes the start tag of an element. */
+ bool startElement (const QString &, const QString &, const QString &name,
+ const QXmlAttributes &attributes);
+
+ /** Processes a chunk of normal character data. */
+ bool characters (const QString &ch);
+
+ /** Processes whitespace. */
+ bool ignorableWhitespace (const QString &ch);
+
+ /** Processes the end tag of an element. */
+ bool endElement (const QString &, const QString &, const QString &name);
+
+ /** Processes the end of the document. */
+ bool endDocument();
+
+ /** returns a list of words */
+ WordMap getList();
+
+private:
+ WordMap list;
+ QString text;
+};
+
+}
+
+#endif
diff --git a/ksayit/AUTHORS b/ksayit/AUTHORS
new file mode 100644
index 0000000..a7733ba
--- /dev/null
+++ b/ksayit/AUTHORS
@@ -0,0 +1 @@
+Robert Vogl <voglrobe@web.de>
diff --git a/ksayit/COPYING b/ksayit/COPYING
new file mode 100644
index 0000000..c13faf0
--- /dev/null
+++ b/ksayit/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ksayit/ChangeLog b/ksayit/ChangeLog
new file mode 100644
index 0000000..0519ecb
--- /dev/null
+++ b/ksayit/ChangeLog
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/ksayit/DocBook.README b/ksayit/DocBook.README
new file mode 100644
index 0000000..97862c0
--- /dev/null
+++ b/ksayit/DocBook.README
@@ -0,0 +1,76 @@
+KSayIt supports the following subset of DocBook elements:
+
+Book ::=
+ (BookInfo, Chapter+)
+
+BookInfo ::=
+ ((KeywordSet|Abstract|AuthorGroup|Date|ReleaseInfo|Title)+)
+
+KeywordSet ::=
+ (Keyword+)
+
+Keyword ::=
+ (#PCDATA+)
+
+Abstract ::=
+ (Para+)
+
+Authorgroup ::=
+ (Author+)
+
+Author ::=
+ ((Firstname|Surname)+)
+
+Firstname ::=
+ (#PCDATA+)
+
+Surname ::=
+ (#PCDATA+)
+
+Date ::=
+ (#PCDATA+)
+
+ReleaseInfo ::=
+ (#PCDATA+)
+
+Title ::=
+ (#PCDATA+)
+
+Chapter ::=
+ (Title,(Para|Sect1)+)
+
+Sect1 ::=
+ (Title,(Para|Sect2)+)
+
+Sect2 ::=
+ (Title,(Para|Sect3)+)
+
+Sect3 ::=
+ (Title,(Para|Sect4)+)
+
+Sect4 ::=
+ (Title,(Para|Sect5)+)
+
+Sect5 ::=
+ (Title, Para+)
+
+Para ::=
+ ((#PCDATA|Citation|Emphasis|ForeignPhrase|Phrase|Action|Application|
+ Command|Email|Filename|Function|GUIButton|GUIIcon|GUILabel|GUIMenu|
+ GUIMenuItem|GUISubmenu|ItemizedList|KeyCap|KeyCode|KeyCombo|KeySym|Literal|
+ MenuChoice|MouseButton|Option|UserInput|Author|CorpAuthor|Comment|
+ Subscript|Superscript|Note|Tip|Warning)+)
+
+ItemizedList ::=
+ (ListItem+)
+
+ListItem ::=
+ (#PCDATA+)
+
+All entities must be defined in an internal DTD within the document. External entities are NOT supported.
+
+--
+Robert Vogl
+
+
+
diff --git a/ksayit/Doxyfile b/ksayit/Doxyfile
new file mode 100644
index 0000000..cb1408f
--- /dev/null
+++ b/ksayit/Doxyfile
@@ -0,0 +1,248 @@
+# Doxyfile 1.3.5-KDevelop
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = ksayit.kdevelop
+PROJECT_NUMBER = 0.1
+OUTPUT_DIRECTORY =
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH = /home/voglrobe/Projekte/ksayit/
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = /home/voglrobe/Projekte/ksayit
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.C \
+ *.H \
+ *.tlh \
+ *.diff \
+ *.patch \
+ *.moc \
+ *.xpm \
+ *.dox
+RECURSIVE = yes
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = yes
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 1000
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/ksayit/Freeverb_plugin/Makefile.am b/ksayit/Freeverb_plugin/Makefile.am
new file mode 100644
index 0000000..0db4104
--- /dev/null
+++ b/ksayit/Freeverb_plugin/Makefile.am
@@ -0,0 +1,13 @@
+INCLUDES = -I$(top_srcdir)/ksayit/src $(all_includes)
+METASOURCES = AUTO
+kde_servicetypes_DATA = ksayit_libFreeverb_service.desktop
+kde_services_DATA = ksayit_libFreeverb.desktop
+fxpluginsdir = $(kde_libraries)/kde3
+fxplugins_LTLIBRARIES = libFreeverb_plugin.la
+libFreeverb_plugin_la_LDFLAGS = -avoid-version -module -no-undefined \
+ $(all_libraries)
+libFreeverb_plugin_la_LIBADD = $(LIB_KDECORE) $(LIB_KDEUI) -lartskde\
+ -lartsmodules
+noinst_HEADERS = freeverbsetupimpl.h ksayitfreeverblib.h kdeexportfix.h
+libFreeverb_plugin_la_SOURCES = freeverbsetupimpl.cpp freeverb_setup.ui \
+ ksayitfreeverblib.cpp
diff --git a/ksayit/Freeverb_plugin/configure.in.in b/ksayit/Freeverb_plugin/configure.in.in
new file mode 100644
index 0000000..adc474e
--- /dev/null
+++ b/ksayit/Freeverb_plugin/configure.in.in
@@ -0,0 +1,17 @@
+dnl ==========================
+dnl checks for Hadifix plug in
+dnl ==========================
+
+AC_ARG_ENABLE(ksayit-audio-plugins,
+ AC_HELP_STRING([--enable-ksayit-audio-plugins],
+ [build audio plugins for KSayIt [default=no]]),
+ ksayit_audio_plugins=$enableval,
+ ksayit_audio_plugins=no)
+
+compile_ksayit_audio_plugins="no"
+
+if test "x$ksayit_audio_plugins" = "xyes"; then
+ compile_ksayit_audio_plugins="yes"
+fi
+
+AM_CONDITIONAL(include_ksayit_audio_plugins, test "x$compile_ksayit_audio_plugins" = "xyes") \ No newline at end of file
diff --git a/ksayit/Freeverb_plugin/freeverb_setup.ui b/ksayit/Freeverb_plugin/freeverb_setup.ui
new file mode 100644
index 0000000..ab3808a
--- /dev/null
+++ b/ksayit/Freeverb_plugin/freeverb_setup.ui
@@ -0,0 +1,668 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>Freeverb_Setup</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>Freeverb_Setup</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>360</width>
+ <height>325</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>360</width>
+ <height>300</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>FreeVerb</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="resizeMode">
+ <enum>Minimum</enum>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame_room</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>260</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel_room</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Room&lt;/b&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLCDNumber">
+ <property name="name">
+ <cstring>LCD_room</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>171</red>
+ <green>223</green>
+ <blue>171</blue>
+ </color>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="numDigits">
+ <number>2</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>Flat</enum>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>slider_room</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>99</number>
+ </property>
+ <property name="lineStep">
+ <number>5</number>
+ </property>
+ <property name="value">
+ <number>99</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="tickmarks">
+ <enum>Above</enum>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame_damp</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>260</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel_damp</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Damp&lt;/b&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLCDNumber">
+ <property name="name">
+ <cstring>LCD_damp</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>171</red>
+ <green>223</green>
+ <blue>171</blue>
+ </color>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="numDigits">
+ <number>2</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>Flat</enum>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>slider_damp</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="lineStep">
+ <number>5</number>
+ </property>
+ <property name="value">
+ <number>99</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="tickmarks">
+ <enum>Above</enum>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame_wet</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>260</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel_wet</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Wet&lt;/b&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLCDNumber">
+ <property name="name">
+ <cstring>LCD_wet</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>171</red>
+ <green>223</green>
+ <blue>171</blue>
+ </color>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="numDigits">
+ <number>2</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>Flat</enum>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>slider_wet</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="lineStep">
+ <number>5</number>
+ </property>
+ <property name="value">
+ <number>99</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="tickmarks">
+ <enum>Above</enum>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame_dry</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>260</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel_dry</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Dry&lt;/b&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLCDNumber">
+ <property name="name">
+ <cstring>LCD_dry</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>171</red>
+ <green>223</green>
+ <blue>171</blue>
+ </color>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="numDigits">
+ <number>2</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>Flat</enum>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>slider_dry</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="lineStep">
+ <number>5</number>
+ </property>
+ <property name="value">
+ <number>99</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="tickmarks">
+ <enum>Above</enum>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame_width</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>260</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel_width</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Width&lt;/b&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLCDNumber">
+ <property name="name">
+ <cstring>LCD_width</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>171</red>
+ <green>223</green>
+ <blue>171</blue>
+ </color>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="numDigits">
+ <number>2</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>Flat</enum>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>slider_width</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="lineStep">
+ <number>5</number>
+ </property>
+ <property name="value">
+ <number>99</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="tickmarks">
+ <enum>Above</enum>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>line5</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer13</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>180</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>OK_Button</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>60</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>slider_room</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>Freeverb_Setup</receiver>
+ <slot>sliderRoomChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>slider_damp</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>Freeverb_Setup</receiver>
+ <slot>sliderDampChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>slider_wet</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>Freeverb_Setup</receiver>
+ <slot>sliderWetChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>slider_dry</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>Freeverb_Setup</receiver>
+ <slot>sliderDryChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>slider_width</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>Freeverb_Setup</receiver>
+ <slot>sliderWidthChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>OK_Button</sender>
+ <signal>clicked()</signal>
+ <receiver>Freeverb_Setup</receiver>
+ <slot>slotOKwasClicked()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>sliderRoomChanged(int)</slot>
+ <slot>sliderDampChanged(int)</slot>
+ <slot>sliderWetChanged(int)</slot>
+ <slot>sliderDryChanged(int)</slot>
+ <slot>sliderWidthChanged(int)</slot>
+ <slot>slotOKwasClicked()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/ksayit/Freeverb_plugin/freeverbsetupimpl.cpp b/ksayit/Freeverb_plugin/freeverbsetupimpl.cpp
new file mode 100644
index 0000000..cf16c0d
--- /dev/null
+++ b/ksayit/Freeverb_plugin/freeverbsetupimpl.cpp
@@ -0,0 +1,116 @@
+/***************************************************************************
+ freeverbsetupimpl.cpp - description
+ -------------------
+ begin : Son Nov 2 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <iostream>
+using namespace std;
+
+// QT includes
+#include <qslider.h>
+#include <qlcdnumber.h>
+
+// KDE includes
+#include <kdebug.h>
+
+// App specific includes
+#include "freeverbsetupimpl.h"
+
+FreeverbSetupImpl::FreeverbSetupImpl(QWidget *parent, const char *name, bool modal, KConfig *config )
+ : Freeverb_Setup(parent,name,modal), m_config(config) {
+
+ // initialize Widgets
+ Init();
+
+}
+FreeverbSetupImpl::~FreeverbSetupImpl(){
+}
+
+
+void FreeverbSetupImpl::sliderRoomChanged(int value)
+{
+ LCD_room->display( 99-value );
+}
+
+
+void FreeverbSetupImpl::sliderDampChanged(int value)
+{
+ LCD_damp->display( 99-value );
+}
+
+
+void FreeverbSetupImpl::sliderWetChanged(int value)
+{
+ LCD_wet->display( 99-value );
+}
+
+
+void FreeverbSetupImpl::sliderDryChanged(int value)
+{
+ LCD_dry->display( 99-value );
+}
+
+
+void FreeverbSetupImpl::sliderWidthChanged(int value)
+{
+ LCD_width->display( 99-value );
+}
+
+
+void FreeverbSetupImpl::saveWasClicked()
+{
+ kdDebug(100200) << "FreeverbSetupImpl::saveWasClicked()" << endl;
+ // Save freeverb configuration
+ m_config->setGroup("Synth_FREEVERB");
+ m_config->writeEntry( "room", LCD_room->intValue() );
+ m_config->writeEntry( "damp", LCD_damp->intValue() );
+ m_config->writeEntry( "wet", LCD_wet->intValue() );
+ m_config->writeEntry( "dry", LCD_dry->intValue() );
+ m_config->writeEntry( "width", LCD_width->intValue() );
+ m_config->sync();
+}
+
+void FreeverbSetupImpl::Init()
+{
+ // Read freeverb configuration
+ m_config->setGroup("Synth_FREEVERB");
+ LCD_room->display( m_config->readNumEntry("room", 50) );
+ slider_room->setValue( 99-LCD_room->intValue() );
+
+ LCD_damp->display( m_config->readNumEntry("damp", 50) );
+ slider_damp->setValue( 99-LCD_damp->intValue() );
+
+ LCD_wet->display( m_config->readNumEntry("wet", 50) );
+ slider_wet->setValue( 99-LCD_wet->intValue() );
+
+ LCD_dry->display( m_config->readNumEntry("dry", 50) );
+ slider_dry->setValue( 99-LCD_dry->intValue() );
+
+ LCD_width->display( m_config->readNumEntry("width", 50) );
+ slider_width->setValue( 99-LCD_width->intValue() );
+}
+
+
+void FreeverbSetupImpl::slotOKwasClicked()
+{
+ // save configuration
+ saveWasClicked();
+ // simply close the dialog
+ this->accept();
+}
+
+
+
+#include "freeverbsetupimpl.moc"
diff --git a/ksayit/Freeverb_plugin/freeverbsetupimpl.h b/ksayit/Freeverb_plugin/freeverbsetupimpl.h
new file mode 100644
index 0000000..8bee5bb
--- /dev/null
+++ b/ksayit/Freeverb_plugin/freeverbsetupimpl.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ freeverbsetupimpl.h - description
+ -------------------
+ begin : Son Nov 2 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef FREEVERBSETUPIMPL_H
+#define FREEVERBSETUPIMPL_H
+
+// QT includes
+#include <qwidget.h>
+
+// KDE includes
+#include <kconfig.h>
+
+// App specific includes
+#include <freeverb_setup.h>
+
+/**
+ *@author Robert Vogl
+ */
+
+class FreeverbSetupImpl : public Freeverb_Setup {
+ Q_OBJECT
+public:
+ FreeverbSetupImpl(QWidget *parent=0, const char *name=0, bool modal=true, KConfig *config=0);
+ ~FreeverbSetupImpl();
+
+public slots:
+ /** saves the configuration */
+ void saveWasClicked();
+
+protected slots:
+ void sliderRoomChanged(int value);
+ void sliderDampChanged(int value);
+ void sliderWetChanged(int value);
+ void sliderDryChanged(int value);
+ void sliderWidthChanged(int value);
+ void slotOKwasClicked();
+
+private: // Methods
+ void Init();
+
+
+private:
+ KConfig *m_config;
+
+
+};
+
+#endif
diff --git a/ksayit/Freeverb_plugin/kdeexportfix.h b/ksayit/Freeverb_plugin/kdeexportfix.h
new file mode 100644
index 0000000..172dd94
--- /dev/null
+++ b/ksayit/Freeverb_plugin/kdeexportfix.h
@@ -0,0 +1,22 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ kdelibs < 3.3.2 had a bug in the KDE_EXPORT macro. This file fixes this
+ by undefining it.
+ -------------------
+ Copyright : (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <kdeversion.h>
+#if KDE_VERSION < KDE_MAKE_VERSION (3,3,2)
+#undef KDE_EXPORT
+#define KDE_EXPORT
+#endif
diff --git a/ksayit/Freeverb_plugin/ksayit_libFreeverb.desktop b/ksayit/Freeverb_plugin/ksayit_libFreeverb.desktop
new file mode 100644
index 0000000..410c23a
--- /dev/null
+++ b/ksayit/Freeverb_plugin/ksayit_libFreeverb.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=Freeverb
+Name[ne]=फ्रीभर्व
+Name[vi]=Động từ tự do
+Comment=A Freeverb Plugin for KSayIt
+Comment[bg]=Приставка Freeverb за KTTSD
+Comment[br]=Lugent Freeverb evit KSayIt
+Comment[ca]=Un connector de Freeverb pel KSayit
+Comment[cs]=Freeverb modul pro KSayIt
+Comment[da]=Et Freeverb plugin for KSayIt
+Comment[de]=Ein Freeverb-Modul für KSayIt
+Comment[el]=Ένα πρόσθετο Freeverb για το KTTSD
+Comment[es]=Complemento Freeverb para KSayIt
+Comment[et]=KSayIt'i Freeverbi plugin
+Comment[eu]=KSayIt-en Freeverb plugina
+Comment[fa]=وصلۀ Freever برای KSaylt
+Comment[fi]=Freeverb-liitännäinen KSayIt--ohjelmalle
+Comment[fr]=Un module Freeverb pour KSayIt
+Comment[ga]=Breiseán Freeverb le haghaidh KSayIt
+Comment[gl]=Un Plugin de Freeverb para KSayIt
+Comment[he]=תוסף Freeverb עבור KSayIt
+Comment[hu]=Freeverb modul a KSayIt programhoz
+Comment[is]=Freeverb íforrit fyrir KSayIt
+Comment[it]=Un plugin per Freeverb per KTTSD
+Comment[ja]=KSayIt 用 Freeverb プラグイン
+Comment[ka]=KSayIt Freeverb მოდული
+Comment[km]= កម្មវិធី​ជំនួយ Freeverb សម្រាប់ KSayIt
+Comment[lt]=Freeverb priedas skirtas KSayIt
+Comment[mk]=Freeverb-приклучок за Ksaylt
+Comment[nb]=Et Freeverb programtillegg for KSayIt
+Comment[nds]=En Freeverb-Moduul för KSayIt
+Comment[ne]=के से इटका लागि एउटा फ्रिभर्व प्लगइन
+Comment[nl]=Een Freeverb-plugin vor KSayIt
+Comment[pa]=KSayIt ਲਈ ਮੁਕਤ-ਵਰਬ ਪਲੱਗਿੰਨ
+Comment[pl]=Wtyczka Freeverb dla KSayIt
+Comment[pt]='Plugin' de Reverberação para o KTTSD
+Comment[pt_BR]=Plug-in do Freeverb para o KSayIt
+Comment[ru]=Модуль Freeverb для KSayIt
+Comment[sk]=Modul Freeverb pre PovedzTo
+Comment[sl]=Vstavek Freeverb za KSayIt
+Comment[sr]=Freeverb прикључак за KSayIt
+Comment[sr@Latn]=Freeverb priključak za KSayIt
+Comment[sv]=Freeverb-insticksprogram för Ksayit
+Comment[tg]=Модули Freeverb барои KSayIt
+Comment[tr]=Ksayit için Freeverb Eklentisi
+Comment[uk]=Втулок Freeverb для KSayIt
+Comment[vi]=Trình bổ sung "Động từ tự do" cho "Nói K"
+Comment[zh_CN]=KSayIt 的 Freeverb 插件
+Comment[zh_TW]=KSayIt 的 Freeverb 外掛程式
+ServiceTypes=KSayIt/FXPlugin
+Type=Service
+X-KDE-Library=libFreeverb_plugin
diff --git a/ksayit/Freeverb_plugin/ksayit_libFreeverb_service.desktop b/ksayit/Freeverb_plugin/ksayit_libFreeverb_service.desktop
new file mode 100644
index 0000000..dbb02d7
--- /dev/null
+++ b/ksayit/Freeverb_plugin/ksayit_libFreeverb_service.desktop
@@ -0,0 +1,48 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KSayIt/FXPlugin
+Comment=A Freeverb Plugin for KSayIt
+Comment[bg]=Приставка Freeverb за KTTSD
+Comment[br]=Lugent Freeverb evit KSayIt
+Comment[ca]=Un connector de Freeverb pel KSayit
+Comment[cs]=Freeverb modul pro KSayIt
+Comment[da]=Et Freeverb plugin for KSayIt
+Comment[de]=Ein Freeverb-Modul für KSayIt
+Comment[el]=Ένα πρόσθετο Freeverb για το KTTSD
+Comment[es]=Complemento Freeverb para KSayIt
+Comment[et]=KSayIt'i Freeverbi plugin
+Comment[eu]=KSayIt-en Freeverb plugina
+Comment[fa]=وصلۀ Freever برای KSaylt
+Comment[fi]=Freeverb-liitännäinen KSayIt--ohjelmalle
+Comment[fr]=Un module Freeverb pour KSayIt
+Comment[ga]=Breiseán Freeverb le haghaidh KSayIt
+Comment[gl]=Un Plugin de Freeverb para KSayIt
+Comment[he]=תוסף Freeverb עבור KSayIt
+Comment[hu]=Freeverb modul a KSayIt programhoz
+Comment[is]=Freeverb íforrit fyrir KSayIt
+Comment[it]=Un plugin per Freeverb per KTTSD
+Comment[ja]=KSayIt 用 Freeverb プラグイン
+Comment[ka]=KSayIt Freeverb მოდული
+Comment[km]= កម្មវិធី​ជំនួយ Freeverb សម្រាប់ KSayIt
+Comment[lt]=Freeverb priedas skirtas KSayIt
+Comment[mk]=Freeverb-приклучок за Ksaylt
+Comment[nb]=Et Freeverb programtillegg for KSayIt
+Comment[nds]=En Freeverb-Moduul för KSayIt
+Comment[ne]=के से इटका लागि एउटा फ्रिभर्व प्लगइन
+Comment[nl]=Een Freeverb-plugin vor KSayIt
+Comment[pa]=KSayIt ਲਈ ਮੁਕਤ-ਵਰਬ ਪਲੱਗਿੰਨ
+Comment[pl]=Wtyczka Freeverb dla KSayIt
+Comment[pt]='Plugin' de Reverberação para o KTTSD
+Comment[pt_BR]=Plug-in do Freeverb para o KSayIt
+Comment[ru]=Модуль Freeverb для KSayIt
+Comment[sk]=Modul Freeverb pre PovedzTo
+Comment[sl]=Vstavek Freeverb za KSayIt
+Comment[sr]=Freeverb прикључак за KSayIt
+Comment[sr@Latn]=Freeverb priključak za KSayIt
+Comment[sv]=Freeverb-insticksprogram för Ksayit
+Comment[tg]=Модули Freeverb барои KSayIt
+Comment[tr]=Ksayit için Freeverb Eklentisi
+Comment[uk]=Втулок Freeverb для KSayIt
+Comment[vi]=Trình bổ sung "Động từ tự do" cho "Nói K"
+Comment[zh_CN]=KSayIt 的 Freeverb 插件
+Comment[zh_TW]=KSayIt 的 Freeverb 外掛程式
diff --git a/ksayit/Freeverb_plugin/ksayitfreeverblib.cpp b/ksayit/Freeverb_plugin/ksayitfreeverblib.cpp
new file mode 100644
index 0000000..1edf874
--- /dev/null
+++ b/ksayit/Freeverb_plugin/ksayitfreeverblib.cpp
@@ -0,0 +1,164 @@
+//
+// C++ Implementation: KSayItFXPlugin
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// QT includes
+// #include <qtextcodec.h>
+#include <qstringlist.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdemacros.h>
+#include <arts/artsmodules.h>
+
+// App specific includes
+#include "ksayitfreeverblib.h"
+#include "freeverbsetupimpl.h"
+
+
+// The class factory
+K_EXPORT_COMPONENT_FACTORY( libFreeverb_plugin, FreeverbPluginFactory )
+/** replaced by macro
+extern "C"
+{
+ void* init_libFreeverb_plugin()
+ {
+ return new FreeverbPluginFactory;
+ }
+};
+*/
+
+KInstance *FreeverbPluginFactory::p_instance = 0L;
+
+
+// Factory Constructor
+FreeverbPluginFactory::FreeverbPluginFactory(QObject *parent, const char* name)
+{
+ p_instance = new KInstance("FreeverbPluginFactory");
+}
+
+
+QObject* FreeverbPluginFactory::createObject(QObject *parent, const char* name,
+ const char*,
+ const QStringList &)
+{
+ kdDebug(100200) << "FreeverbPluginFactory::createObject()" << endl;
+
+ QObject* obj = new FreeverbPlugin( parent, name );
+ emit objectCreated( obj );
+ return obj;
+}
+
+
+
+
+// Plugin Constructor
+FreeverbPlugin::FreeverbPlugin(QObject *parent, const char* name) //, KApplication *Appl)
+ : FXPlugin(parent, name) //, m_Appl(Appl)
+{
+ m_config = new KSimpleConfig("ksayit_freeverbrc");
+
+}
+
+FreeverbPlugin::~FreeverbPlugin()
+{
+ delete m_config;
+}
+
+/** sets the Main application object
+*/
+void FreeverbPlugin::setApplication(KApplication *Appl)
+{
+ m_Appl = Appl;
+}
+
+
+/** returns the Name of the Plugin
+*/
+QString FreeverbPlugin::getName_KS() const
+{
+ return "Synth_FREEVERB";
+}
+
+/** returns a description of the plugin
+*/
+QString FreeverbPlugin::getDescription_KS() const
+{
+ return i18n("This is a freeverb effect.");
+}
+
+/** shows the GUI to configure the plugin
+*/
+bool FreeverbPlugin::showGUI_KS()
+{
+ FreeverbSetupImpl *dlg = new FreeverbSetupImpl(0, "Freeverb", true, m_config);
+ if ( !dlg ){
+ delete dlg;
+ return false;
+ }
+ dlg->exec();
+ delete dlg;
+
+ return true;
+}
+
+/** activate the effect
+*/
+long FreeverbPlugin::activate_KS(KArtsServer *server,
+ StereoEffectStack *fx_stack) const
+{
+ // kdDebug(100200) << "Aktiviere Synth_FREEVERB-Effekt" << endl;
+ Synth_FREEVERB fv = DynamicCast( server->server().createObject("Arts::Synth_FREEVERB") );
+ if ( !fv.isNull() ){
+ // kdDebug(100200) << "Filter angelegt" << endl;
+ // get filter parameter
+ m_config->setGroup("Synth_FREEVERB");
+ fv.roomsize( m_config->readDoubleNumEntry("roomsize", 50.0)/100.0 );
+ fv.damp ( m_config->readDoubleNumEntry("damp", 50.0 )/100.0 );
+ fv.wet ( m_config->readDoubleNumEntry("wet", 50.0 )/100.0 );
+ fv.dry ( m_config->readDoubleNumEntry("dry", 50.0 )/100.0 );
+ fv.width ( m_config->readDoubleNumEntry("width", 50.0 )/100.0 );
+
+ fv.start();
+ return fx_stack->insertBottom( fv, "Freeverb" );
+ }
+ return 0;
+}
+
+/** deactivates the effect
+*/
+bool FreeverbPlugin::deactivate_KS(StereoEffectStack *fx_stack,
+ long EffectID ) const
+{
+ // kdDebug(100200) << "Deaktiviere Synth_FREEVERB-Effekt" << endl;
+ if (EffectID!=0){
+ fx_stack->remove(EffectID);
+ }
+ return true;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#include "ksayitfreeverblib.moc"
diff --git a/ksayit/Freeverb_plugin/ksayitfreeverblib.h b/ksayit/Freeverb_plugin/ksayitfreeverblib.h
new file mode 100644
index 0000000..50bfa62
--- /dev/null
+++ b/ksayit/Freeverb_plugin/ksayitfreeverblib.h
@@ -0,0 +1,96 @@
+//
+// C++ Interface: ksayitfreeverblib
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef KSAYITFREEVERBLIB_H
+#define KSAYITFREEVERBLIB_H
+
+// QT includes
+#include <qobject.h>
+#include <qstringlist.h>
+
+// KDE includes
+#include <ksimpleconfig.h>
+#include <kapplication.h>
+#include <klibloader.h>
+#include <kinstance.h>
+
+#include "ksayit_fxplugin.h"
+
+class FreeverbPluginFactory : public KLibFactory
+{
+Q_OBJECT
+public:
+ // Consturctor
+ FreeverbPluginFactory(QObject *parent=0, const char* name=0);
+
+ // Destructor
+ virtual ~FreeverbPluginFactory(){ delete p_instance; };
+
+ QObject* createObject(QObject *parent=0, const char* name=0,
+ const char* className="QObject",
+ const QStringList &args=QStringList());
+
+private:
+ static KInstance* p_instance;
+
+};
+
+
+
+
+
+class FreeverbPlugin : public FXPlugin
+{
+Q_OBJECT
+public:
+ // Constructor
+ FreeverbPlugin(QObject *parent=0, const char* name=0); //, KApplication *Appl=0);
+
+ // Destructor
+ ~FreeverbPlugin();
+
+ /** sets the Main application object
+ */
+ void setApplication(KApplication *Appl);
+
+ /** returns the Name of the Plugin
+ */
+ QString getName_KS() const;
+
+ /** returns a description of the plugin
+ */
+ QString getDescription_KS() const;
+
+ /** shows the GUI to configure the plugin
+ */
+ bool showGUI_KS();
+
+ /** activate the effect
+ */
+ long activate_KS(KArtsServer *server,
+ StereoEffectStack *fx_stack) const;
+
+ /** deactivates the effect
+ */
+ bool deactivate_KS(StereoEffectStack *fx_stack,
+ long EffectID ) const;
+
+
+private:
+ KApplication *m_Appl;
+ KSimpleConfig *m_config;
+
+};
+
+
+
+#endif
+
diff --git a/ksayit/INSTALL b/ksayit/INSTALL
new file mode 100644
index 0000000..02a4a07
--- /dev/null
+++ b/ksayit/INSTALL
@@ -0,0 +1,167 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 4. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/ksayit/KTTSD_Lib/KTTSDlibSetup.ui b/ksayit/KTTSD_Lib/KTTSDlibSetup.ui
new file mode 100644
index 0000000..8c624e4
--- /dev/null
+++ b/ksayit/KTTSD_Lib/KTTSDlibSetup.ui
@@ -0,0 +1,121 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KTTSDlibSetup</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KTTSDlibSetup</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>528</width>
+ <height>364</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>KTTSD-Setup</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;If you would like to change the configuration of KTTSD please use the KDE Control Center or click the button below.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>kcm_Button</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Launch Control Center</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>kcm_Button</sender>
+ <signal>clicked()</signal>
+ <receiver>KTTSDlibSetup</receiver>
+ <slot>slotLaunchControlcenter()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot access="protected">slotLaunchControlcenter()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/ksayit/KTTSD_Lib/Makefile.am b/ksayit/KTTSD_Lib/Makefile.am
new file mode 100644
index 0000000..0a26093
--- /dev/null
+++ b/ksayit/KTTSD_Lib/Makefile.am
@@ -0,0 +1,23 @@
+INCLUDES = \
+ $(KTTS_KSPEECH_INCLUDE) \
+ $(all_includes)
+
+METASOURCES = AUTO
+libKTTSD_Lib_la_LDFLAGS = -no-undefined $(all_libraries) -version-info 0:1
+lib_LTLIBRARIES = libKTTSD_Lib.la
+libKTTSD_Lib_la_LIBADD = $(LIB_KDEUI) $(LIB_KDECORE)
+noinst_HEADERS = kttsdlib.h kttsdlibsetupimpl.h kttsdlibtalker2.h kdeexportfix.h
+
+kspeech_DIR = $(KTTS_KSPEECH_DIR)
+kspeechsink_DIR = $(KTTS_KSPEECH_DIR)
+
+libKTTSD_Lib_la_SOURCES = \
+ kspeech.stub kspeechsink.skel \
+ kttsdlib.cpp \
+ kttsdlibsetupimpl.cpp \
+ KTTSDlibSetup.ui \
+ kttsdlibtalker2.cpp
+AM_CXXFLAGS = -fPIC
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/libKTTSD.pot
diff --git a/ksayit/KTTSD_Lib/kdeexportfix.h b/ksayit/KTTSD_Lib/kdeexportfix.h
new file mode 100644
index 0000000..172dd94
--- /dev/null
+++ b/ksayit/KTTSD_Lib/kdeexportfix.h
@@ -0,0 +1,22 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ kdelibs < 3.3.2 had a bug in the KDE_EXPORT macro. This file fixes this
+ by undefining it.
+ -------------------
+ Copyright : (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <kdeversion.h>
+#if KDE_VERSION < KDE_MAKE_VERSION (3,3,2)
+#undef KDE_EXPORT
+#define KDE_EXPORT
+#endif
diff --git a/ksayit/KTTSD_Lib/kttsdlib.cpp b/ksayit/KTTSD_Lib/kttsdlib.cpp
new file mode 100644
index 0000000..224cd21
--- /dev/null
+++ b/ksayit/KTTSD_Lib/kttsdlib.cpp
@@ -0,0 +1,221 @@
+//
+// C++ Implementation: kttsdplugin
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+// #include <time.h> // nanosleep
+
+// Qt includes
+#include <qstring.h>
+#include <qstringlist.h>
+
+// KDE includes
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+
+// App specific includes
+#include "kttsdlib.h"
+#include "kttsdlibtalker2.h"
+#include "kttsdlibsetupimpl.h"
+
+
+KTTSDLib::KTTSDLib(QObject *parent, const char *name, KApplication *Appl)
+ : QObject(parent, name), m_Appl(Appl)
+{
+ KGlobal::locale()->insertCatalogue("libKTTSD");
+ m_talker = new kttsdlibtalker2(static_cast<QObject*>(this), "kttsdlibtalker");
+ connect(m_talker, SIGNAL(signalTextFinished(const uint)),
+ this, SLOT(slotTextFinished(const uint)) );
+ connect(m_talker, SIGNAL(signalTextStopped(const uint)),
+ this, SLOT(slotTextStopped(const uint)) );
+ connect(m_talker, SIGNAL(signalTextStarted(const uint)),
+ this, SLOT(slotTextStarted(const uint)) );
+
+ // reset list of currently processed jobs
+ while ( !jobList.empty() ){
+ jobList.pop();
+ }
+
+ // initialize the talker
+ m_talker->KTTSD_init(m_Appl);
+
+ // some presets
+ // m_config = new KSimpleConfig("ksayit_kttsdpluginrc");
+ // m_usersetupimpl = NULL;
+}
+
+
+KTTSDLib::~KTTSDLib()
+{
+ // delete m_config;
+}
+
+
+QString KTTSDLib::getName() const
+{
+ return "KDE KTTSD";
+}
+
+
+QString KTTSDLib::getDescription() const
+{
+ QString str;
+ str = i18n("<qt><big><u>Description:</u></big><br>");
+ str += i18n("This plugin uses the KDE TTS Daemon for speech output.");
+
+ return str;
+}
+
+
+int KTTSDLib::getActions()
+{
+ return ACTIONS::PLAY | ACTIONS::STOP | ACTIONS::PAUSE | ACTIONS::FFWD | ACTIONS::FREV;
+}
+
+
+int KTTSDLib::getStatus() const
+{
+ return TTS::AUDIOFILE;
+}
+
+
+const QWidget* KTTSDLib::getGUI(QFrame *frame)
+{
+ kdDebug(100200) << "KTTSDLib::getGUI()" << endl;
+
+ return new KTTSDlibSetupImpl( frame, "kttsdlibsetup" );
+}
+
+
+void KTTSDLib::reloadConfiguration()
+{
+ kdDebug(100200) << "KTTSDLib::reloadConfiguration()" << endl;
+ // N.A.
+}
+
+
+bool KTTSDLib::saveWasClicked() const
+{
+ kdDebug(100200) << "KTTSDLib::saveWasClicked()" << endl;
+ // N.A.
+
+ return true;
+}
+
+
+void KTTSDLib::setText(const QString &text)
+{
+ kdDebug(100200) << "KTTSDLib::setText()" << endl;
+
+ uint jobNum = m_talker->KTTSD_setText(text, "");
+ jobList.push(jobNum);
+}
+
+
+
+void KTTSDLib::sayText()
+{
+ kdDebug(100200) << "KTTSDLib::sayText()" << endl;
+
+ if( !jobList.empty() ){
+ m_curJobNum = jobList.front();
+ jobList.pop();
+ kdDebug(100200) << " Starting job No.: " << m_curJobNum << endl;
+ m_talker->KTTSD_startText( m_curJobNum );
+ }
+}
+
+
+void KTTSDLib::removeAllJobsFromList()
+{
+ kdDebug(100200) << "KTTSDLib::removeAllJobsFromList()" << endl;
+
+ m_talker->KTTSD_removeText(m_curJobNum);
+
+ while( !jobList.empty() ){
+ uint job = jobList.front();
+ jobList.pop();
+ kdDebug(100200) << "*** removing... " << job << endl;
+ m_talker->KTTSD_removeText( job );
+ }
+}
+
+void KTTSDLib::stop()
+{
+ kdDebug(100200) << "***** KTTSDLib::stop(" << m_curJobNum << ")" << endl;
+ m_talker->KTTSD_stopText(m_curJobNum);
+ removeAllJobsFromList();
+ emit signalFinished();
+}
+
+
+void KTTSDLib::pause()
+{
+ kdDebug(100200) << "void KTTSDLib::pause(" << m_curJobNum << ")" << endl;
+
+ m_talker->KTTSD_pauseText( m_curJobNum );
+}
+
+
+void KTTSDLib::resume()
+{
+ kdDebug(100200) << "void KTTSDLib::resume(" << m_curJobNum << ")" << endl;
+
+ m_talker->KTTSD_resumeText( m_curJobNum );
+}
+
+
+void KTTSDLib::ffwd()
+{
+ kdDebug(100200) << "void KTTSDLib::ffwd(" << m_curJobNum << ")" << endl;
+ m_talker->KTTSD_moveRelTextSentence(1, m_curJobNum);
+}
+
+
+void KTTSDLib::frev()
+{
+ kdDebug(100200) << "void KTTSDLib::frev(" << m_curJobNum << ")" << endl;
+ m_talker->KTTSD_moveRelTextSentence(-1, m_curJobNum);
+}
+
+
+//////////////////////////////////////
+// Signals from the talker
+//////////////////////////////////////
+
+void KTTSDLib::slotTextFinished(const uint job)
+{
+ kdDebug(100200) << "---- KTTSDLib::slotTextFinished(" << job << ")" << endl;
+
+ // check if List is empty. If yes, send signalFinished().
+ if ( jobList.empty() ){
+ kdDebug(100200) << " All jobs processed." << endl;
+ emit signalFinished();
+ } else {
+ sayText();
+ }
+}
+
+void KTTSDLib::slotTextStopped(const uint job)
+{
+ kdDebug(100200) << "---- KTTSDLib::slotTextStopped(" << job << ")" << endl;
+ // removeAllJobsFromList();
+ // emit signalFinished();
+}
+
+
+void KTTSDLib::slotTextStarted(const uint job)
+{
+ kdDebug(100200) << "---- KTTSDLib::slotTextStarted(" << job << ")" << endl;
+ // m_curJobNum = job;
+}
+
+#include "kttsdlib.moc"
diff --git a/ksayit/KTTSD_Lib/kttsdlib.h b/ksayit/KTTSD_Lib/kttsdlib.h
new file mode 100644
index 0000000..6d8de9b
--- /dev/null
+++ b/ksayit/KTTSD_Lib/kttsdlib.h
@@ -0,0 +1,119 @@
+//
+// C++ Interface: kttsdplugin
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef KTTSDLIB_H
+#define KTTSDLIB_H
+
+// stl
+#include <queue>
+using namespace std;
+
+// QT includes
+#include <qobject.h>
+#include <qwidget.h>
+#include <qframe.h>
+
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+
+// KDE includes
+#include <kapplication.h>
+
+// App specific includes
+
+
+namespace TTS {
+ enum {AUDIOFILE=1};
+}
+
+namespace ACTIONS {
+ enum {PLAY=1, STOP=2, PAUSE=4, FFWD=8, FREV=16};
+}
+
+
+// forward declarations
+class kttsdlibtalker2;
+
+/**
+@author Robert Vogl
+*/
+class KDE_EXPORT KTTSDLib : public QObject
+{
+Q_OBJECT
+signals:
+ /** Emitted when the plugin has been finished speeking.
+ */
+ void signalFinished();
+
+public slots:
+ /** Called from the talker on textFinished().
+ * \param job The number of the finished job.
+ */
+ void slotTextFinished(const uint job);
+
+ /** Called from the talker on textStopped().
+ * \param job The number of the stopped job.
+ */
+ void slotTextStopped(const uint job);
+
+ /** Called from the talker on textStarted().
+ * \param job The number of the stopped job.
+ */
+ void slotTextStarted(const uint job);
+
+public:
+ KTTSDLib(QObject *parent=0, const char *name=0, KApplication *Appl=0);
+
+ ~KTTSDLib();
+
+ /** Reimplementations from the base class.
+ */
+ QString getName() const;
+
+ QString getDescription() const;
+
+ int getActions();
+
+ const QWidget* getGUI(QFrame *frame);
+
+ void reloadConfiguration();
+
+ bool saveWasClicked() const;
+
+ void setText(const QString &text);
+
+ void sayText();
+
+ int getStatus() const;
+
+ void stop();
+
+ void pause();
+
+ void resume();
+
+ void ffwd();
+
+ void frev();
+
+private slots:
+ void removeAllJobsFromList();
+
+private:
+ KApplication *m_Appl;
+ kttsdlibtalker2 *m_talker;
+ uint m_curJobNum;
+ typedef queue<uint> jobListType;
+ jobListType jobList;
+
+};
+
+#endif
diff --git a/ksayit/KTTSD_Lib/kttsdlibsetupimpl.cpp b/ksayit/KTTSD_Lib/kttsdlibsetupimpl.cpp
new file mode 100644
index 0000000..0c7bc8f
--- /dev/null
+++ b/ksayit/KTTSD_Lib/kttsdlibsetupimpl.cpp
@@ -0,0 +1,76 @@
+//
+// C++ Implementation: kttsdlibsetupimpl
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <stdio.h>
+
+// Qt includes
+#include <qpushbutton.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+// App specific includes
+#include "kttsdlibsetupimpl.h"
+
+KTTSDlibSetupImpl::KTTSDlibSetupImpl(QWidget *parent, const char *name)
+ : KTTSDlibSetup(parent, name)
+{
+}
+
+
+KTTSDlibSetupImpl::~KTTSDlibSetupImpl()
+{
+}
+
+
+void KTTSDlibSetupImpl::slotLaunchControlcenter()
+{
+ kdDebug(100200) << "KTTSDlibSetupImpl::slotLaunchControlCenter()" << endl;
+
+ // check if controllcenter module for KTTSD exists
+ FILE *fp;
+ char cmdresult[20];
+
+ // if ( (fp = popen("kcmshell --list | grep kcmkttsmgr", "r")) != NULL){
+ if ( (fp = popen("kcmshell --list | grep kcmkttsd", "r")) != NULL){
+ fgets(cmdresult, 18, fp);
+ pclose(fp);
+ }
+ if ( !QCString(cmdresult).contains("kcmkttsd") ){
+ QString error = i18n("Control Center Module for KTTSD not found.");
+ KMessageBox::sorry(this, error, i18n("Problem"));
+ return;
+ }
+
+ // invoke the Control Center Module
+ KProcess *kcmproc = new KProcess();
+ connect(kcmproc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotKCMProcessExited(KProcess*)) );
+ (*kcmproc) << "kcmshell";
+ (*kcmproc) << "kcmkttsd";
+ kcmproc->start(KProcess::NotifyOnExit);
+
+ kcm_Button->setEnabled(false);
+}
+
+
+void KTTSDlibSetupImpl::slotKCMProcessExited(KProcess *p)
+{
+ kdDebug(100200) << "slotKCMProcessExited()" << endl;
+ kcm_Button->setEnabled(true);
+}
+
+
+
+#include "kttsdlibsetupimpl.moc"
diff --git a/ksayit/KTTSD_Lib/kttsdlibsetupimpl.h b/ksayit/KTTSD_Lib/kttsdlibsetupimpl.h
new file mode 100644
index 0000000..1fcf585
--- /dev/null
+++ b/ksayit/KTTSD_Lib/kttsdlibsetupimpl.h
@@ -0,0 +1,46 @@
+//
+// C++ Interface: kttsdsetupimpl
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef KTTSDSETUPIMPL_H
+#define KTTSDSETUPIMPL_H
+
+// Qt includes
+
+// KDE includes
+#include <kprocess.h>
+
+// App specific includes
+#include "KTTSDlibSetup.h"
+
+/**
+@author Robert Vogl
+*/
+class KTTSDlibSetupImpl : public KTTSDlibSetup
+{
+Q_OBJECT
+public:
+ KTTSDlibSetupImpl(QWidget *parent = 0, const char *name = 0);
+
+ ~KTTSDlibSetupImpl();
+
+protected slots:
+ /** Connected with the button to launch the controlcenter.
+ */
+ void slotLaunchControlcenter();
+
+private slots:
+
+ /** Called when the Control Center Module was closed.
+ */
+ void slotKCMProcessExited(KProcess *p);
+};
+
+#endif
diff --git a/ksayit/KTTSD_Lib/kttsdlibtalker2.cpp b/ksayit/KTTSD_Lib/kttsdlibtalker2.cpp
new file mode 100644
index 0000000..808f8f2
--- /dev/null
+++ b/ksayit/KTTSD_Lib/kttsdlibtalker2.cpp
@@ -0,0 +1,166 @@
+//
+// C++ Implementation: kttsdlibtalker2
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <unistd.h> //sleep
+
+// Qt includes
+#include <qstring.h>
+
+// KDE includes
+#include <kdebug.h>
+
+// App specific includes
+#include "kttsdlibtalker2.h"
+
+kttsdlibtalker2::kttsdlibtalker2(QObject *parent, const char *name)
+ : QObject(parent, name), DCOPStub("kttsd", "KSpeech")
+{
+ m_client = NULL;
+
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textStarted(QCString, uint)",
+ "textStarted(QCString, uint)", false);
+
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textFinished(QCString, uint)",
+ "textFinished(QCString, uint)", false);
+
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textStopped(QCString, uint)",
+ "textStopped(QCString, uint)", false);
+
+}
+
+
+kttsdlibtalker2::~kttsdlibtalker2()
+{
+}
+
+
+void kttsdlibtalker2::KTTSD_init(KApplication *Appl)
+{
+ kdDebug(100200) << "kttsdlibtalker2::KTTSD_init()" << endl;
+
+ m_client = Appl->dcopClient();
+ if ( !m_client->isApplicationRegistered("kttsd")){
+ QString error;
+ if ( Appl->startServiceByDesktopName("kttsd", QStringList(), &error) ){
+ // throw(error);
+ kdDebug() << "Starting KTTSD failed with message " << error << endl;
+ }
+ }
+ m_objID = m_client->appId();
+
+ kdDebug(100200) << " sucessfully registered. objID: " << m_objID << endl;
+}
+
+
+uint kttsdlibtalker2::KTTSD_setText(const QString &text, QString lang)
+{
+ kdDebug(100200) << "kttsdlibtalker2::KTTSD_setText()" << endl;
+ uint jobNum = setText(text, lang);
+ return jobNum;
+}
+
+
+void kttsdlibtalker2::KTTSD_startText(uint jobNum)
+{
+ kdDebug(100200) << "kttsdlibtalker2::KTTSD_startText()" << endl;
+ startText(jobNum);
+}
+
+
+void kttsdlibtalker2::KTTSD_stopText(uint jobNum)
+{
+ kdDebug(100200) << "kttsdlibtalker2::KTTSD_stopText()" << endl;
+ stopText(jobNum);
+}
+
+
+void kttsdlibtalker2::KTTSD_pauseText(uint jobNum)
+{
+ kdDebug(100200) << "kttsdlibtalker2::KTTSD_pauseText()" << endl;
+ pauseText(jobNum);
+}
+
+
+void kttsdlibtalker2::KTTSD_resumeText(uint jobNum)
+{
+ kdDebug(100200) << "kttsdlibtalker2::KTTSD_resumeText()" << endl;
+ resumeText(jobNum);
+}
+
+
+uint kttsdlibtalker2::KTTSD_moveRelTextSentence(const int n, const uint jobNum)
+{
+ kdDebug(100200) << "kttsdlibtalker2::KTTSD_moveRelTextSentence()" << endl;
+ uint seqNum = moveRelTextSentence(n, jobNum);
+ return seqNum;
+}
+
+
+void kttsdlibtalker2::KTTSD_removeText(uint jobNum)
+{
+ kdDebug(100200) << "kttsdlibtalker2::KTTSD_removeText()" << endl;
+ removeText(jobNum);
+}
+
+
+int kttsdlibtalker2::KTTSD_getTextJobState(uint jobNum)
+{
+
+ return 0;
+}
+
+
+int kttsdlibtalker2::KTTSD_getCurrentTextJob()
+{
+
+ return 0;
+}
+
+
+
+////////////////////////////////////////////
+// DCOP signals
+////////////////////////////////////////////
+
+ASYNC kttsdlibtalker2::textStarted(const QCString &appID,
+ const uint jobNum)
+{
+ kdDebug(100200) << "*** kttsdlibtalker2::textStarted()" << endl;
+ if ( appID != m_objID )
+ return;
+ emit signalTextStarted(jobNum);
+}
+
+
+ASYNC kttsdlibtalker2::textFinished(const QCString &appID,
+ const uint jobNum)
+{
+ kdDebug(100200) << "*** kttsdlibtalker2::textFinished()" << endl;
+ if ( appID != m_objID )
+ return;
+ emit signalTextFinished(jobNum);
+}
+
+
+ASYNC kttsdlibtalker2::textStopped(const QCString &appID,
+ const uint jobNum)
+{
+ kdDebug(100200) << "*** kttsdlibtalker2::textStopped()" << endl;
+ if ( appID != m_objID )
+ return;
+ emit signalTextStopped(jobNum);
+}
+
+#include "kttsdlibtalker2.moc"
diff --git a/ksayit/KTTSD_Lib/kttsdlibtalker2.h b/ksayit/KTTSD_Lib/kttsdlibtalker2.h
new file mode 100644
index 0000000..e39f1c8
--- /dev/null
+++ b/ksayit/KTTSD_Lib/kttsdlibtalker2.h
@@ -0,0 +1,101 @@
+//
+// C++ Interface: kttsdlibtalker2
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef KTTSDLIBTALKER2_H
+#define KTTSDLIBTALKER2_H
+
+// Qt includes
+#include <qobject.h>
+#include <qcstring.h>
+
+#include <kspeech_stub.h>
+#include <kspeechsink.h>
+
+// KDE includes
+#include <kapplication.h>
+#include <dcopclient.h>
+
+/**
+@author Robert Vogl
+*/
+class kttsdlibtalker2 : public QObject, public KSpeech_stub, virtual public KSpeechSink
+{
+Q_OBJECT
+
+signals:
+ void signalTextStarted(const uint);
+ void signalTextFinished(const uint);
+ void signalTextStopped(const uint);
+
+public:
+ kttsdlibtalker2(QObject *parent = 0, const char *name = 0);
+
+ ~kttsdlibtalker2();
+
+ /** Intializes the DCOP interface.
+ */
+ void KTTSD_init(KApplication *Appl);
+
+ /** See \p KSpeech Class Reference. Returns the job number.
+ */
+ uint KTTSD_setText(const QString &text, QString lang);
+
+ /** See \p KSpeech Class Reference.
+ */
+ void KTTSD_startText(uint jobNum);
+
+ /** See \p KSpeech Class Reference.
+ */
+ void KTTSD_stopText(uint jobNum);
+
+ /** See \p KSpeech Class Reference.
+ */
+ void KTTSD_pauseText(uint jobNum);
+
+ /** See \p KSpeech Class Reference.
+ */
+ void KTTSD_resumeText(uint jobNum);
+
+ /** See \p KSpeech Class Reference.
+ */
+ uint KTTSD_moveRelTextSentence(const int n, const uint jobNum = 0);
+
+ /** See \p KSpeech Class Reference.
+ */
+ int KTTSD_getTextJobState(uint jobNum);
+
+ /** See \p KSpeech Class Reference.
+ */
+ void KTTSD_removeText(uint jobNum);
+
+ /** See \p KSpeech Class Reference.
+ */
+ int KTTSD_getCurrentTextJob();
+
+
+protected:
+ ////////////////////////////////////////////
+ // Slots for DCOP signals
+ ////////////////////////////////////////////
+ ASYNC textStarted(const QCString &appID, const uint jobNum);
+ ASYNC textFinished(const QCString &appID, const uint jobNum);
+ ASYNC textStopped(const QCString &appID, const uint jobNum);
+
+private:
+ QCString m_objID;
+ KApplication *m_Appl;
+ DCOPClient *m_client;
+ uint m_jobNum;
+
+
+};
+
+#endif
diff --git a/ksayit/Makefile.am b/ksayit/Makefile.am
new file mode 100644
index 0000000..80c4d86
--- /dev/null
+++ b/ksayit/Makefile.am
@@ -0,0 +1,5 @@
+if include_ksayit_audio_plugins
+ freeverbplugin_DIR = Freeverb_plugin
+endif
+
+SUBDIRS = KTTSD_Lib src $(freeverbplugin_DIR)
diff --git a/ksayit/NEWS b/ksayit/NEWS
new file mode 100644
index 0000000..0519ecb
--- /dev/null
+++ b/ksayit/NEWS
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/ksayit/README b/ksayit/README
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ksayit/README
@@ -0,0 +1 @@
+
diff --git a/ksayit/TODO b/ksayit/TODO
new file mode 100644
index 0000000..0519ecb
--- /dev/null
+++ b/ksayit/TODO
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/ksayit/configure.in.in b/ksayit/configure.in.in
new file mode 100644
index 0000000..618f5dc
--- /dev/null
+++ b/ksayit/configure.in.in
@@ -0,0 +1,16 @@
+#MIN_CONFIG(3.0.0)
+
+if test "x$build_arts" = "xno"; then
+ DO_NOT_COMPILE="$DO_NOT_COMPILE ksayit"
+fi
+
+AM_INIT_AUTOMAKE(ksayit, 0.8.3)
+AC_C_BIGENDIAN
+AC_CHECK_KDEMAXPATHLEN
+
+CXXFLAGS="$CXXFLAGS $USE_EXCEPTIONS"
+CXXFLAGS="$CXXFLAGS $USE_RTTI" dnl (if you also want rtti)
+
+if test "x$build_arts" = "xno"; then
+· DO_NOT_COMPILE="$DO_NOT_COMPILE ksayit"
+fi
diff --git a/ksayit/ksayit.kdevelop b/ksayit/ksayit.kdevelop
new file mode 100644
index 0000000..2d26220
--- /dev/null
+++ b/ksayit/ksayit.kdevelop
@@ -0,0 +1,196 @@
+<?xml version = '1.0'?>
+<kdevelop>
+ <general>
+ <author>Robert Vogl</author>
+ <email>voglrobe@web.de</email>
+ <version>0.8.3</version>
+ <projectmanagement>KDevKDEAutoProject</projectmanagement>
+ <primarylanguage>C++</primarylanguage>
+ <keywords>
+ <keyword>C++</keyword>
+ <keyword>Code</keyword>
+ <keyword>Qt</keyword>
+ <keyword>KDE</keyword>
+ </keywords>
+ <projectdirectory>.</projectdirectory>
+ <absoluteprojectpath>false</absoluteprojectpath>
+ <description/>
+ <ignoreparts>
+ <part>KDevCTags2</part>
+ <part>Unterstützung für Perforce (KDevelop)</part>
+ <part>Unterstützung für Subversion (KDevelop)</part>
+ <part>Unterstützung für CTags (KDevelop)</part>
+ <part>Unterstützung für CVSService (KDevelop)</part>
+ </ignoreparts>
+ <secondaryLanguages/>
+ </general>
+ <kdevautoproject>
+ <general>
+ <activetarget>KTTSD_Lib/libKTTSD_Lib.la</activetarget>
+ <useconfiguration>debug</useconfiguration>
+ </general>
+ <run>
+ <mainprogram>src/ksayit</mainprogram>
+ <directoryradio>executable</directoryradio>
+ <runarguments>
+ <ksayit/>
+ </runarguments>
+ <customdirectory>/</customdirectory>
+ <programargs/>
+ <terminal>false</terminal>
+ <autocompile>true</autocompile>
+ <envvars/>
+ </run>
+ <configurations>
+ <optimized>
+ <builddir>optimized</builddir>
+ <ccompiler>kdevgccoptions</ccompiler>
+ <cxxcompiler>kdevgppoptions</cxxcompiler>
+ <f77compiler>kdevg77options</f77compiler>
+ <cxxflags>-O2 -g0</cxxflags>
+ </optimized>
+ <debug>
+ <configargs>--enable-debug=full</configargs>
+ <builddir>debug</builddir>
+ <ccompiler>kdevgccoptions</ccompiler>
+ <cxxcompiler>kdevgppoptions</cxxcompiler>
+ <f77compiler>kdevg77options</f77compiler>
+ <cxxflags>-O0</cxxflags>
+ <topsourcedir/>
+ <cppflags/>
+ <ldflags/>
+ <ccompilerbinary/>
+ <cxxcompilerbinary/>
+ <f77compilerbinary/>
+ <cflags/>
+ <f77flags/>
+ <envvars/>
+ </debug>
+ </configurations>
+ <make>
+ <envvars>
+ <envvar value="1" name="WANT_AUTOCONF_2_5" />
+ <envvar value="1" name="WANT_AUTOMAKE_1_6" />
+ </envvars>
+ <abortonerror>true</abortonerror>
+ <numberofjobs>1</numberofjobs>
+ <dontact>false</dontact>
+ <makebin/>
+ <prio>0</prio>
+ </make>
+ </kdevautoproject>
+ <kdevfileview>
+ <groups>
+ <group pattern="*.cpp;*.cxx;*.h" name="Sources" />
+ <group pattern="*.ui" name="User Interface" />
+ <group pattern="*.png" name="Icons" />
+ <group pattern="*.po;*.ts" name="Translations" />
+ <group pattern="*" name="Others" />
+ <hidenonprojectfiles>false</hidenonprojectfiles>
+ <hidenonlocation>false</hidenonlocation>
+ </groups>
+ <tree>
+ <hidepatterns>*.o,*.lo,CVS</hidepatterns>
+ <hidenonprojectfiles>false</hidenonprojectfiles>
+ </tree>
+ </kdevfileview>
+ <kdevdoctreeview>
+ <ignoretocs>
+ <toc>ada</toc>
+ <toc>ada_bugs_gcc</toc>
+ <toc>bash</toc>
+ <toc>bash_bugs</toc>
+ <toc>clanlib</toc>
+ <toc>w3c-dom-level2-html</toc>
+ <toc>fortran_bugs_gcc</toc>
+ <toc>gnome1</toc>
+ <toc>gnustep</toc>
+ <toc>gtk</toc>
+ <toc>gtk_bugs</toc>
+ <toc>haskell</toc>
+ <toc>haskell_bugs_ghc</toc>
+ <toc>java_bugs_gcc</toc>
+ <toc>java_bugs_sun</toc>
+ <toc>pascal_bugs_fp</toc>
+ <toc>php</toc>
+ <toc>php_bugs</toc>
+ <toc>perl</toc>
+ <toc>perl_bugs</toc>
+ <toc>python</toc>
+ <toc>python_bugs</toc>
+ <toc>ruby</toc>
+ <toc>ruby_bugs</toc>
+ <toc>sdl</toc>
+ <toc>w3c-svg</toc>
+ <toc>sw</toc>
+ <toc>w3c-uaag10</toc>
+ <toc>wxwidgets_bugs</toc>
+ <toc>opengl</toc>
+ <toc>wxwindows_bugs</toc>
+ </ignoretocs>
+ <ignoreqt_xml>
+ <toc>qmake User Guide</toc>
+ </ignoreqt_xml>
+ <projectdoc>
+ <userdocDir>html/</userdocDir>
+ <apidocDir>html/</apidocDir>
+ </projectdoc>
+ <ignoredoxygen/>
+ <ignorekdocs/>
+ <ignoredevhelp/>
+ </kdevdoctreeview>
+ <kdevdebugger>
+ <general>
+ <dbgshell>libtool</dbgshell>
+ <programargs/>
+ <gdbpath/>
+ <configGdbScript/>
+ <runShellScript/>
+ <runGdbScript/>
+ <breakonloadinglibs>true</breakonloadinglibs>
+ <separatetty>false</separatetty>
+ <floatingtoolbar>false</floatingtoolbar>
+ </general>
+ <display>
+ <staticmembers>false</staticmembers>
+ <demanglenames>true</demanglenames>
+ <outputradix>10</outputradix>
+ </display>
+ </kdevdebugger>
+ <kdevfilecreate>
+ <filetypes/>
+ <useglobaltypes>
+ <type ext="ui" />
+ <type ext="cpp" />
+ <type ext="h" />
+ </useglobaltypes>
+ </kdevfilecreate>
+ <kdevcppsupport>
+ <references/>
+ <codecompletion>
+ <includeGlobalFunctions>true</includeGlobalFunctions>
+ <includeTypes>true</includeTypes>
+ <includeEnums>true</includeEnums>
+ <includeTypedefs>false</includeTypedefs>
+ <automaticCodeCompletion>true</automaticCodeCompletion>
+ <automaticArgumentsHint>true</automaticArgumentsHint>
+ <automaticHeaderCompletion>true</automaticHeaderCompletion>
+ <codeCompletionDelay>250</codeCompletionDelay>
+ <argumentsHintDelay>400</argumentsHintDelay>
+ <headerCompletionDelay>250</headerCompletionDelay>
+ </codecompletion>
+ </kdevcppsupport>
+ <cppsupportpart>
+ <filetemplates>
+ <interfacesuffix>.h</interfacesuffix>
+ <implementationsuffix>.cpp</implementationsuffix>
+ </filetemplates>
+ </cppsupportpart>
+ <kdevdocumentation>
+ <projectdoc>
+ <docsystem/>
+ <docurl/>
+ <usermanualurl/>
+ </projectdoc>
+ </kdevdocumentation>
+</kdevelop>
diff --git a/ksayit/src/ContextMenus.xml b/ksayit/src/ContextMenus.xml
new file mode 100644
index 0000000..201e8ec
--- /dev/null
+++ b/ksayit/src/ContextMenus.xml
@@ -0,0 +1,100 @@
+<?xml version = '1.0' encoding = 'ISO-8859-1'?>
+<KSayItContextActions>
+ <Item editable="no" id="RobDocument">
+ <Submenu name="New">
+ <Action qty="1">BookInfo</Action>
+ <Action qty="n">Chapter</Action>
+ </Submenu>
+ </Item>
+ <Item editable="no" id="BookInfo">
+ <Submenu name="New">
+ <Action qty="1">KeywordSet</Action>
+ <Action qty="1">Abstract</Action>
+ <Action qty="1">AuthorGroup</Action>
+ <Action qty="1">Date</Action>
+ <Action qty="1">ReleaseInfo</Action>
+ </Submenu>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="AuthorGroup">
+ <Submenu name="New">
+ <Action qty="n">Author</Action>
+ </Submenu>
+ <Action qty="n">Rename</Action>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="KeywordSet">
+ <Submenu name="New">
+ <Action qty="n">Keyword</Action>
+ </Submenu>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="yes" maxlines="1" id="Keyword">
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="yes" maxlines="1" id="Author">
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="yes" maxlines="1" id="Date">
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="yes" maxlines="1" id="ReleaseInfo">
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="Abstract">
+ <Submenu name="New">
+ <Action qty="n">Paragraph</Action>
+ </Submenu>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="Chapter">
+ <Submenu name="New">
+ <Action qty="n">Paragraph</Action>
+ <Action qty="n">Section_1</Action>
+ </Submenu>
+ <Action qty="n">Rename</Action>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="Sect1">
+ <Submenu name="New">
+ <Action qty="n">Paragraph</Action>
+ <Action qty="n">Section_2</Action>
+ </Submenu>
+ <Action qty="n">Rename</Action>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="Sect2">
+ <Submenu name="New">
+ <Action qty="n">Paragraph</Action>
+ <Action qty="n">Section_3</Action>
+ </Submenu>
+ <Action qty="n">Rename</Action>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="Sect3">
+ <Submenu name="New">
+ <Action qty="n">Paragraph</Action>
+ <Action qty="n">Section_4</Action>
+ </Submenu>
+ <Action qty="n">Rename</Action>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="Sect4">
+ <Submenu name="New">
+ <Action qty="n">Paragraph</Action>
+ <Action qty="n">Section_5</Action>
+ </Submenu>
+ <Action qty="n">Rename</Action>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="no" id="Sect5">
+ <Submenu name="New">
+ <Action qty="n">Paragraph</Action>
+ </Submenu>
+ <Action qty="n">Rename</Action>
+ <Action qty="n">Delete</Action>
+ </Item>
+ <Item editable="yes" maxlines="-1" id="Para">
+ <Action qty="n">Delete</Action>
+ </Item>
+</KSayItContextActions>
diff --git a/ksayit/src/DocTreeView.ui b/ksayit/src/DocTreeView.ui
new file mode 100644
index 0000000..14e5f09
--- /dev/null
+++ b/ksayit/src/DocTreeView.ui
@@ -0,0 +1,158 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>DocTreeView</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>DocTreeView</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>467</width>
+ <height>331</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>200</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Document Contents</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <property name="resizeMode">
+ <enum>Minimum</enum>
+ </property>
+ <widget class="KListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>Chapter</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Info</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Page</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Hidden</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>false</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>listView</cstring>
+ </property>
+ <property name="resizePolicy">
+ <enum>Default</enum>
+ </property>
+ <property name="selectionMode" stdset="0">
+ <enum>NoSelection</enum>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>true</bool>
+ </property>
+ <property name="itemsMovable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>listView</sender>
+ <signal>clicked(QListViewItem*)</signal>
+ <receiver>DocTreeView</receiver>
+ <slot>slotItemClicked(QListViewItem*)</slot>
+ </connection>
+ <connection>
+ <sender>listView</sender>
+ <signal>rightButtonPressed(QListViewItem*,const QPoint&amp;,int)</signal>
+ <receiver>DocTreeView</receiver>
+ <slot>slotRightButtonPressed(QListViewItem*,const QPoint&amp;,int)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">DocTreeView.ui.h</include>
+</includes>
+<signals>
+ <signal>signalContentChanged(const QString &amp;)</signal>
+ <signal>signalAllNodesProcessed()</signal>
+ <signal>signalSetText(const QString &amp;)</signal>
+ <signal>signalEnableTextedit(bool)</signal>
+ <signal>signalNotifyBookmarkManager(const QString&amp;, const QString &amp;)</signal>
+ <signal>signalSetBookmarkFilename(const QString&amp;)</signal>
+ <signal>signalChangeBookmarkFilename(const QString &amp;)</signal>
+ <signal>signalDeleteBookmark(const QString&amp;, const QString&amp;)</signal>
+</signals>
+<slots>
+ <slot>slotItemClicked( QListViewItem * )</slot>
+ <slot access="protected">slotRenameItem()</slot>
+ <slot access="protected">slotDeleteItem()</slot>
+ <slot access="protected">slotNewBookInfo()</slot>
+ <slot access="protected">slotNewChapter()</slot>
+ <slot access="protected">slotNewKeywordSet()</slot>
+ <slot access="protected">slotNewKeyword()</slot>
+ <slot access="protected">slotNewAbstract()</slot>
+ <slot access="protected">slotNewAuthorGroup()</slot>
+ <slot access="protected">slotNewAuthor()</slot>
+ <slot access="protected">slotNewDate()</slot>
+ <slot access="protected">slotNewReleaseInfo()</slot>
+ <slot access="protected">slotNewTitle()</slot>
+ <slot access="protected">slotNewParagraph()</slot>
+ <slot access="protected">slotNewSection_1()</slot>
+ <slot access="protected">slotNewSection_2()</slot>
+ <slot access="protected">slotNewSection_3()</slot>
+ <slot access="protected">slotNewSection_4()</slot>
+ <slot access="protected">slotNewSection_5()</slot>
+ <slot>slotRightButtonPressed( QListViewItem * i, const QPoint &amp;, int )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/ksayit/src/DocTreeView.ui.h b/ksayit/src/DocTreeView.ui.h
new file mode 100644
index 0000000..39720c1
--- /dev/null
+++ b/ksayit/src/DocTreeView.ui.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you want to add, delete, or rename functions or slots, use
+** Qt Designer to update this file, preserving your code.
+**
+** You should not define a constructor or destructor in this file.
+** Instead, write your code in functions called init() and destroy().
+** These will automatically be called by the form's constructor and
+** destructor.
+*****************************************************************************/
+
+
+void DocTreeView::slotItemClicked( QListViewItem * )
+{
+
+}
+
+
+
+void DocTreeView::slotRenameItem()
+{
+
+}
+
+
+void DocTreeView::slotDeleteItem()
+{
+
+}
+
+
+void DocTreeView::slotNewBookInfo()
+{
+
+}
+
+
+void DocTreeView::slotNewChapter()
+{
+
+}
+
+
+void DocTreeView::slotNewKeywordSet()
+{
+
+}
+
+
+void DocTreeView::slotNewKeyword()
+{
+
+}
+
+
+void DocTreeView::slotNewAbstract()
+{
+
+}
+
+
+void DocTreeView::slotNewAuthorGroup()
+{
+
+}
+
+
+void DocTreeView::slotNewAuthor()
+{
+
+}
+
+
+void DocTreeView::slotNewDate()
+{
+
+}
+
+
+void DocTreeView::slotNewReleaseInfo()
+{
+
+}
+
+
+void DocTreeView::slotNewTitle()
+{
+
+}
+
+
+void DocTreeView::slotNewParagraph()
+{
+
+}
+
+
+void DocTreeView::slotNewSection_1()
+{
+
+}
+
+
+void DocTreeView::slotNewSection_2()
+{
+
+}
+
+
+void DocTreeView::slotNewSection_3()
+{
+
+}
+
+
+void DocTreeView::slotNewSection_4()
+{
+
+}
+
+
+void DocTreeView::slotNewSection_5()
+{
+
+}
+
+
+void DocTreeView::slotRightButtonPressed( QListViewItem *i, const QPoint &, int )
+{
+
+}
diff --git a/ksayit/src/KSayItView.ui b/ksayit/src/KSayItView.ui
new file mode 100644
index 0000000..4ffa9b9
--- /dev/null
+++ b/ksayit/src/KSayItView.ui
@@ -0,0 +1,69 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KSayItView</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KSayItView</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>422</width>
+ <height>441</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <widget class="KTextEdit" row="0" column="0">
+ <property name="name">
+ <cstring>TextEdit</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>400</width>
+ <height>200</height>
+ </size>
+ </property>
+ <property name="textFormat">
+ <enum>RichText</enum>
+ </property>
+ <property name="linkUnderline">
+ <bool>false</bool>
+ </property>
+ <property name="autoFormatting">
+ <set>AutoAll</set>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>TextEdit</sender>
+ <signal>copyAvailable(bool)</signal>
+ <receiver>KSayItView</receiver>
+ <slot>slotCopyAvailable(bool)</slot>
+ </connection>
+ <connection>
+ <sender>TextEdit</sender>
+ <signal>textChanged()</signal>
+ <receiver>KSayItView</receiver>
+ <slot>slotTextChanged()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>TextEdit</tabstop>
+</tabstops>
+<slots>
+ <slot>slotCopyAvailable(bool)</slot>
+ <slot>slotTextChanged()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>ktextedit.h</includehint>
+</includehints>
+</UI>
diff --git a/ksayit/src/Makefile.am b/ksayit/src/Makefile.am
new file mode 100644
index 0000000..9fb2b84
--- /dev/null
+++ b/ksayit/src/Makefile.am
@@ -0,0 +1,45 @@
+# set the include path for X, qt and KDE
+INCLUDES = -I$(top_srcdir)/ksayit/KTTSD_Lib $(all_includes)
+
+# these are the headers for your project
+noinst_HEADERS = doctreeviewimpl.h effectstack.h fxpluginhandler.h \
+ fxsetupimpl.h ksayit_fxplugin.h ksayitsystemtray.h ksayit_ttsplugin.h \
+ ksayitviewimpl.h Types.h version.h voicesetupdlg.h ksayit.h parasaxparser.h saxhandler.h \
+ ksayitbookmarkhandler.h contextmenuhandler.h docbookclasses.h docbookgenerator.h \
+ docbookparser.h
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/ksayit.pot
+
+KDE_ICON = AUTO
+
+
+#########################################################################
+# APPLICATION SECTION
+#########################################################################
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+bin_PROGRAMS = ksayit
+
+# the application source, library search path, and link libraries
+ksayit_SOURCES = doctreeviewimpl.cpp effectstack.cpp fxpluginhandler.cpp \
+ fxsetupimpl.cpp ksayit.skel ksayitsystemtray.cpp ksayitviewimpl.cpp \
+ main.cpp voicesetupdlg.cpp ksayit.cpp DocTreeView.ui fx_setup.ui KSayItView.ui \
+ parasaxparser.cpp saxhandler.cpp ksayitbookmarkhandler.cpp contextmenuhandler.cpp docbookclasses.cpp \
+ docbookgenerator.cpp docbookparser.cpp
+
+ksayit_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+ksayit_LDADD = $(top_builddir)/ksayit/KTTSD_Lib/libKTTSD_Lib.la $(LIB_KIO) \
+ -lartskde -lsoundserver_idl -lartsflow
+
+
+# this is where the shell's XML-GUI resource file goes
+shellrcdir = $(kde_datadir)/ksayit
+
+
+shellrc_DATA = ksayitui.rc ContextMenus.xml
+xdg_apps_DATA = ksayit.desktop
+include_HEADERS = ksayit_fxplugin.h
diff --git a/ksayit/src/Types.h b/ksayit/src/Types.h
new file mode 100644
index 0000000..017f721
--- /dev/null
+++ b/ksayit/src/Types.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+ Types.h - description
+ -------------------
+ begin : Fr Nov 21 2003
+ copyright : (C) 2003 by voglrobe
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef TYPES_H
+#define TYPES_H
+
+// #include <vector>
+
+// QT includes
+#include <qvaluelist.h>
+#include <qmap.h>
+
+// KDE includes
+#include <klistview.h>
+
+typedef QValueList<int> ParameterList_type;
+typedef QMap<QString, ParameterList_type> EffectConfig_type;
+
+namespace KSayItGlobal {
+ static const int item_initial_id = 100;
+
+ enum {
+ XMLCONTEXTNAME=0,
+ ISEDITABLE,
+ MAXLINES,
+ SUMMARY,
+ RAWDATA,
+ RTFHEADER,
+ RTFDATA,
+ SPEAKERHEADER,
+ SPEAKERDATA
+ };
+
+}
+
+/**
+This abstract class is the interface to access the items of the TreeView.
+@author Robert Vogl
+*/
+class ListViewInterface : public KListViewItem
+{
+public:
+ ListViewInterface(ListViewInterface *parent=0, QString label=QString::null);
+ ListViewInterface(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ListViewInterface(KListView *lv=0, QString label=QString::null);
+
+ // ~ListViewItemInterface();
+
+ /**
+ * Stores data to the item referenced by the given index.
+ * \param index The index is defined by the following enum:
+ * \param data The data to store.
+ * \returns <tt>true</tt> if the operation was successfully performed,
+ * in all other cases <tt>false</tt>.
+ */
+ virtual bool setValue( unsigned int index, QVariant data ) = 0;
+
+ /**
+ * Requests data from the item referenced by the index.
+ * \param index See <tt>setValue()</tt>.
+ * \returns The requested data as a <tt>QVariant</tt> or a invalid
+ * <tt>QVariant()</tt> if the data was not available.
+ */
+ virtual QVariant getValue( unsigned int index ) const = 0;
+
+};
+
+
+#endif
diff --git a/ksayit/src/contextmenuhandler.cpp b/ksayit/src/contextmenuhandler.cpp
new file mode 100644
index 0000000..311a39a
--- /dev/null
+++ b/ksayit/src/contextmenuhandler.cpp
@@ -0,0 +1,407 @@
+//
+// C++ Implementation: %{MODULE}
+//
+// Description:
+//
+//
+// Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR}
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// Qt includes
+#include <qfile.h>
+#include <qvariant.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+
+// App specific includes
+#include "Types.h"
+#include "contextmenuhandler.h"
+
+
+/**
+ * XML-ActionHandler
+ */
+ContextActionHandler::ContextActionHandler(ContextMenuHandler *menuhandler)
+ : QXmlDefaultHandler(), m_menuhandler(menuhandler)
+{
+ m_subName = QString::null;
+ m_actionName = QString::null;
+ m_qty = QString::null;
+ m_popup = menuhandler->m_popupmenu;
+ m_hit = false;
+ m_searchID = QString::null;
+}
+
+ContextActionHandler::~ContextActionHandler()
+{
+}
+
+
+void ContextActionHandler::setSearchID( const QString xmlID )
+{
+ m_searchID = xmlID;
+}
+
+
+bool ContextActionHandler::startElement( const QString &,
+ const QString &,
+ const QString &qName,
+ const QXmlAttributes &atts )
+{
+ if ( qName == "Item" ){
+ if ( atts.value("id") == m_searchID ){
+ if ( atts.value("editable") == "yes"){
+ m_menuhandler->setItemEditable( true );
+ }
+ if ( atts.value("maxlines") != ""){
+ m_menuhandler->setItemMaxlines( atts.value("maxlines") );
+ }
+ m_hit = true;
+ } else {
+ m_hit = false;
+ }
+ }
+ if ( !(m_hit && m_menuhandler->m_popupmenu) )
+ return true;
+
+ if ( qName == "Action" ){
+ m_actionName = "";
+ m_qty = atts.value("qty");
+ } else if ( qName == "Submenu" ){
+ if ( atts.value("name") != "" ){
+ m_subName = atts.value("name");
+ m_popup = m_menuhandler->SubMenuFactory(m_popup);
+ }
+ }
+ return true;
+}
+
+
+bool ContextActionHandler::endElement( const QString &,
+ const QString &,
+ const QString &qName )
+{
+ if ( !(m_hit && m_menuhandler->m_popupmenu) )
+ return true;
+
+ if ( qName == "Action" ){
+ KAction* newAction = m_menuhandler->ActionFactory(m_actionName, m_qty);
+ if ( newAction )
+ newAction->plug( m_popup );
+ } else if ( qName == "Submenu" ){
+ if ( m_subName == "New" ){
+ m_menuhandler->m_popupmenu->insertItem( i18n("New"), m_popup);
+ }
+ // only one sublevel spported -> back to toplevel menu
+ m_popup = m_menuhandler->m_popupmenu;
+ }
+ return true;
+}
+
+
+bool ContextActionHandler::characters( const QString &ch )
+{
+ m_actionName += ch;
+ return true;
+}
+
+
+
+/**
+ * MenuHandler
+ */
+ContextMenuHandler::ContextMenuHandler(QObject *parent, const char *name)
+ : QObject(parent, name), m_DocTreeView(parent)
+{
+ m_popupmenu = NULL;
+ m_item = NULL;
+ initActions();
+ m_XmlFilePath = KGlobal::dirs()->findResource("data", "ksayit/ContextMenus.xml");
+}
+
+
+ContextMenuHandler::~ContextMenuHandler()
+{
+ delete renameItem;
+ delete deleteItem;
+ delete newBookInfo;
+ delete newChapter;
+ delete newKeywordSet;
+ delete newKeyword;
+ delete newAbstract;
+ delete newAuthorGroup;
+ delete newAuthor;
+ delete newDate;
+ delete newReleaseInfo;
+ delete newTitle;
+ delete newParagraph;
+ delete newSection_1;
+ delete newSection_2;
+ delete newSection_3;
+ delete newSection_4;
+ delete newSection_5;
+
+ if (m_popupmenu)
+ delete m_popupmenu;
+}
+
+
+void ContextMenuHandler::initActions()
+{
+ // User defined actions
+ renameItem = new KAction (i18n("Rename..."),
+ 0,
+ m_DocTreeView, SLOT (slotRenameItem()), NULL );
+
+ deleteItem = new KAction (i18n("Delete..."),
+ 0,
+ m_DocTreeView, SLOT (slotDeleteItem()), NULL );
+
+ newBookInfo = new KAction ( i18n("Overview"),
+ 0,
+ m_DocTreeView, SLOT (slotNewBookInfo()), NULL );
+
+ newChapter = new KAction ( i18n("Chapter"),
+ 0,
+ m_DocTreeView, SLOT (slotNewChapter()), NULL );
+
+ newKeywordSet = new KAction ( i18n("Keywords"),
+ 0,
+ m_DocTreeView, SLOT (slotNewKeywordSet()), NULL );
+
+ newKeyword = new KAction ( i18n("Keyword"),
+ 0,
+ m_DocTreeView, SLOT (slotNewKeyword()), NULL );
+
+ newAbstract = new KAction ( i18n("Abstract"),
+ 0,
+ m_DocTreeView, SLOT (slotNewAbstract()), NULL );
+
+ newAuthorGroup = new KAction ( i18n("Authors"),
+ 0,
+ m_DocTreeView, SLOT (slotNewAuthorGroup()), NULL );
+
+ newAuthor = new KAction ( i18n("Author"),
+ 0,
+ m_DocTreeView, SLOT (slotNewAuthor()), NULL );
+
+ newDate = new KAction ( i18n("Date"),
+ 0,
+ m_DocTreeView, SLOT (slotNewDate()), NULL );
+
+ newReleaseInfo = new KAction ( i18n("Release Info"),
+ 0,
+ m_DocTreeView, SLOT (slotNewReleaseInfo()), NULL );
+
+ newTitle = new KAction ( i18n("Title"),
+ 0,
+ m_DocTreeView, SLOT (slotNewTitle()), NULL );
+
+ newParagraph = new KAction ( i18n("Paragraph"),
+ 0,
+ m_DocTreeView, SLOT (slotNewParagraph()), NULL );
+
+ newSection_1 = new KAction ( i18n("Section Level 1"),
+ 0,
+ m_DocTreeView, SLOT (slotNewSection_1()), NULL );
+
+ newSection_2 = new KAction ( i18n("Section Level 2"),
+ 0,
+ m_DocTreeView, SLOT (slotNewSection_2()), NULL );
+
+ newSection_3 = new KAction ( i18n("Section Level 3"),
+ 0,
+ m_DocTreeView, SLOT (slotNewSection_3()), NULL );
+
+ newSection_4 = new KAction ( i18n("Section Level 4"),
+ 0,
+ m_DocTreeView, SLOT (slotNewSection_4()), NULL );
+
+ newSection_5 = new KAction ( i18n("Section Level 5"),
+ 0,
+ m_DocTreeView, SLOT (slotNewSection_5()), NULL );
+}
+
+
+KPopupMenu* ContextMenuHandler::getPopupMenu(ListViewInterface *item)
+{
+ if ( !item )
+ return NULL;
+
+ m_item = item;
+
+ QString xmlID = ( item->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( xmlID.isNull() )
+ return NULL;
+
+ // delete old popup menu and create new one
+ if ( m_popupmenu ){
+ delete m_popupmenu;
+ m_popupmenu = NULL;
+ }
+ m_popupmenu = new KPopupMenu(0);
+
+ bool res;
+ res = parseXmlFile(xmlID);
+
+ if ( res ){
+ return m_popupmenu;
+ } else {
+ delete m_popupmenu;
+ m_popupmenu = NULL;
+ return NULL;
+ }
+}
+
+
+void ContextMenuHandler::registerPopupMenu(ListViewInterface *item)
+{
+ if ( !item )
+ return;
+
+ m_item = item;
+
+ QString xmlID = ( item->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( xmlID.isNull() )
+ return;
+
+ // delete old popup menu
+ if ( m_popupmenu ){
+ delete m_popupmenu;
+ m_popupmenu = NULL;
+ }
+
+ // if m_popupmenu == NULL, the parser should not create a popupmenu
+ parseXmlFile(xmlID);
+}
+
+
+bool ContextMenuHandler::parseXmlFile(const QString &xmlID)
+{
+ kdDebug(100200) << "ContextMenuHandler::parseXmlFile()" << endl;
+ kdDebug(100200) << "XML-File: " << m_XmlFilePath << endl;
+
+ QFile xmlFile( m_XmlFilePath );
+ QXmlSimpleReader parser;
+ ContextActionHandler handler(this);
+ handler.setSearchID(xmlID);
+ parser.setContentHandler( &handler );
+ return parser.parse( &xmlFile );
+}
+
+
+KAction* ContextMenuHandler::ActionFactory( const QString &actionName, const QString &qty )
+{
+ bool enabled;
+ if ( qty.lower() == "n" ){
+ // unlimited don't check return enabled action
+ enabled = true;
+ } else {
+ // check if qty is within allowed limits
+ ListViewInterface *i = static_cast<ListViewInterface*>(m_item->firstChild());
+ int count = 0;
+ QString name = QString::null;
+ while (i){
+ name = ( i->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( name.lower() == actionName.lower() ){
+ count++;
+ }
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+ enabled = count < qty.toInt() ? true : false;
+ }
+
+ if ( actionName == "Rename" ){
+ renameItem->setEnabled( enabled );
+ return renameItem;
+ } else if ( actionName == "Delete" ){
+ deleteItem->setEnabled( enabled );
+ return deleteItem;
+ } else if ( actionName == "BookInfo" ){
+ newBookInfo->setEnabled( enabled );
+ return newBookInfo;
+ } else if ( actionName == "Chapter" ){
+ newChapter->setEnabled( enabled );
+ return newChapter;
+ } else if ( actionName == "KeywordSet" ){
+ newKeywordSet->setEnabled( enabled );
+ return newKeywordSet;
+ } else if ( actionName == "Keyword" ){
+ newKeyword->setEnabled( enabled );
+ return newKeyword;
+ } else if ( actionName == "Abstract" ){
+ newAbstract->setEnabled( enabled );
+ return newAbstract;
+ } else if ( actionName == "AuthorGroup" ){
+ newAuthorGroup->setEnabled( enabled );
+ return newAuthorGroup;
+ } else if ( actionName == "Author" ){
+ newAuthor->setEnabled( enabled );
+ return newAuthor;
+ } else if ( actionName == "Date" ){
+ newDate->setEnabled( enabled );
+ return newDate;
+ } else if ( actionName == "ReleaseInfo" ){
+ newReleaseInfo->setEnabled( enabled );
+ return newReleaseInfo;
+ } else if ( actionName == "Title" ){
+ newTitle->setEnabled( enabled );
+ return newTitle;
+ } else if ( actionName == "Paragraph" ){
+ newParagraph->setEnabled( enabled );
+ return newParagraph;
+ } else if ( actionName == "Section_1" ){
+ newSection_1->setEnabled( enabled );
+ return newSection_1;
+ } else if ( actionName == "Section_2" ){
+ newSection_2->setEnabled( enabled );
+ return newSection_2;
+ } else if ( actionName == "Section_3" ){
+ newSection_3->setEnabled( enabled );
+ return newSection_3;
+ } else if ( actionName == "Section_4" ){
+ newSection_4->setEnabled( enabled );
+ return newSection_4;
+ } else if ( actionName == "Section_5" ){
+ newSection_5->setEnabled( enabled );
+ return newSection_5;
+ }
+ kdDebug(100200) << "ERROR!!! ContextMenuHandler::ActionFactory()" << endl;
+ return NULL;
+}
+
+
+KPopupMenu* ContextMenuHandler::SubMenuFactory(KPopupMenu *parent)
+{
+ return new KPopupMenu(parent);
+}
+
+
+void ContextMenuHandler::setItemEditable( bool editable )
+{
+ if ( m_item )
+ m_item->setValue(KSayItGlobal::ISEDITABLE, editable);
+}
+
+
+void ContextMenuHandler::setItemMaxlines( const QString &maxlines )
+{
+ if ( maxlines == "" )
+ return;
+
+ if ( !m_item )
+ return;
+
+ int value = maxlines.toInt();
+ m_item->setValue( KSayItGlobal::MAXLINES, value );
+}
+
+
+#include "contextmenuhandler.moc"
diff --git a/ksayit/src/contextmenuhandler.h b/ksayit/src/contextmenuhandler.h
new file mode 100644
index 0000000..102181a
--- /dev/null
+++ b/ksayit/src/contextmenuhandler.h
@@ -0,0 +1,152 @@
+//
+// C++ Interface: %{MODULE}
+//
+// Description:
+//
+//
+// Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR}
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef CONTEXTMENUHANDLER_H
+#define CONTEXTMENUHANDLER_H
+
+// Qt includes
+#include <qobject.h>
+#include <qstring.h>
+#include <qxml.h>
+
+// KDE includes
+#include <kaction.h>
+#include <kpopupmenu.h>
+
+//forward declarations
+class ContextMenuHandler;
+class ListViewInterface;
+
+/**
+@author Robert Vogl
+*/
+class ContextActionHandler : public QXmlDefaultHandler
+{
+public:
+ ContextActionHandler(ContextMenuHandler *menuhandler = 0);
+ ~ContextActionHandler();
+
+ // Reimplementations from base class
+ bool startElement( const QString &namespaceURI,
+ const QString &localName,
+ const QString &qName,
+ const QXmlAttributes &atts );
+
+ // Reimplementations from base class
+ bool endElement( const QString &namespaceURI,
+ const QString &localName,
+ const QString &qName );
+
+ // Reimplementations from base class
+ bool characters( const QString &ch );
+
+ void setSearchID( const QString xmlID );
+
+private:
+ ContextMenuHandler *m_menuhandler;
+ QString m_subName;
+ QString m_actionName;
+ QString m_qty;
+ KPopupMenu *m_popup;
+ bool m_hit;
+ QString m_searchID;
+};
+
+
+/**
+@author Robert Vogl
+*/
+class ContextMenuHandler : public QObject
+{
+Q_OBJECT
+public:
+ ContextMenuHandler(QObject *parent = 0, const char *name = 0);
+
+ ~ContextMenuHandler();
+
+ /**
+ * \param item The selected TreeView item.
+ * \returns A pointer to the popup-menu.
+ */
+ KPopupMenu* getPopupMenu(ListViewInterface *item);
+
+ /**
+ * \returns A pointer to the Submenu as a child of the parent
+ * \p parent.
+ */
+ KPopupMenu* SubMenuFactory(KPopupMenu *parent);
+
+ /**
+ * Creates an action sufficiant to the given name.
+ * It checks if the action is allowed or not and returns
+ * a disabled or enabled action.
+ * \param actionName The name of the action as defined in the
+ * namespace \p ContextMenu.xml.
+ * \param qty The maximum allowed quantity of the same action for the
+ * given element.
+ * \returns A Pointer to the action.
+ */
+ KAction* ActionFactory( const QString &actionName, const QString &qty );
+
+ /**
+ * Creates a Popup context menu for the given item and stores a
+ * pointer to it in \p m_MenuList.
+ */
+ void registerPopupMenu(ListViewInterface *item);
+
+ /**
+ * Sets wether the content of the item is editable or not.
+ */
+ void setItemEditable( bool editable );
+
+ /**
+ * Sets the number of lines a editable item can hold.
+ * -1 = unlimited.
+ */
+ void setItemMaxlines( const QString &maxlines );
+
+private: // Methods
+ void initActions();
+ bool parseXmlFile(const QString &xmlID);
+
+public: // Attributes
+ KPopupMenu* m_popupmenu;
+
+private:
+ // Basic actions
+ KAction* renameItem;
+ KAction* deleteItem;
+ // Actions to create new items
+ KAction* newBookInfo;
+ KAction* newChapter;
+ KAction* newKeywordSet;
+ KAction* newKeyword;
+ KAction* newAbstract;
+ KAction* newAuthorGroup;
+ KAction* newAuthor;
+ KAction* newDate;
+ KAction* newReleaseInfo;
+ KAction* newTitle;
+ KAction* newParagraph;
+ KAction* newSection_1;
+ KAction* newSection_2;
+ KAction* newSection_3;
+ KAction* newSection_4;
+ KAction* newSection_5;
+
+ // mixed stuff
+ QString m_XmlFilePath;
+ ListViewInterface* m_item;
+ QObject* m_DocTreeView;
+
+};
+
+#endif
diff --git a/ksayit/src/docbookclasses.cpp b/ksayit/src/docbookclasses.cpp
new file mode 100644
index 0000000..7e5c677
--- /dev/null
+++ b/ksayit/src/docbookclasses.cpp
@@ -0,0 +1,1056 @@
+//
+// C++ Implementation: docbookclasses
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+// Qt includes
+#include <qwidget.h>
+#include <qtextstream.h>
+#include <qpixmap.h>
+#include <qregexp.h>
+#include <qstringlist.h>
+
+//KDE includes
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+// App specific includes
+#include "parasaxparser.h"
+#include "docbookclasses.h"
+
+
+//////////////////////////////////////
+// Interface
+//////////////////////////////////////
+ListViewInterface::ListViewInterface(ListViewInterface *parent, QString label)
+ : KListViewItem( parent, label )
+{
+}
+
+ListViewInterface::ListViewInterface(ListViewInterface *parent, ListViewInterface *after, QString label) : KListViewItem( parent, after, label )
+{
+}
+
+ListViewInterface::ListViewInterface(KListView *lv, QString label)
+ : KListViewItem( lv, label )
+{
+}
+
+
+//////////////////////////////////////
+// Classes for Roberts elements
+//////////////////////////////////////
+/**
+ * RobDocument
+ */
+RobDocument::RobDocument(KListView *lv, QString label)
+ : ListViewInterface( lv, label )
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("contents", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("RobDocument") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append("<H1><center>" + i18n("unnamed") + "</center></H1>"); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("unnamed") + "\n"); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+RobDocument::~RobDocument()
+{
+}
+
+bool RobDocument::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFHEADER:
+ *it = "<H1><center>" + data.toString() + "</center></H1>";
+ break;
+ case KSayItGlobal::SPEAKERHEADER:
+ *it = data.toString() + "\n";
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant RobDocument::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+
+//////////////////////////////////////
+// Classes for Docbook elements
+//////////////////////////////////////
+/**
+ * Overview
+ */
+Overview::Overview(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("filenew", KIcon::Small);
+ this->setPixmap(0, pixmap);
+ this->setText(3, "0"); // upmost element
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("BookInfo") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append("<H1>" + i18n("Overview") + "</H1>"); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("Overview") + "\n"); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Overview::~Overview()
+{
+}
+
+bool Overview::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Overview::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * Date
+ */
+Date::Date(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("filenew", KIcon::Small);
+ this->setPixmap(0, pixmap);
+ this->setText(3, "00000001");
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Date") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)1 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append("<B>" + i18n("Date") +": </B>"); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("Date") + ": "); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Date::~Date()
+{
+}
+
+bool Date::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::MAXLINES:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFDATA:
+ *it = data.toString() + "<br>";
+ break;
+ case KSayItGlobal::SPEAKERDATA:
+ *it = data;
+ break;
+ case KSayItGlobal::RAWDATA:
+ *it = data;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Date::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * ReleaseInfo
+ */
+ReleaseInfo::ReleaseInfo(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("filenew", KIcon::Small);
+ this->setPixmap(0, pixmap);
+ this->setText(3, "00000002");
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("ReleaseInfo") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)1 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append("<B>" + i18n("Release") + ": </B>"); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("Release") + ": "); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+ReleaseInfo::~ReleaseInfo()
+{
+}
+
+bool ReleaseInfo::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::MAXLINES:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFDATA:
+ *it = data.toString() + "<br>";
+ break;
+ case KSayItGlobal::SPEAKERDATA:
+ *it = data;
+ break;
+ case KSayItGlobal::RAWDATA:
+ *it = data;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant ReleaseInfo::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * Authorgroup
+ */
+AuthorGroup::AuthorGroup(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("kdmconfig", KIcon::Small);
+ this->setPixmap(0, pixmap);
+ this->setText(3, "00000003");
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("AuthorGroup") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append("<H2>" + i18n("Author(s)")+ "</H2>"); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("Author(s)") + "\n"); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+AuthorGroup::~AuthorGroup()
+{
+}
+
+bool AuthorGroup::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant AuthorGroup::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+
+/**
+ * Author
+ */
+Author::Author(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("personal", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Author") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)1 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append("<B>" + i18n("Author") + ": </B>"); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("Author") + ": "); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Author::~Author()
+{
+}
+
+// void Author::setData(const QString &data, QDomDocument &)
+// {
+// // canonify string
+// QString m_data = data;
+// m_data.replace( QRegExp("\n"), "" ); // remove Newlines
+// m_data.replace( QRegExp(" {2,}"), " " ); // remove multiple spaces
+// m_data.replace( QRegExp("[\t|\r]{1,}"), ""); // remove Tabs
+// // split string "firstname surname"
+// QString firstname = m_data.section(' ', 0, 0);
+// QString surname = m_data.section(' ', 1, 1);
+// // update node elements
+// m_node1.setNodeValue(firstname);
+// m_node2.setNodeValue(surname);
+// // update Listview
+// this->setText(1, firstname + " " + surname);
+// }
+
+bool Author::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::MAXLINES:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFDATA:
+ *it = data.toString() + "<br>";
+ break;
+ case KSayItGlobal::SPEAKERDATA:
+ *it = data;
+ this->setText( 1, data.toString() );
+ break;
+ case KSayItGlobal::RAWDATA:
+ *it = data;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Author::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * KeywordSet
+ */
+KeywordSet::KeywordSet(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("txt", KIcon::Small);
+ this->setPixmap(0, pixmap);
+ this->setText(3, "00000004");
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("KeywordSet") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append("<H2>" + i18n("Keywords") + "</H2>"); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("Keywords") + "\n"); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+KeywordSet::~KeywordSet()
+{
+}
+
+bool KeywordSet::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant KeywordSet::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * Keyword
+ */
+Keyword::Keyword(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Keyword") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (bool)1 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append(QString::null); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(QString::null); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Keyword::~Keyword()
+{
+}
+
+bool Keyword::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::MAXLINES:
+ *it = data;
+ break;
+ case KSayItGlobal::RAWDATA:
+ *it = data;
+ this->setText( 0, data.toString() );
+ break;
+ case KSayItGlobal::RTFDATA:
+ *it = data.toString() + "<br>";
+ break;
+ case KSayItGlobal::SPEAKERDATA:
+ *it = data;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Keyword::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+
+
+/**
+ * Abstract
+ */
+Abstract::Abstract(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("filenew", KIcon::Small);
+ this->setPixmap(0, pixmap);
+ this->setText(3, "00000005");
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Abstract") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append("<H2>" + i18n("Abstract") + "</H2>"); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("Abstract") + "\n"); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Abstract::~Abstract()
+{
+}
+
+bool Abstract::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Abstract::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+
+/**
+ * Para
+ */
+Para::Para(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("leftjust", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Para") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)-1 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append(QString::null); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(i18n("Paragraph") + "\n"); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Para::~Para()
+{
+}
+
+bool Para::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ QString sData = QString::null;
+ ParaSaxParser *p = ParaSaxParser::Instance();
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::MAXLINES:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFDATA:
+ p->setData( "<para>" + data.toString() + "</para>" );
+ p->getRTFText( sData );
+ *it = "<p>" + sData + "</p>";
+ break;
+ case KSayItGlobal::SPEAKERDATA:
+ p->setData( "<para>" + data.toString() + "</para>" );
+ p->getText( sData );
+ *it = sData;
+ break;
+ case KSayItGlobal::RAWDATA:
+ sData = data.toString();
+ *it = sData;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Para::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+
+/**
+ * Chapter
+ */
+Chapter::Chapter(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("leftjust", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Chapter") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append(QString::null); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(QString::null); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Chapter::~Chapter()
+{
+}
+
+bool Chapter::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFHEADER:
+ *it = "<H1>" + data.toString() + "</H1>";
+ break;
+ case KSayItGlobal::SPEAKERHEADER:
+ *it = data.toString() + "\n";
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Chapter::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+
+/**
+ * Sect1
+ */
+Sect1::Sect1(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("leftjust", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Sect1") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append(QString::null); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(QString::null); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Sect1::~Sect1()
+{
+}
+
+bool Sect1::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFHEADER:
+ *it = "<H2>" + data.toString() + "</H2>";
+ break;
+ case KSayItGlobal::SPEAKERHEADER:
+ *it = data.toString() + "\n";
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Sect1::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * Sect2
+ */
+Sect2::Sect2(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("leftjust", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Sect2") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append(QString::null); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(QString::null); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Sect2::~Sect2()
+{
+}
+
+bool Sect2::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFHEADER:
+ *it = "<H3>" + data.toString() + "</H3>";
+ break;
+ case KSayItGlobal::SPEAKERHEADER:
+ *it = data.toString() + "\n";
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Sect2::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * Sect3
+ */
+Sect3::Sect3(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("leftjust", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Sect3") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append(QString::null); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(QString::null); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Sect3::~Sect3()
+{
+}
+
+bool Sect3::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFHEADER:
+ *it = "<B>" + data.toString() + "</B><br>";
+ break;
+ case KSayItGlobal::SPEAKERHEADER:
+ *it = data.toString() + "\n";
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Sect3::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * Sect4
+ */
+Sect4::Sect4(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("leftjust", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Sect4") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append(QString::null); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(QString::null); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Sect4::~Sect4()
+{
+}
+
+bool Sect4::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFHEADER:
+ *it = "<B>" + data.toString() + "</B><br>";
+ break;
+ case KSayItGlobal::SPEAKERHEADER:
+ *it = data.toString() + "\n";
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Sect4::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
+/**
+ * Sect5
+ */
+Sect5::Sect5(ListViewInterface *parent, ListViewInterface *after, QString label)
+ : ListViewInterface(parent, after, label)
+{
+ QPixmap pixmap = KGlobal::iconLoader()->loadIcon("leftjust", KIcon::Small);
+ this->setPixmap(0, pixmap);
+
+ // new Concept (begin)
+ m_valueList.clear();
+ m_valueList.append( QString("Sect5") ); // XmlContextName
+ m_valueList.append( (bool)false ); // isEditable
+ m_valueList.append( (int)0 ); // MaxLines
+ m_valueList.append(QString::null); // Summary
+ m_valueList.append(QString::null); // RawData
+ m_valueList.append(QString::null); // RTFHeader
+ m_valueList.append(QString::null); // RTFData
+ m_valueList.append(QString::null); // SpeakerHeader
+ m_valueList.append(QString::null); // SpeakerData
+ // new Concept (end)
+}
+
+Sect5::~Sect5()
+{
+}
+
+bool Sect5::setValue( unsigned int index, QVariant data )
+{
+ if ( index<1 || index > m_valueList.count() )
+ return false;
+
+ QValueList<QVariant>::Iterator it = m_valueList.at(index);
+ switch (index){
+ case KSayItGlobal::ISEDITABLE:
+ *it = data;
+ break;
+ case KSayItGlobal::RTFHEADER:
+ *it = "<B>" + data.toString() + "</B><br>";
+ break;
+ case KSayItGlobal::SPEAKERHEADER:
+ *it = data.toString() + "\n";
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+QVariant Sect5::getValue( unsigned int index ) const
+{
+ if ( index > m_valueList.count() )
+ return QVariant(); // a invalid QVariant
+
+ QVariant data;
+ data = m_valueList[index];
+
+ return data;
+}
+
diff --git a/ksayit/src/docbookclasses.h b/ksayit/src/docbookclasses.h
new file mode 100644
index 0000000..a7f84af
--- /dev/null
+++ b/ksayit/src/docbookclasses.h
@@ -0,0 +1,344 @@
+//
+// C++ Interface: docbookclasses.h
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef DOCBOOKCLASSES_H
+#define DOCBOOKCLASSES_H
+
+// Qt includes
+#include <qstring.h>
+
+#include <qvariant.h>
+#include <qvaluelist.h>
+
+// KDE includes
+#include <klistview.h>
+
+// App specific includes
+#include "Types.h"
+
+// forward declarations
+class QStringList;
+
+//
+// Classes for Roberts elements
+//
+/**
+ Represents the root item of the document, therefore it expects
+ a \p QListView object as parent.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class RobDocument : public ListViewInterface
+{
+public:
+ /**
+ * Constructor
+ * \param lv The ListView parent.
+ * \param label The label is shown in column 0 of the TreeView and is also
+ * used as bookmark title.
+ */
+ RobDocument(KListView *lv=0, QString label=QString::null);
+ ~RobDocument();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+//
+// Classes for Docbook elements
+//
+/**
+ Represents the DocBook \p Overview element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class Overview : public ListViewInterface
+{
+public:
+ Overview(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Overview();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Date element of the document.\n
+ @author Robert Vogl
+ */
+class Date : public ListViewInterface
+{
+public:
+ Date(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Date();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ // Pointer to the associated Data
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p ReleasInfo element of the document.\n
+ @author Robert Vogl
+ */
+class ReleaseInfo : public ListViewInterface
+{
+public:
+ ReleaseInfo(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~ReleaseInfo();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ // Pointer to the associated Data
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p AuthorGroup element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class AuthorGroup : public ListViewInterface
+{
+public:
+ AuthorGroup(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~AuthorGroup();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Author element and its Subelements
+ \p Firstname and \p Surname of the document.\n
+ @author Robert Vogl
+ */
+class Author : public ListViewInterface
+{
+public:
+ Author(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Author();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p KeywordSet element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class KeywordSet : public ListViewInterface
+{
+public:
+ KeywordSet(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~KeywordSet();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Keyword element of the document.\n
+ @author Robert Vogl
+ */
+class Keyword : public ListViewInterface
+{
+public:
+ Keyword(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Keyword();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Abstract element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class Abstract : public ListViewInterface
+{
+public:
+ Abstract(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Abstract();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents a DocBook Paragraph item of the document.\n
+ @author Robert Vogl
+ */
+class Para : public ListViewInterface
+{
+public:
+ Para(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Para();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Chapter element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class Chapter : public ListViewInterface
+{
+public:
+ Chapter(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Chapter();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Sec1 element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class Sect1 : public ListViewInterface
+{
+public:
+ Sect1(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Sect1();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Sec2 element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class Sect2 : public ListViewInterface
+{
+public:
+ Sect2(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Sect2();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Sec3 element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class Sect3 : public ListViewInterface
+{
+public:
+ Sect3(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Sect3();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Sec4 element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class Sect4 : public ListViewInterface
+{
+public:
+ Sect4(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Sect4();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+
+/**
+ Represents the DocBook \p Sec5 element of the document.\n
+ Structural item only (no references to a DOM node).
+ @author Robert Vogl
+ */
+class Sect5 : public ListViewInterface
+{
+public:
+ Sect5(ListViewInterface *parent=0, ListViewInterface *after=0, QString label=QString::null);
+ ~Sect5();
+
+ bool setValue( unsigned int index, QVariant data );
+ QVariant getValue( unsigned int index ) const;
+
+private:
+ QValueList<QVariant> m_valueList;
+};
+
+#endif
diff --git a/ksayit/src/docbookgenerator.cpp b/ksayit/src/docbookgenerator.cpp
new file mode 100644
index 0000000..1d6db9c
--- /dev/null
+++ b/ksayit/src/docbookgenerator.cpp
@@ -0,0 +1,483 @@
+//
+// C++ Implementation: docbookgenerator
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// Qt includes
+#include <qstring.h>
+#include <qvariant.h>
+
+//KDE includes
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+// App specific includes
+#include "docbookgenerator.h"
+
+
+DocbookGenerator::DocbookGenerator()
+{
+}
+
+
+DocbookGenerator::~DocbookGenerator()
+{
+}
+
+
+void DocbookGenerator::writeBook(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeBook()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "RobDocument" )
+ return;
+
+ // add node to document
+ doc << "<Book>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "BookInfo" ){
+ writeBookInfo( doc, i );
+ } else if ( itemType == "Chapter" ) {
+ writeChapter( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+ doc << "</Book>" << endl;
+}
+
+
+void DocbookGenerator::writeBookInfo(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeBookInfo()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "BookInfo" )
+ return;
+
+ // add node to document
+ doc << "<BookInfo>" << endl;
+ writeTitleOfBook( doc, item );
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "KeywordSet" ){
+ writeKeywordSet( doc, i );
+ } else if ( itemType == "Abstract" ) {
+ writeAbstract( doc, i );
+ } else if ( itemType == "AuthorGroup" ) {
+ writeAuthorGroup( doc, i );
+ } else if ( itemType == "Date" ) {
+ writeDate( doc, i );
+ } else if ( itemType == "ReleaseInfo" ) {
+ writeReleaseInfo( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</BookInfo>" << endl;
+}
+
+
+void DocbookGenerator::writeTitleOfBook(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeTitle()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "BookInfo" )
+ return;
+
+ // Documents title is stored in root element (parent of BookInfo)
+ ListViewInterface *parent = static_cast<ListViewInterface*>(item->parent());
+ if ( parent ){
+ QString title = parent->text(0);
+
+ // add node to document
+ doc << "<Title>" << title << "</Title>" << endl;
+ }
+}
+
+
+void DocbookGenerator::writeAuthorGroup(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeAuthorGroup()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "AuthorGroup" )
+ return;
+
+ // add node to document
+ doc << "<AuthorGroup>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "Author" ){
+ writeAuthor( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</AuthorGroup>" << endl;
+}
+
+
+void DocbookGenerator::writeAuthor(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeAuthor()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Author" )
+ return;
+
+ QString author = QString::null;
+ author = ( item->getValue(KSayItGlobal::RAWDATA) ).toString();
+
+ // add node to document
+ doc << "<Author>" << endl;
+
+ // process childs
+ doc << "<Firstname>" << author.section(' ', 0, 0) << "</Firstname>" << endl;
+ doc << "<Surname>" << author.section(' ', 1, 1) << "</Surname>" << endl;
+
+ doc << "</Author>" << endl;
+}
+
+
+void DocbookGenerator::writeDate(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeDate()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Date" )
+ return;
+
+ QString date = item->text(1);
+
+ // add node to document
+ doc << "<Date>" << date << "</Date>" << endl;
+}
+
+
+void DocbookGenerator::writeReleaseInfo(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeReleaseInfo()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "ReleaseInfo" )
+ return;
+
+ QString releaseinfo = item->text(1);
+
+ // add node to document
+ doc << "<ReleaseInfo>" << releaseinfo << "</ReleaseInfo>" << endl;
+}
+
+
+void DocbookGenerator::writeKeywordSet(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeKeywordSet()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "KeywordSet" )
+ return;
+
+ // add node to document
+ doc << "<KeywordSet>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = ( i->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( itemType == "Keyword" ){
+ writeKeyword( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</KeywordSet>" << endl;
+}
+
+
+void DocbookGenerator::writeKeyword(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeKeyword()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Keyword" )
+ return;
+
+ // QString keyword = item->text( 0 );
+ QString keyword = QString::null;
+ keyword = (item->getValue(3)).toString();
+
+ // add node to document
+ doc << "<Keyword>" << keyword << "</Keyword>" << endl;
+
+ // process childs
+ // no childs
+}
+
+
+void DocbookGenerator::writeAbstract(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeAbstract()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Abstract" )
+ return;
+
+ // add node to document
+ doc << "<Abstract>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "Para" ){
+ writePara( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</Abstract>" << endl;
+}
+
+
+void DocbookGenerator::writeChapter( QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeChapter()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Chapter" )
+ return;
+
+ QString title = item->text(0);
+
+ // add node to document
+ doc << "<Chapter>" << endl;
+ doc << "<Title>" << title << "</Title>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "Para" ){
+ writePara( doc, i );
+ } else if ( itemType == "Sect1" ) {
+ writeSect1( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</Chapter>" << endl;
+}
+
+
+void DocbookGenerator::writeSect1(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeSect1()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Sect1" )
+ return;
+
+ QString title = item->text(0);
+
+ // add node to document
+ doc << "<Sect1>" << endl;
+ doc << "<Title>" << title << "</Title>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "Para" ){
+ writePara( doc, i );
+ } else if ( itemType == "Sect2" ) {
+ writeSect2( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</Sect1>" << endl;
+}
+
+
+void DocbookGenerator::writeSect2(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeSect1()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Sect2" )
+ return;
+
+ QString title = item->text(0);
+
+ // add node to document
+ doc << "<Sect2>" << endl;
+ doc << "<Title>" << title << "</Title>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = ( i->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( itemType == "Para" ){
+ writePara( doc, i );
+ } else if ( itemType == "Sect3" ) {
+ writeSect3( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</Sect2>" << endl;
+}
+
+
+void DocbookGenerator::writeSect3(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeSect3()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Sect3" )
+ return;
+
+ QString title = item->text(0);
+
+ // add node to document
+ doc << "<Sect3>" << endl;
+ doc << "<Title>" << title << "</Title>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "Para" ){
+ writePara( doc, i );
+ } else if ( itemType == "Sect4" ) {
+ writeSect4( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</Sect3>" << endl;
+}
+
+
+void DocbookGenerator::writeSect4(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeSect4()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Sect4" )
+ return;
+
+ QString title = item->text(0);
+
+ // add node to document
+ doc << "<Sect4>" << endl;
+ doc << "<Title>" << title << "</Title>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "Para" ){
+ writePara( doc, i );
+ } else if ( itemType == "Sect5" ) {
+ writeSect5( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</Sect4>" << endl;
+}
+
+
+void DocbookGenerator::writeSect5(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writeSect5()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Sect5" )
+ return;
+
+ QString title = item->text(0);
+
+ // add node to document
+ doc << "<Sect5>" << endl;
+ doc << "<Title>" << title << "</Title>" << endl;
+
+ // process childs
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ QString itemType;
+ while( i ){
+ itemType = (i->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( itemType == "Para" ){
+ writePara( doc, i );
+ }
+ // next child
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+
+ doc << "</Sect5>" << endl;
+}
+
+
+void DocbookGenerator::writePara(QTextStream &doc, ListViewInterface *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::writePara()" << endl;
+ // read item's content
+ QString whoAmI = (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString();
+ if ( whoAmI != "Para" )
+ return;
+
+ QString data = ( item->getValue(KSayItGlobal::RAWDATA) ).toString();
+
+ // add node to document
+ doc << "<Para>" << endl;
+ doc << data << endl;
+ doc << "</Para>" << endl;
+
+ // process childs
+ // childs are embedded in data.
+}
+
+
+
+
diff --git a/ksayit/src/docbookgenerator.h b/ksayit/src/docbookgenerator.h
new file mode 100644
index 0000000..80f526b
--- /dev/null
+++ b/ksayit/src/docbookgenerator.h
@@ -0,0 +1,71 @@
+//
+// C++ Interface: docbookgenerator
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef DOCBOOKGENERATOR_H
+#define DOCBOOKGENERATOR_H
+
+// Qt includes
+#include <qtextstream.h>
+
+// KDE includes
+
+// App specific includes
+#include "Types.h"
+
+class DocbookGenerator
+{
+public:
+ // Constructor
+ DocbookGenerator();
+
+ // Destructor
+ ~DocbookGenerator();
+
+ /**
+ * Walks throug the entire treeview starting with given item and returns
+ * returns a DocBook representation of its content.
+ * \returns doc The content of the TreeView in DocBook format
+ * \param item A pointer to the root item of the tree. Must be of type
+ * \p RobDocument.
+ */
+ void writeBook(QTextStream &doc, ListViewInterface *item);
+
+
+private:
+ void writeBookInfo(QTextStream &doc, ListViewInterface *item);
+ void writeTitleOfBook(QTextStream &doc, ListViewInterface *item);
+ void writeChapter(QTextStream &doc, ListViewInterface *item);
+ void writeKeywordSet(QTextStream &doc, ListViewInterface *item);
+ void writeKeyword(QTextStream &doc, ListViewInterface *item);
+ void writeAbstract(QTextStream &doc, ListViewInterface *item);
+ void writePara(QTextStream &doc, ListViewInterface *item);
+ void writeAuthorGroup(QTextStream &doc, ListViewInterface *item);
+ void writeAuthor(QTextStream &doc, ListViewInterface *item);
+ void writeDate(QTextStream &doc, ListViewInterface *item);
+ void writeReleaseInfo(QTextStream &doc, ListViewInterface *item);
+ void writeSect1(QTextStream &doc, ListViewInterface *item);
+ void writeSect2(QTextStream &doc, ListViewInterface *item);
+ void writeSect3(QTextStream &doc, ListViewInterface *item);
+ void writeSect4(QTextStream &doc, ListViewInterface *item);
+ void writeSect5(QTextStream &doc, ListViewInterface *item);
+
+
+
+};
+
+
+
+
+
+
+
+#endif
+
diff --git a/ksayit/src/docbookparser.cpp b/ksayit/src/docbookparser.cpp
new file mode 100644
index 0000000..03b9f73
--- /dev/null
+++ b/ksayit/src/docbookparser.cpp
@@ -0,0 +1,493 @@
+//
+// C++ Implementation: docbookparser
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// Qt includes
+#include <qregexp.h>
+#include <qstring.h>
+#include <qtextstream.h>
+
+//KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+
+// App specific includes
+#include "docbookparser.h"
+#include "docbookclasses.h"
+
+
+DocbookParser::DocbookParser(ContextMenuHandler *cmHandler)
+{
+ m_contextmenuhandler = cmHandler;
+ m_idCounter = KSayItGlobal::item_initial_id;
+}
+
+
+DocbookParser::~DocbookParser()
+{
+}
+
+
+QString DocbookParser::node2raw(QDomNode node) const
+{
+ QString ret;
+
+ // get content of element
+ QTextStream in(ret, IO_WriteOnly);
+ in.setEncoding(QTextStream::UnicodeUTF8);
+ in << node;
+
+ return ret;
+}
+
+
+/******************************************
+ * XML-Parser functions
+ ******************************************/
+//
+// DocBook parser
+//
+void DocbookParser::parseBook(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseBook()" << endl;
+ item->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( item );
+
+ // TODO: Attributes Id, Lang
+
+ // Elements (parse BookInfo before Chapter)
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="bookinfo" ){
+ parseBookInfo( node.toElement(), item );
+ break;
+ }
+ node = node.nextSibling();
+ }
+ node = element.firstChild();
+ while( !node.isNull() ){
+ if ( node.isElement() && node.nodeName().lower()=="chapter" ){
+ parseChapter( node.toElement(), item );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseBook()" << endl;
+}
+
+
+void DocbookParser::parseBookInfo(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseBookInfo()" << endl;
+
+ Overview *overview = new Overview(item, NULL, i18n("Overview"));
+ overview->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( overview );
+
+ QDomText data;
+ QDomNode node = element.firstChild();
+ // fixed order
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="title" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ item->setText( 0, data.nodeValue() ); // assign title to RootItem
+ item->setValue(KSayItGlobal::RTFHEADER, data.nodeValue() );
+ item->setValue(KSayItGlobal::SPEAKERHEADER, data.nodeValue() );
+
+ break;
+ }
+ }
+ node = node.nextSibling();
+ }
+ node = element.firstChild();
+ while( !node.isNull() ){
+ if ( node.isElement() && node.nodeName().lower()=="authorgroup" ){
+ parseAuthorGroup( node.toElement(), overview );
+ }
+ node = node.nextSibling();
+ }
+ node = element.firstChild();
+ while( !node.isNull() ){
+ if ( node.isElement() && node.nodeName().lower()=="date" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ Date *date = new Date(overview, NULL, i18n("Date"));
+ date->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ date->setText( 1, data.nodeValue() );
+ date->setValue(KSayItGlobal::RTFDATA, data.nodeValue());
+ date->setValue(KSayItGlobal::SPEAKERDATA, data.nodeValue());
+ date->setValue(KSayItGlobal::RAWDATA, node2raw(data));
+
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( date );
+ }
+ }
+ node = node.nextSibling();
+ }
+ node = element.firstChild();
+ while( !node.isNull() ){
+ if ( node.isElement() && node.nodeName().lower()=="releaseinfo" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ ReleaseInfo *relinfo = new ReleaseInfo(overview, NULL, i18n("Release"));
+ relinfo->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ relinfo->setText( 1, data.nodeValue() );
+ relinfo->setValue(KSayItGlobal::RTFDATA, data.nodeValue());
+ relinfo->setValue(KSayItGlobal::SPEAKERDATA, data.nodeValue());
+ relinfo->setValue(KSayItGlobal::RAWDATA, node2raw(data));
+
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( relinfo );
+ }
+ }
+ node = node.nextSibling();
+ }
+ node = element.firstChild();
+ while( !node.isNull() ){
+ if ( node.isElement() && node.nodeName().lower()=="keywordset" ){
+ parseKeywordSet( node.toElement(), overview );
+ }
+ node = node.nextSibling();
+ }
+ node = element.firstChild();
+ while( !node.isNull() ){
+ if ( node.isElement() && node.nodeName().lower()=="abstract" ){
+ parseAbstract( node.toElement(), overview );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseBookInfo()" << endl;
+}
+
+
+void DocbookParser::parseAuthorGroup(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseAuthorGroup()" << endl;
+
+ // item = overview
+ AuthorGroup *authorgroup = new AuthorGroup(item, NULL, i18n("Author(s)"));
+ authorgroup->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( authorgroup );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="author" ){
+ parseAuthor( node.toElement(), authorgroup );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseAuthorGroup()" << endl;
+}
+
+
+void DocbookParser::parseAuthor(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseAuthor()" << endl;
+
+ // item = authorgroup
+ QDomText data;
+ QDomText firstname = QDomText();
+ QDomText surname = QDomText();
+ QString s_firstname = QString::null;
+ QString s_surname = QString::null;
+
+ Author *author = new Author(item);
+ author->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="firstname" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ s_firstname = data.nodeValue();
+ firstname = data;
+ }
+ } else if ( node.isElement() && node.nodeName().lower()=="surname" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ s_surname = data.nodeValue();
+ surname = data;
+ }
+ }
+ node = node.nextSibling();
+ }
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( author );
+
+ author->setText(0, i18n("Author") );
+ author->setText(1, s_firstname + " " + s_surname);
+ author->setValue(KSayItGlobal::RTFDATA, s_firstname + " " + s_surname);
+ author->setValue(KSayItGlobal::SPEAKERDATA, s_firstname + " " + s_surname);
+ author->setValue(KSayItGlobal::RAWDATA, s_firstname + " " + s_surname);
+
+ kdDebug(100200) << "--- leaving parseAuthor()" << endl;
+}
+
+
+void DocbookParser::parseKeywordSet(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseKeywordSet()" << endl;
+
+ // item = overview
+ KeywordSet *keywordset = new KeywordSet(item, NULL, i18n("Keywords"));
+ keywordset->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( keywordset );
+
+ QDomText data;
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="keyword" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ Keyword *keyword = new Keyword(keywordset);
+ keyword->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ keyword->setText(0, data.nodeValue() );
+ keyword->setValue(KSayItGlobal::RTFDATA, data.nodeValue() );
+ keyword->setValue(KSayItGlobal::SPEAKERDATA, data.nodeValue() );
+ keyword->setValue(KSayItGlobal::RAWDATA, node2raw(data) );
+
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( keyword );
+ }
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseKeywordSet()" << endl;
+}
+
+
+void DocbookParser::parseAbstract(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseAbstract()" << endl;
+
+ // item = overview
+ QDomText data;
+ Abstract *abstract = new Abstract(item, NULL, i18n("Abstract"));
+ abstract->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( abstract );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="para" ){
+ parsePara( node.toElement(), abstract );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseAbstract()" << endl;
+}
+
+
+void DocbookParser::parseChapter(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseChapter()" << endl;
+
+ QDomText data;
+ Chapter *chapter = new Chapter(item, NULL, i18n("Chapter"));
+ chapter->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( chapter );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="title" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ chapter->setText( 0, data.nodeValue() );
+ chapter->setValue(KSayItGlobal::RTFHEADER, data.nodeValue());
+ chapter->setValue(KSayItGlobal::SPEAKERHEADER, data.nodeValue());
+ }
+ } else if ( node.isElement() && node.nodeName().lower()=="para" ){
+ parsePara( node.toElement(), chapter );
+ } else if ( node.isElement() && node.nodeName().lower()=="sect1" ){
+ parseSect1( node.toElement(), chapter );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseChapter()" << endl;
+}
+
+
+void DocbookParser::parseSect1(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseSect1()" << endl;
+
+ QDomText data;
+ Sect1 *sect1 = new Sect1(item, NULL, i18n("Section Level 1"));
+ sect1->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( sect1 );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="title" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ sect1->setText( 0, data.nodeValue() );
+ sect1->setValue(KSayItGlobal::RTFHEADER, data.nodeValue());
+ sect1->setValue(KSayItGlobal::SPEAKERHEADER, data.nodeValue());
+ }
+ } else if ( node.isElement() && node.nodeName().lower()=="para" ){
+ parsePara( node.toElement(), sect1 );
+ } else if ( node.isElement() && node.nodeName().lower()=="sect2" ){
+ parseSect2( node.toElement(), sect1 );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseSect1()" << endl;
+}
+
+
+void DocbookParser::parseSect2(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseSect2()" << endl;
+
+ QDomText data;
+ Sect2 *sect2 = new Sect2(item, NULL, i18n("Section Level 2"));
+ sect2->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( sect2 );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="title" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ sect2->setText( 0, data.nodeValue() );
+ sect2->setValue(KSayItGlobal::RTFHEADER, data.nodeValue());
+ sect2->setValue(KSayItGlobal::SPEAKERHEADER, data.nodeValue());
+ }
+ } else if ( node.isElement() && node.nodeName().lower()=="para" ){
+ parsePara( node.toElement(), sect2 );
+ } else if ( node.isElement() && node.nodeName().lower()=="sect3" ){
+ parseSect3( node.toElement(), sect2 );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseSect2()" << endl;
+}
+
+
+void DocbookParser::parseSect3(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseSect3()" << endl;
+
+ QDomText data;
+ Sect3 *sect3 = new Sect3(item, NULL, i18n("Section Level 3"));
+ sect3->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( sect3 );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="title" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ sect3->setText( 0, data.nodeValue() );
+ sect3->setValue(KSayItGlobal::RTFHEADER, data.nodeValue());
+ sect3->setValue(KSayItGlobal::SPEAKERHEADER, data.nodeValue());
+ }
+ } else if ( node.isElement() && node.nodeName().lower()=="para" ){
+ parsePara( node.toElement(), sect3 );
+ } else if ( node.isElement() && node.nodeName().lower()=="sect4" ){
+ parseSect4( node.toElement(), sect3 );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseSect3()" << endl;
+}
+
+
+void DocbookParser::parseSect4(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseSect4()" << endl;
+
+ QDomText data;
+ Sect4 *sect4 = new Sect4(item, NULL, i18n("Section Level 4"));
+ sect4->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( sect4 );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="title" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ sect4->setText( 0, data.nodeValue() );
+ sect4->setValue(KSayItGlobal::RTFHEADER, data.nodeValue());
+ sect4->setValue(KSayItGlobal::SPEAKERHEADER, data.nodeValue());
+ }
+ } else if ( node.isElement() && node.nodeName().lower()=="para" ){
+ parsePara( node.toElement(), sect4 );
+ } else if ( node.isElement() && node.nodeName().lower()=="sect5" ){
+ parseSect5( node.toElement(), sect4 );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseSect4()" << endl;
+}
+
+
+void DocbookParser::parseSect5(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parseSect5()" << endl;
+
+ QDomText data;
+ Sect5 *sect5 = new Sect5(item, NULL, i18n("Section Level 4"));
+ sect5->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( sect5 );
+
+ QDomNode node = element.firstChild();
+ while( !node.isNull() ){
+ if( node.isElement() && node.nodeName().lower()=="title" ){
+ data = node.firstChild().toText();
+ if( !data.isNull() ){
+ sect5->setText( 0, data.nodeValue() );
+ sect5->setValue(KSayItGlobal::RTFHEADER, data.nodeValue());
+ sect5->setValue(KSayItGlobal::SPEAKERHEADER, data.nodeValue());
+ }
+ } else if ( node.isElement() && node.nodeName().lower()=="para" ){
+ parsePara( node.toElement(), sect5 );
+ }
+ node = node.nextSibling();
+ }
+ kdDebug(100200) << "--- leaving parseSect5()" << endl;
+}
+
+
+void DocbookParser::parsePara(const QDomElement &element, ListViewInterface *item)
+{
+ kdDebug(100200) << "+++ entering parsePara()" << endl;
+
+ Para *para = new Para(item, NULL, i18n("Paragraph"));
+ para->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ // register Popup menu
+ m_contextmenuhandler->registerPopupMenu( para );
+
+ QString raw = node2raw(element);
+ // remove <para> tags
+ raw.replace( QRegExp("</?(para|Para|PARA)/?>"),"");
+ raw.replace( QRegExp("^ "),"" );
+ raw.replace( QRegExp("^\n"), "" );
+
+ para->setValue(KSayItGlobal::RAWDATA, raw);
+ para->setValue(KSayItGlobal::RTFDATA, raw);
+ para->setValue(KSayItGlobal::SPEAKERDATA, raw);
+
+ kdDebug(100200) << "--- leaving parsePara()" << endl;
+}
+
+
diff --git a/ksayit/src/docbookparser.h b/ksayit/src/docbookparser.h
new file mode 100644
index 0000000..e603e93
--- /dev/null
+++ b/ksayit/src/docbookparser.h
@@ -0,0 +1,64 @@
+//
+// C++ Interface: docbookparser
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef DOCBOOKPARSER_H
+#define DOCBOOKPARSER_H
+
+// Qt includes
+#include <qdom.h>
+
+// KDE includes
+
+// App specific includes
+#include "Types.h"
+#include "contextmenuhandler.h"
+
+
+class DocbookParser
+{
+public:
+ // Constructor
+ DocbookParser(ContextMenuHandler *cmHandler=0);
+
+ // Destructor
+ ~DocbookParser();
+
+ void parseBook(const QDomElement &element, ListViewInterface *item);
+
+ int getIdCounter(){ return m_idCounter; };
+
+private: // Methods
+ // a selection of DocBook elements
+ void parseBookInfo(const QDomElement &element, ListViewInterface *item);
+ void parseAuthorGroup(const QDomElement &element, ListViewInterface *item);
+ void parseAuthor(const QDomElement &element, ListViewInterface *item);
+ void parseKeywordSet(const QDomElement &element, ListViewInterface *item);
+ void parseAbstract(const QDomElement &element, ListViewInterface *item);
+ void parseChapter(const QDomElement &element, ListViewInterface *item);
+ void parseSect1(const QDomElement &element, ListViewInterface *item);
+ void parseSect2(const QDomElement &element, ListViewInterface *item);
+ void parseSect3(const QDomElement &element, ListViewInterface *item);
+ void parseSect4(const QDomElement &element, ListViewInterface *item);
+ void parseSect5(const QDomElement &element, ListViewInterface *item);
+ void parsePara(const QDomElement &element, ListViewInterface *item);
+
+ // Helpers
+ QString node2raw(QDomNode node) const;
+
+private: // Attributes
+ ContextMenuHandler *m_contextmenuhandler;
+ int m_idCounter;
+
+};
+
+#endif
+
+
diff --git a/ksayit/src/doctreeviewimpl.cpp b/ksayit/src/doctreeviewimpl.cpp
new file mode 100644
index 0000000..663933b
--- /dev/null
+++ b/ksayit/src/doctreeviewimpl.cpp
@@ -0,0 +1,1141 @@
+//
+// C++ Implementation: doctreeviewimpl
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include <stdlib.h> // getenv
+
+// Qt includes
+#include <qdom.h>
+#include <qfile.h>
+#include <qwidget.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <qdatetime.h>
+#include <qcolor.h>
+#include <qlistview.h>
+
+//KDE includes
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+
+// App specific includes
+#include "doctreeviewimpl.h"
+#include "contextmenuhandler.h"
+#include "parasaxparser.h"
+#include "docbookclasses.h"
+#include "docbookgenerator.h"
+#include "docbookparser.h"
+
+
+//////////////////////////////////////
+// TreeView Implementation
+//////////////////////////////////////
+DocTreeViewImpl::DocTreeViewImpl(QWidget* parent, const char* name, WFlags fl)
+ : DocTreeView(parent, name, fl)
+{
+ m_rootItem = NULL;
+ m_url = KURL();
+ // the hidden formated id to set a sort order
+ listView->setSorting(3, true);
+ listView->setColumnText(0, i18n("Chapter"));
+ listView->setColumnText(1, i18n("Info"));
+ listView->setColumnText(2, i18n("Page"));
+ listView->setColumnText(3, "");
+ listView->setResizeMode( KListView::NoColumn );
+ listView->setColumnWidthMode(0, KListView::Maximum );
+ listView->setColumnWidthMode(1, KListView::Maximum );
+ listView->setColumnWidthMode(2, KListView::Maximum );
+ listView->setColumnWidthMode(3, KListView::Manual );
+ listView->setColumnWidth(3, 0);
+ listView->setAlternateBackground( QColor(230, 230, 240) );
+ listView->setSelectionModeExt( KListView::Single );
+
+ m_idCounter = KSayItGlobal::item_initial_id;
+ m_stopped = false;
+ m_currentItem = m_rootItem;
+ m_parasaxparser = ParaSaxParser::Instance();
+ m_editMode = false;
+ m_changedContent = QString::null;
+
+ m_contextmenuhandler = NULL;
+ m_contextmenu = NULL;
+}
+
+
+DocTreeViewImpl::~DocTreeViewImpl()
+{
+ if ( m_rootItem )
+ delete m_rootItem;
+ delete m_parasaxparser;
+ if ( m_contextmenuhandler )
+ delete m_contextmenuhandler;
+}
+
+
+void DocTreeViewImpl::enableContextMenus( bool enabled )
+{
+ if ( enabled ){
+ m_contextmenuhandler = new ContextMenuHandler(this, "contextmenuhandler");
+ } else {
+ if ( m_contextmenuhandler )
+ delete m_contextmenuhandler;
+ m_contextmenuhandler = NULL;
+ }
+}
+
+
+void DocTreeViewImpl::clear()
+{
+ kdDebug(100200) << "DocTreeViewImpl::clear()" << endl;
+ m_url = KURL();
+
+ if ( m_rootItem )
+ delete m_rootItem;
+
+ // inform BookmarkHandler
+ //
+ emit signalSetBookmarkFilename( QString::null );
+
+ listView->clear();
+ m_rootItem = new RobDocument( listView, i18n("unnamed") );
+ m_idCounter = KSayItGlobal::item_initial_id;
+ m_stopped = false;
+ m_currentItem = static_cast<ListViewInterface*>(m_rootItem);
+}
+
+
+void DocTreeViewImpl::createEmptyDocument()
+{
+ kdDebug(100200) << "DocTreeViewImpl::createEmptyDocument()" << endl;
+ // create empty document
+ QByteArray data;
+ QTextStream wrapped(data, IO_ReadWrite);
+ wrapped.setEncoding(QTextStream::UnicodeUTF8);
+
+ wrapped << "<?xml version=\"1.0\" ?>" << endl;
+ wrapped << "<!--" << endl;
+ wrapped << "!DOCTYPE book PUBLIC \"-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN\" \"dtd/kdex.dtd\"" << endl;
+ wrapped << "-->" << endl;
+
+ QString header(data);
+ m_parasaxparser->setProcessingInstruction( header );
+
+ wrapped << "<book>" << endl;
+ wrapped << "<bookinfo>" << endl;
+ wrapped << "<title><![CDATA[" << i18n("Empty Document") << "]]></title>" << endl;
+ wrapped << "<authorgroup>" << endl;
+ wrapped << "<author>" << endl;
+ wrapped << "<firstname>KSayIt</firstname>" << endl;
+ wrapped << "<surname>Wrapper</surname>" << endl;
+ wrapped << "</author>" << endl;
+ wrapped << "</authorgroup>" << endl;
+ wrapped << "<copyright>" << endl;
+ wrapped << "<year>2005</year>" << endl;
+ wrapped << "<holder>Robert Vogl</holder>" << endl;
+ wrapped << "</copyright>" << endl;
+ wrapped << "</bookinfo>" << endl;
+ wrapped << "<chapter>" << endl;
+ wrapped << "<title><![CDATA[" << i18n("Untitled") << "]]></title>" << endl;
+ wrapped << "<para>" << endl;
+ wrapped << "";
+ wrapped << "</para>" << endl;
+ wrapped << "</chapter>" << endl;
+ wrapped << "</book>" << endl;
+
+ QDomDocument domTree;
+ if ( ! domTree.setContent( data ) ){
+ kdDebug(100200) << "Kein gueltiges Dokument!!" << endl;
+ };
+ // inform BookmarkHandler
+ emit signalSetBookmarkFilename( i18n("Untitled") );
+
+ QDomElement root = domTree.documentElement();
+ QDomNode node;
+ if( root.tagName().lower() == "book" ){ // DocBook
+ DocbookParser docbookparser(m_contextmenuhandler);
+ docbookparser.parseBook(root , m_rootItem);
+ m_idCounter = docbookparser.getIdCounter();
+ }
+
+ // Initial view
+ m_currentItem = static_cast<ListViewInterface*>( listView->lastItem() );
+ listView->setSelected( m_currentItem, true );
+ listView->ensureItemVisible( m_currentItem );
+ slotItemClicked( m_currentItem );
+}
+
+
+void DocTreeViewImpl::openFile(const KURL &url)
+{
+ kdDebug(100200) << "DocTreeViewImpl::openFile(" << url.path() << ")" << endl;
+
+ m_url = url;
+ // open file
+ QString err;
+ QFile file( url.path() );
+ if( !file.open(IO_ReadOnly) ){
+ err = i18n("Unable to open File.");
+ throw(err);
+ }
+ QDomDocument domTree;
+ // check document
+ if( domTree.setContent(&file) ){
+ // extract Header
+ file.reset();
+ QString header = QString::null;
+ QString line;
+ int offset;
+ file.readLine( line, file.size() );
+ while( !file.atEnd() && (offset = line.find("<book", 0, false)) < 0 ){
+ header += line;
+ file.readLine( line, file.size() );
+ }
+ file.close();
+ header += line.left( offset );
+ kdDebug(100200) << "### Header: " << endl << header << endl;
+ m_parasaxparser->setProcessingInstruction( header );
+ // inform BookmarkHandler about the opened file
+ emit signalSetBookmarkFilename( url.fileName() );
+ } else {
+ // File is not a valid XML-File. Wrap it
+ file.reset();
+ QByteArray data;
+ QTextStream wrapped(data, IO_ReadWrite);
+ wrapped.setEncoding(QTextStream::UnicodeUTF8);
+
+ wrapped << "<?xml version=\"1.0\" ?>" << endl;
+ wrapped << "<!--" << endl;
+ wrapped << "!DOCTYPE book PUBLIC \"-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN\" \"dtd/kdex.dtd\"" << endl;
+ wrapped << "-->" << endl;
+
+ QString header(data);
+ kdDebug(100200) << "Header (Wrapper): " << endl << header << endl;
+ m_parasaxparser->setProcessingInstruction( header );
+
+ wrapped << "<book>" << endl;
+ wrapped << "<bookinfo>" << endl;
+ wrapped << "<title><![CDATA[" << url.path() << "]]></title>" << endl;
+ wrapped << "<authorgroup>" << endl;
+ wrapped << "<author>" << endl;
+ wrapped << "<firstname>KSayIt</firstname>" << endl;
+ wrapped << "<surname>Wrapper</surname>" << endl;
+ wrapped << "</author>" << endl;
+ wrapped << "</authorgroup>" << endl;
+ wrapped << "<copyright>" << endl;
+ wrapped << "<year>2005</year>" << endl;
+ wrapped << "<holder>Robert Vogl</holder>" << endl;
+ wrapped << "</copyright>" << endl;
+ wrapped << "</bookinfo>" << endl;
+ wrapped << "<chapter>" << endl;
+ wrapped << "<title><![CDATA[" << i18n("Plain File") << "]]></title>" << endl;
+ wrapped << "<para><![CDATA[";
+ wrapped << QString( file.readAll() );
+ wrapped << "]]></para>" << endl;
+ wrapped << "</chapter>" << endl;
+ wrapped << "</book>" << endl;
+ file.close();
+
+ // Try again
+ if (! domTree.setContent(data)){
+ err = i18n("Failed wrapping the file into XML.");
+ throw(err);
+ }
+ emit signalSetBookmarkFilename( i18n("Plain File") );
+ }
+
+ // check if correct document type
+ QDomElement root = domTree.documentElement();
+ if( root.tagName().lower() == "book" ){ // DocBook
+ DocbookParser docbookparser(m_contextmenuhandler);
+ docbookparser.parseBook(root , m_rootItem);
+ m_idCounter = docbookparser.getIdCounter();
+ } else {
+ err = i18n("The file is of type %1, 'book' expected.").arg(root.tagName() );
+ throw(err);
+ }
+
+ // Initial view
+ listView->setSelected( m_rootItem, true );
+ slotItemClicked( m_rootItem );
+}
+
+
+void DocTreeViewImpl::saveFile()
+{
+ kdDebug(100200) << "DocTreeViewImpl::saveFile()" << endl;
+
+ makeCurrentNodePersistent();
+
+ QString err;
+
+ if ( m_url.isEmpty() ){ // file has no name, ask user
+ QString usershome( getenv("HOME") );
+ m_url = KFileDialog::getSaveURL(usershome, "*.docbook", this, i18n("Save File"));
+ }
+ if ( m_url.isEmpty() ) // dialog cancelled
+ return;
+ if ( !m_url.isValid() ){
+ err = i18n("The given URL is invalid. Try 'File save as...' instead.");
+ throw( err );
+ }
+ if ( m_url.isLocalFile() ){
+ QFile file( m_url.path() );
+ if ( !file.open(IO_WriteOnly) ){
+ err = i18n("Unable open file to write.");
+ throw( err );
+ }
+ // write file
+ QTextStream doc(&file);
+ doc.setEncoding(QTextStream::UnicodeUTF8);
+
+ doc << "<?xml version=\"1.0\" ?>" << endl;
+ doc << "<!--" << endl;
+ doc << "!DOCTYPE book PUBLIC \"-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN\" \"dtd/kdex.dtd\"" << endl;
+ doc << "-->" << endl;
+
+ DocbookGenerator generator;
+ generator.writeBook( doc, m_rootItem );
+
+ // update root item
+ m_rootItem->setText(0, m_url.fileName() );
+ m_rootItem->setValue(KSayItGlobal::RTFHEADER, m_url.fileName());
+ m_rootItem->setValue(KSayItGlobal::SPEAKERHEADER, m_url.fileName());
+ file.close();
+ } else {
+ err = i18n("Save operation currently works on local files only.");
+ throw( err );
+ }
+ // inform BookmarkHandler
+ emit signalChangeBookmarkFilename( m_url.fileName() );
+ slotItemClicked( m_currentItem );
+}
+
+
+void DocTreeViewImpl::saveFileAs()
+{
+ kdDebug(100200) << "DocTreeViewImpl::saveFileAs()" << endl;
+ QString err;
+
+ makeCurrentNodePersistent();
+
+ m_url = KFileDialog::getSaveURL(QString::null, "*.docbook", this, i18n("Save File As"));
+ if ( m_url.isEmpty() ) // dialog cancelled
+ return;
+ if ( !m_url.isValid() ){
+ err = i18n("The given URL is invalid.");
+ throw( err );
+ }
+ if ( m_url.isLocalFile() ){
+ QFile file( m_url.path() );
+ if ( !file.open(IO_WriteOnly) ){
+ err = i18n("Unable open file to write.");
+ throw( err );
+ }
+
+ // write file
+ QTextStream doc(&file);
+ doc.setEncoding(QTextStream::UnicodeUTF8);
+
+ doc << "<?xml version=\"1.0\" ?>" << endl;
+ doc << "<!--" << endl;
+ doc << "!DOCTYPE book PUBLIC \"-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN\" \"dtd/kdex.dtd\"" << endl;
+ doc << "-->" << endl;
+
+ DocbookGenerator generator;
+ generator.writeBook( doc, m_rootItem );
+
+ // update root item
+ m_rootItem->setText(0, m_url.fileName() );
+ m_rootItem->setValue(KSayItGlobal::RTFHEADER, m_url.fileName());
+ m_rootItem->setValue(KSayItGlobal::SPEAKERHEADER, m_url.fileName());
+
+ file.close();
+ } else {
+ err = i18n("Save operation currently works on local files only.");
+ throw( err );
+ }
+ // inform BookmarkHandler
+ emit signalChangeBookmarkFilename( m_url.fileName() );
+ slotItemClicked( m_currentItem );
+}
+
+
+void DocTreeViewImpl::setEditMode(bool mode)
+{
+ m_editMode = mode;
+ bool editable = ( m_currentItem->getValue(KSayItGlobal::ISEDITABLE) ).toBool();
+ if ( editable && mode ){
+ emit signalEnableTextedit( true );
+ slotItemClicked( m_currentItem );
+ return;
+ }
+
+ makeCurrentNodePersistent();
+ slotItemClicked( m_currentItem );
+
+ emit signalEnableTextedit( false );
+}
+
+
+void DocTreeViewImpl::makeToSingleLine( QString &content )
+{
+ // canonify string
+ content.replace( QRegExp("\n"), "" ); // remove Newlines
+ content.replace( QRegExp(" {2,}"), " " ); // remove multiple spaces
+ content.replace( QRegExp("[\t|\r]{1,}"), ""); // remove Tabs
+}
+
+
+QString DocTreeViewImpl::selectItemByID(const QString &ID, const QString title)
+{
+ kdDebug(100200) << "DocTreeViewImpl::selectItemByID(" << ID << ")" << endl;
+
+ if ( ID.isNull() )
+ return QString::null;
+
+ QString sTitle = title.lower();
+ QString err = QString::null;
+
+ /**
+ * Search on structure (URL)
+ * e.g. 1=RobDokument|1=BookInfo|1=KeywordSet|2=Keyword
+ */
+ QStringList partList;
+ partList = QStringList::split("|", ID);
+ QStringList::Iterator it = partList.begin();
+ it++; // skip first element (allways RobDocument)
+ int childNum = 0;
+ QString childType = QString::null;
+ ListViewInterface *item = m_rootItem;
+ bool hit = false;
+
+ for (; it!=partList.end(); ++it){
+ kdDebug(100200) << "Part: " << (*it) << endl;
+ if ( !item )
+ break; // expected item does not exist
+ item = static_cast<ListViewInterface*>( item->firstChild() );
+ if ( item ){
+ childNum = ((*it).section('=', 0, 0)).toInt();
+ childType = (*it).section('=', 1, 1);
+ childType = childType.lower();
+ for (int i=1; i<childNum; i++){
+ item = static_cast<ListViewInterface*>( item->nextSibling() );
+ if ( !item )
+ break; // expected item does not exist
+ }
+ if ( !item )
+ break; // expected item does not exist
+ QString type = ( item->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ type = type.lower();
+ if ( childType != type )
+ break; // structure has been changed
+ }
+ }
+
+ if ( item ){
+ QString itemTitle = getItemTitle( item );
+ itemTitle = itemTitle.lower();
+ if ( sTitle.left(itemTitle.length()) == itemTitle )
+ // Title made unique by KDE by appending "(2)", "(3)"...
+ hit = true;
+ }
+
+ if ( !hit ){
+ /**
+ * Not found, search on title
+ */
+ // walk trough the entire tree and try to find an item
+ // with the given title.
+ item = NULL;
+ QListViewItemIterator sit( m_rootItem );
+ QString itemTitle = QString::null;
+ while ( sit.current() ) {
+ item = static_cast<ListViewInterface*>(sit.current());
+ if ( !item )
+ break; // expected item does not exist
+ itemTitle = getItemTitle( item );
+ itemTitle = itemTitle.lower();
+ if ( sTitle.left(itemTitle.length()) == itemTitle ){
+ hit = true;
+ err = i18n("Maybe the structure of the document has been changed. Please check if this bookmark is still valid.");
+ break;
+ }
+ ++sit;
+ }
+ }
+
+ // still not found => Failure
+ if ( !hit ){
+ err = i18n("Bookmark not found. Maybe the file content or the bookmark URL has been changed.");
+ return err;
+ }
+
+ // show
+ bool editable = ( item->getValue(KSayItGlobal::ISEDITABLE) ).toBool();
+ if ( editable )
+ makeCurrentNodePersistent();
+
+ listView->setSelected( item, true );
+ listView->ensureItemVisible( item );
+ slotItemClicked( item );
+ return err;
+}
+
+
+void DocTreeViewImpl::slotItemClicked(QListViewItem *item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::slotItemClicked()" << endl;
+
+ if ( item != m_currentItem ){
+ makeCurrentNodePersistent();
+ }
+
+ if ( item ){
+ m_currentItem = static_cast<ListViewInterface*>(item);
+ QString str = QString::null;
+ QTextStream msg(&str, IO_ReadWrite);
+ msg.setEncoding(QTextStream::UnicodeUTF8);
+
+ // check if item has a child and check state
+ // of Edit Mode.
+ bool editable = ( m_currentItem->getValue(KSayItGlobal::ISEDITABLE) ).toBool() && m_editMode;
+
+ emit signalEnableTextedit( editable );
+ recursiveTextCollector( m_currentItem, msg, !editable );
+ emit signalContentChanged( str );
+
+ // Create Bookmark-ID depending on the location of the item
+ // within the tree
+ QString idstring = QString::null;
+ QTextStream id(&idstring, IO_ReadWrite);
+ id.setEncoding(QTextStream::UnicodeUTF8);
+ id << "1=RobDocument";
+ recursiveBuildItemIdentifier( m_currentItem, id );
+
+ // inform the Bookmark Manager about the new item.
+ QString title = getItemTitle( m_currentItem );
+ emit signalNotifyBookmarkManager(idstring, title);
+ }
+}
+
+
+void DocTreeViewImpl::slotRightButtonPressed(QListViewItem *item, const QPoint &pos, int)
+{
+ kdDebug(100200) << "DocTreeViewImpl::slotRightButtonPressed()" << endl;
+ slotItemClicked( item );
+
+ if ( !m_currentItem )
+ return;
+
+ m_contextmenu = m_contextmenuhandler->getPopupMenu( m_currentItem );
+ if ( !m_contextmenu )
+ return;
+
+ m_contextmenu->exec( pos );
+}
+
+
+void DocTreeViewImpl::recursiveBuildItemIdentifier(ListViewInterface* item, QTextStream &idstring)
+{
+ kdDebug(100200) << "DocTreeViewImpl::recursiveBuildItemIdentifier()" << endl;
+
+ if ( !item )
+ return;
+
+ // 1. Do we have a parent (=parentItem)?
+ // If no -> return, if yes -> recursive call
+ ListViewInterface *parentItem = NULL;
+ parentItem = static_cast<ListViewInterface*>( item->parent() );
+ if ( parentItem ){
+ recursiveBuildItemIdentifier( parentItem, idstring );
+ } else {
+ // break recursion
+ return;
+ }
+
+ // 2. Which child of the parentItem are we? Append no. to idstring.
+ int childno = 0;
+ QString itemID = item->text(3);
+ ListViewInterface *i = static_cast<ListViewInterface*>( parentItem->firstChild() );
+ while( i ){
+ childno++;
+ if ( i->text(3) == itemID )
+ break;
+ i = static_cast<ListViewInterface*>( i->nextSibling() );
+ }
+ idstring << "|" << childno;
+
+ // 3. Who are we? Append ID to idstring.
+ QString itemType = ( item->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ idstring << "=" << itemType;
+}
+
+
+QString DocTreeViewImpl::getItemTitle( ListViewInterface *item )
+{
+ if ( !item )
+ return QString::null;
+
+ QString col0 = item->text(0);
+ QString title = QString::null;
+ // if ( col0 == i18n("Paragraph") ){ // better to use XmlContextName?
+ if( (item->getValue(KSayItGlobal::XMLCONTEXTNAME)).toString() == i18n("Paragraph") ){
+ title = ( item->getValue(KSayItGlobal::SPEAKERDATA) ).toString().left(32);
+
+ // canonify string
+ title.replace( QRegExp("^( |\t|\n)+"), "");
+ title.replace( QRegExp("( |\t|\n)$+"), "");
+ } else {
+ title = col0.left(32);
+ }
+ return title;
+}
+
+
+void DocTreeViewImpl::recursiveTextCollector(ListViewInterface* item, QTextStream &msg, bool header)
+{
+ kdDebug(100200) << "DocTreeViewImpl::recursiveTextCollector()" << endl;
+
+ QString text;
+ if ( header ){
+ // if header==true get Headers
+ msg << ( item->getValue(KSayItGlobal::RTFHEADER) ).toString();
+ text = ( item->getValue(KSayItGlobal::RTFDATA ) ).toString();
+ } else {
+ // get raw data (Edit Mode)
+ text = ( item->getValue(KSayItGlobal::RAWDATA) ).toString();
+ }
+ if ( !text.isNull() )
+ msg << text;
+
+ // check if current item has a child
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+
+ while( i ){
+ recursiveTextCollector( i, msg, header );
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+}
+
+
+void DocTreeViewImpl::sayActiveNodeAndChilds()
+{
+ kdDebug(100200) << "DocTreeViewImpl::sayActiveNodeAndChilds()" << endl;
+
+ m_stopped = false;
+ if ( !(m_currentItem->firstChild()) ){
+ // current item has no childs. It may be changed.
+ makeCurrentNodePersistent();
+ }
+
+ recursiveSayNodes( m_currentItem );
+ emit signalAllNodesProcessed();
+}
+
+
+void DocTreeViewImpl::recursiveSayNodes(ListViewInterface* item)
+{
+ kdDebug(100200) << "DocTreeViewImpl::recursiveSayNodes()" << endl;
+
+ QString str;
+ QTextStream msg(&str, IO_ReadWrite);
+ msg.setEncoding(QTextStream::UnicodeUTF8);
+
+ msg << ( item->getValue(KSayItGlobal::SPEAKERHEADER) ).toString();
+ msg << ( item->getValue(KSayItGlobal::SPEAKERDATA) ).toString() << "\n" << endl;
+
+ // request say task
+ if ( !m_stopped ){
+ emit signalSetText( str );
+ } else {
+ return;
+ }
+
+ // check if current item has a child
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ while( i ){
+ recursiveSayNodes( i );
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+}
+
+
+void DocTreeViewImpl::stop()
+{
+ kdDebug(100200) << "DocTreeViewImpl::stop()" << endl;
+ m_stopped = true;
+}
+
+
+void DocTreeViewImpl::setNodeContent(QString &text)
+{
+ kdDebug(100200) << "DocTreeViewImpl::setNodeContent()" << endl;
+ m_changedContent = text;
+}
+
+
+void DocTreeViewImpl::makeCurrentNodePersistent()
+{
+ kdDebug(100200) << "DocTreeViewImpl::slotMakeCurrentNodePersistent()" << endl;
+ if ( m_changedContent.isNull() )
+ return; // no changes were happen
+
+ int maxlines = ( m_currentItem->getValue(KSayItGlobal::MAXLINES) ).toInt();
+ if ( maxlines == 1 ){ // Item with max. 1 line.
+ makeToSingleLine( m_changedContent );
+ }
+
+ m_currentItem->setValue( KSayItGlobal::RAWDATA, m_changedContent );
+ m_currentItem->setValue( KSayItGlobal::RTFDATA, m_changedContent );
+ m_currentItem->setValue( KSayItGlobal::SPEAKERDATA, m_changedContent );
+
+ m_changedContent = QString::null;
+}
+
+/** replaced by slotRightButtonPressed()
+ */
+// void DocTreeViewImpl::contextMenuEvent(QContextMenuEvent *e)
+// {
+// kdDebug(100200) << "DocTreeViewImpl::contextMenuEvent()" << endl;
+//
+// if ( !m_currentItem )
+// return;
+//
+// m_contextmenu = m_contextmenuhandler->getPopupMenu( m_currentItem );
+// if ( !m_contextmenu )
+// return;
+//
+// m_contextmenu->exec( e->globalPos() );
+// }
+
+
+/******************************************
+ * Context-Menu functions
+ ******************************************/
+
+void DocTreeViewImpl::slotRenameItem()
+{
+ kdDebug(100200) << "DocTreeViewImpl::slotRenameItem()" << endl;
+
+ if (!m_currentItem)
+ return;
+
+ bool responseOK;
+ QString newname;
+ newname = KInputDialog::getText(
+ i18n("Rename Item"),
+ i18n("Please enter the new name of the item:"),
+ m_currentItem->text(0),
+ &responseOK,
+ this,
+ "queryNewItemName"
+ );
+ if ( !responseOK )
+ return;
+
+ // update TreeView
+ m_currentItem->setText(0, newname);
+ m_currentItem->setValue( KSayItGlobal::RTFHEADER, newname );
+ m_currentItem->setValue( KSayItGlobal::SPEAKERHEADER, newname );
+}
+
+
+void DocTreeViewImpl::slotDeleteItem()
+{
+ kdDebug(100200) << "DocTreeViewImpl::slotDeleteItem()" << endl;
+
+ ListViewInterface *itemToDelete = m_currentItem;
+ ListViewInterface *parentItem = NULL;
+ parentItem = static_cast<ListViewInterface*>(itemToDelete->parent());
+ if ( !parentItem )
+ return; // delete only items with parent
+
+ // try to delete bookmark
+ QString url = QString::null;
+ QTextStream id(&url, IO_ReadWrite);
+ id.setEncoding(QTextStream::UnicodeUTF8);
+ id << "ksayit://1=RobDocument";
+ recursiveBuildItemIdentifier( itemToDelete, id );
+ QString title = getItemTitle( itemToDelete );
+ emit signalDeleteBookmark( url, title );
+
+ // remove TreeView item
+ delete itemToDelete;
+
+ // reindex entire remaining tree
+ ListViewInterface *item = NULL;
+ m_idCounter = KSayItGlobal::item_initial_id;
+ QListViewItemIterator itr( m_rootItem );
+ while ( itr.current() ) {
+ item = static_cast<ListViewInterface*>(itr.current());
+ item->setText(3, QString("%1").arg(++m_idCounter).rightJustify(8,'0') );
+ ++itr;
+ }
+
+ // show
+ m_rootItem->sort();
+ listView->setSelected( parentItem, true );
+ listView->ensureItemVisible( parentItem );
+ slotItemClicked( parentItem );
+}
+
+
+void DocTreeViewImpl::slotNewBookInfo()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "RobDocument" ){
+ int newIndex = newIndexFirstChild();
+ Overview *overview = new Overview( m_currentItem, NULL, i18n("Overview") );
+ overview->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ m_contextmenuhandler->registerPopupMenu( overview );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewChapter()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "RobDocument" ){
+ int newIndex = newIndexLastChild();
+ Chapter *chapter = new Chapter( m_currentItem, NULL, i18n("Chapter") );
+ chapter->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ QString newTitle = i18n("New Chapter Title");
+ chapter->setText(0, newTitle );
+ chapter->setValue(KSayItGlobal::RTFHEADER, newTitle );
+ chapter->setValue(KSayItGlobal::SPEAKERHEADER, newTitle );
+
+ m_contextmenuhandler->registerPopupMenu( chapter );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewKeywordSet()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "BookInfo" ){
+ // New TreeView item
+ int newIndex = newIndexFirstChild();
+ KeywordSet *keywordset = new KeywordSet(m_currentItem, NULL, i18n("Keywords"));
+ keywordset->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ m_contextmenuhandler->registerPopupMenu( keywordset );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewKeyword()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "KeywordSet" ){
+ // New TreeView item
+ int newIndex = newIndexLastChild();
+ Keyword *keyword = new Keyword(m_currentItem, NULL, i18n("Keyword"));
+ keyword->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ QString newKeyword = i18n("New Keyword");
+ keyword->setText(0, newKeyword );
+ keyword->setValue(KSayItGlobal::RAWDATA, newKeyword);
+ keyword->setValue(KSayItGlobal::RTFDATA, newKeyword);
+ keyword->setValue(KSayItGlobal::SPEAKERDATA, newKeyword);
+
+ m_contextmenuhandler->registerPopupMenu( keyword );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewAbstract()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "BookInfo" ){
+ // New TreeView item
+ int newIndex = newIndexLastChild();
+ Abstract *abstract = new Abstract(m_currentItem, NULL, i18n("Abstract"));
+ abstract->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ m_contextmenuhandler->registerPopupMenu( abstract );
+
+ // add a new Para-Element
+ ListViewInterface *backup = m_currentItem;
+ m_currentItem = abstract;
+ slotNewParagraph();
+ m_currentItem = backup;
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewAuthorGroup()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "BookInfo" ){
+ // New TreeView item
+ int newIndex = newIndexFirstChild();
+ AuthorGroup *authorgroup = new AuthorGroup(m_currentItem, NULL, i18n("Author(s)"));
+ authorgroup->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ m_contextmenuhandler->registerPopupMenu( authorgroup );
+
+ // add a new Author-Element
+ ListViewInterface *backup = m_currentItem;
+ m_currentItem = authorgroup;
+ slotNewAuthor();
+ m_currentItem = backup;
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewAuthor()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "AuthorGroup" ){
+ // New TreeView item
+ int newIndex = newIndexLastChild();
+ Author *author = new Author(m_currentItem);
+ author->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ author->setText(0, i18n("Author") );
+ QString newAuthor = i18n("Firstname Surname");
+ author->setText(1, newAuthor );
+ author->setValue( KSayItGlobal::RAWDATA, newAuthor );
+ author->setValue( KSayItGlobal::RTFDATA, newAuthor );
+ author->setValue( KSayItGlobal::SPEAKERDATA, newAuthor );
+
+ m_contextmenuhandler->registerPopupMenu( author );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewDate()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "BookInfo" ){
+ // New TreeView item
+ int newIndex = newIndexLastChild();
+ Date *date = new Date(m_currentItem, NULL, i18n("Date"));
+ date->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+ // get current date
+ QString today;
+ today = KGlobal::locale()->formatDate(QDate::currentDate(Qt::LocalTime), true);
+ date->setText( 1, today);
+ date->setValue( KSayItGlobal::RAWDATA, today );
+ date->setValue( KSayItGlobal::RTFDATA, today );
+ date->setValue( KSayItGlobal::SPEAKERDATA, today );
+
+ m_contextmenuhandler->registerPopupMenu( date );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewReleaseInfo()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "BookInfo" ){
+ // New TreeView item
+ int newIndex = newIndexLastChild();
+ ReleaseInfo *relinfo = new ReleaseInfo(m_currentItem, NULL, i18n("Release"));
+ relinfo->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ QString newRelease = "0.0.0";
+ relinfo->setText( 1, newRelease );
+ relinfo->setValue( KSayItGlobal::RAWDATA, newRelease );
+ relinfo->setValue( KSayItGlobal::RTFDATA, newRelease );
+ relinfo->setValue( KSayItGlobal::SPEAKERDATA, newRelease );
+
+ m_contextmenuhandler->registerPopupMenu( relinfo );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewTitle()
+{
+
+}
+
+void DocTreeViewImpl::slotNewParagraph()
+{
+/* // Create Null element
+ QDomElement parentElement = QDomElement();
+
+ NodeList_type list;
+ list.clear();
+ m_currentItem->getNodes( list );
+ parentElement = (list.front()).toElement();
+
+ if ( parentElement.isNull() )
+ return;
+*/
+ // New TreeView item
+ int newIndex = newIndexLastChild();
+ Para *para = new Para(m_currentItem, NULL, i18n("Paragraph"));
+ para->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ m_contextmenuhandler->registerPopupMenu( para );
+
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewSection_1()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "Chapter" ){
+ int newIndex = newIndexLastChild();
+ Sect1 *sect1 = new Sect1(m_currentItem, NULL, i18n("Section Level 1"));
+ sect1->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ QString newTitle = i18n("New Section Title");
+ sect1->setValue( KSayItGlobal::RTFHEADER, newTitle );
+ sect1->setValue( KSayItGlobal::SPEAKERHEADER, newTitle );
+
+ m_contextmenuhandler->registerPopupMenu( sect1 );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewSection_2()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "Sect1" ){
+ int newIndex = newIndexLastChild();
+ Sect2 *sect2 = new Sect2(m_currentItem, NULL, i18n("Section Level 2"));
+ sect2->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ QString newTitle = i18n("New Section Title");
+ sect2->setValue( KSayItGlobal::RTFHEADER, newTitle );
+ sect2->setValue( KSayItGlobal::SPEAKERHEADER, newTitle );
+
+ m_contextmenuhandler->registerPopupMenu( sect2 );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewSection_3()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "Sect2" ){
+ int newIndex = newIndexLastChild();
+ Sect3 *sect3 = new Sect3(m_currentItem, NULL, i18n("Section Level 3"));
+ sect3->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ QString newTitle = i18n("New Section Title");
+ sect3->setValue( KSayItGlobal::RTFHEADER, newTitle );
+ sect3->setValue( KSayItGlobal::SPEAKERHEADER, newTitle );
+
+ m_contextmenuhandler->registerPopupMenu( sect3 );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewSection_4()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "Sect3" ){
+ int newIndex = newIndexLastChild();
+ Sect4 *sect4 = new Sect4(m_currentItem, NULL, i18n("Section Level 4"));
+ sect4->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ QString newTitle = i18n("New Section Title");
+ sect4->setValue( KSayItGlobal::RTFHEADER, newTitle );
+ sect4->setValue( KSayItGlobal::SPEAKERHEADER, newTitle );
+
+ m_contextmenuhandler->registerPopupMenu( sect4 );
+ }
+ m_rootItem->sort();
+}
+
+void DocTreeViewImpl::slotNewSection_5()
+{
+ QString whoAmI = ( m_currentItem->getValue(KSayItGlobal::XMLCONTEXTNAME) ).toString();
+ if ( whoAmI == "Sect4" ){
+ int newIndex = newIndexLastChild();
+ Sect5 *sect5 = new Sect5(m_currentItem, NULL, i18n("Section Level 5"));
+ sect5->setText(3, QString("%1").arg(newIndex).rightJustify(8,'0') );
+
+ QString newTitle = i18n("New Section Title");
+ sect5->setValue( KSayItGlobal::RTFHEADER, newTitle );
+ sect5->setValue( KSayItGlobal::SPEAKERHEADER, newTitle );
+
+ m_contextmenuhandler->registerPopupMenu( sect5 );
+ }
+ m_rootItem->sort();
+}
+
+int DocTreeViewImpl::newIndexFirstChild()
+{
+ kdDebug(100200) << "DocTreeViewImpl::newIndexFirstChild()" << endl;
+
+ int currentIndex = (m_currentItem->text(3)).toInt();
+
+ // walk trough the entire tree and increment all
+ // indices greater than currentIndex
+ ListViewInterface *item = NULL;
+ int itemIndex;
+ QListViewItemIterator it( m_rootItem );
+ while ( it.current() ) {
+ item = static_cast<ListViewInterface*>(it.current());
+ itemIndex = (item->text(3)).toInt();
+ if ( itemIndex > currentIndex ){
+ item->setText(3, QString("%1").arg(itemIndex+1).rightJustify(8,'0') );;
+ }
+ ++it;
+ }
+
+ m_idCounter++;
+ currentIndex += 1;
+ return currentIndex;
+}
+
+
+int DocTreeViewImpl::newIndexLastChild()
+{
+ kdDebug(100200) << "DocTreeViewImpl::newIndexLastChild()" << endl;
+
+ // find highest index of the subtree with
+ // m_currentItem as root
+ int lastIndex = 0;
+ findHighestIndex( m_currentItem, lastIndex );
+ kdDebug(100200) << "Letzter Index: " << lastIndex << endl;
+
+ // walk trough the entire tree and increment all
+ // indices greater than lastIndex
+ int itemIndex;
+ ListViewInterface *item;
+ QListViewItemIterator it( m_rootItem );
+ while ( it.current() ) {
+ item = static_cast<ListViewInterface*>(it.current());
+ itemIndex = (item->text(3)).toInt();
+ if ( itemIndex > lastIndex ){
+ item->setText(3, QString("%1").arg(itemIndex+1).rightJustify(8,'0') );
+ }
+ ++it;
+ }
+
+ m_idCounter++;
+ lastIndex += 1;
+ return lastIndex;
+}
+
+
+void DocTreeViewImpl::findHighestIndex(ListViewInterface* item, int &index)
+{
+ int currentIndex = (item->text(3)).toInt();
+ index = currentIndex > index ? currentIndex : index;
+
+ ListViewInterface *i = static_cast<ListViewInterface*>(item->firstChild());
+ while( i ){
+ findHighestIndex(i, index);
+ i = static_cast<ListViewInterface*>(i->nextSibling());
+ }
+}
+
diff --git a/ksayit/src/doctreeviewimpl.h b/ksayit/src/doctreeviewimpl.h
new file mode 100644
index 0000000..4ad0c38
--- /dev/null
+++ b/ksayit/src/doctreeviewimpl.h
@@ -0,0 +1,191 @@
+//
+// C++ Interface: doctreeviewimpl
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef DOCTREEVIEWIMPL_H
+#define DOCTREEVIEWIMPL_H
+
+// Qt includes
+#include <qstring.h>
+
+// KDE includes
+#include <kurl.h>
+#include <klistview.h>
+#include <kpopupmenu.h>
+
+// App specific includes
+#include "Types.h"
+#include "DocTreeView.h"
+
+// forward declarations
+class ParaSaxParser;
+class ContextMenuHandler;
+
+
+/**
+This class implements the TreeView object.\n
+It takes a XML/DocBook file, parses it and builds up a hierarchical
+\p QListView structure corresponding to the structure of the document.
+The objective of this class is to maintain the document and provide
+all required methods to access or manipulate its content.
+@author Robert Vogl
+*/
+class DocTreeViewImpl : public DocTreeView
+{
+public:
+ DocTreeViewImpl(QWidget* parent=0, const char* name=0, WFlags fl=0);
+
+ ~DocTreeViewImpl();
+
+ /**
+ * Tries to open and parse the given file. If the file is not identified as a
+ * valid XML/DocBook file, it will be packed as a \p CDATA block into a \p para element
+ * of a simple DocBook'ish XML file.
+ * \param url The URL of the file.
+ */
+ void openFile(const KURL &url);
+
+ /**
+ * Saves the document to a XML file.
+ */
+ void saveFile();
+
+ /**
+ * Saves the document to a XML file and allows the user to define a name.
+ */
+ void saveFileAs();
+
+ /**
+ * Cleans up the interal document data structures.
+ */
+ void clear();
+
+ /**
+ * Creates an empty XML document that conatins one editable DocBook \p Paragraph.
+ * Usually called after clean() and initial startup.
+ */
+ void createEmptyDocument();
+
+ /**
+ * Stores the given text but does not make the new content
+ * persistent.
+ * \param text The content of the TextEdit view.
+ */
+ void setNodeContent(QString &text);
+
+ /**
+ * Starting from the current selected node it travels recursively
+ * through all childs and collects the content of all corresponding
+ * DOM nodes. After sending the text to the TTS system the speech synthesis
+ * process will be started.
+ */
+ void sayActiveNodeAndChilds();
+
+ /**
+ * Signals a stop-talking-request from the user.
+ */
+ void stop();
+
+ /**
+ * Controls the Edit Mode.
+ * \param mode If true, Edit Mode ON,\n if false, Edit Mode OFF.
+ */
+ void setEditMode(bool mode);
+
+ /**
+ * Sets the item active designated by the ID.
+ * \param ID The ID (column 3) of the TreeView item.
+ * \returns <tt>QString::null</tt> if the operation was successfull,\n
+ * an error message, if the item was not found.
+ */
+ QString selectItemByID(const QString &ID, const QString title);
+
+ /**
+ * Enables/disables the contextmenus
+ */
+ void enableContextMenus( bool enabled );
+
+public slots:
+ void slotRenameItem(); // reimplemented from base classes
+ void slotDeleteItem();
+ void slotNewBookInfo();
+ void slotNewChapter();
+ void slotNewKeywordSet();
+ void slotNewKeyword();
+ void slotNewAbstract();
+ void slotNewAuthorGroup();
+ void slotNewAuthor();
+ void slotNewDate();
+ void slotNewReleaseInfo();
+ void slotNewTitle();
+ void slotNewParagraph();
+ void slotNewSection_1();
+ void slotNewSection_2();
+ void slotNewSection_3();
+ void slotNewSection_4();
+ void slotNewSection_5();
+
+protected slots:
+ /**
+ * Reimplemented from base class.
+ * Called whenever the active node has been changed.\n
+ * Makes the former selected item persistent (maybe it has
+ * been changed).\n
+ * Displays the content of the selected Node either in RTF or
+ * plain text format (depending on the Edit Mode flag, childs
+ * present or not).\n
+ * Informs the BookmarkManager about the new item.
+ *
+ * \param item The new active item of the TreeView.
+ */
+ void slotItemClicked(QListViewItem *item);
+
+ /**
+ * Reimplemented from base class.
+ * Called when the right button was pressed.
+ * \param item The new active item of the TreeView.
+ */
+ void slotRightButtonPressed(QListViewItem *item, const QPoint &pos, int);
+
+ /**
+ * Reimplemented from QWidget class.
+ */
+ // void contextMenuEvent(QContextMenuEvent *e);
+
+private: // Methods
+ void recursiveTextCollector(ListViewInterface* item, QTextStream &msg, bool header=true);
+ void recursiveSayNodes(ListViewInterface* item);
+ void recursiveBuildItemIdentifier(ListViewInterface* item, QTextStream &idstring);
+ void makeCurrentNodePersistent();
+ int newIndexFirstChild();
+ int newIndexLastChild();
+ void findHighestIndex(ListViewInterface* item, int &index);
+ QString getItemTitle( ListViewInterface *item);
+ void makeToSingleLine( QString &content );
+
+
+private: // Attributes
+ ContextMenuHandler *m_contextmenuhandler;
+ KPopupMenu *m_contextmenu;
+ ListViewInterface *m_rootItem;
+ ListViewInterface *m_currentItem;
+ QString m_changedContent;
+ int m_idCounter;
+ bool m_stopped;
+ KURL m_url;
+ ParaSaxParser *m_parasaxparser;
+ bool m_editMode;
+};
+
+
+
+
+
+#endif
diff --git a/ksayit/src/effectstack.cpp b/ksayit/src/effectstack.cpp
new file mode 100644
index 0000000..7497847
--- /dev/null
+++ b/ksayit/src/effectstack.cpp
@@ -0,0 +1,65 @@
+//
+// C++ Implementation: effectstack
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// Qt includes
+#include <qstringlist.h>
+
+// KDE includes
+#include <kdebug.h>
+
+// App specific includes
+#include "effectstack.h"
+#include "fxpluginhandler.h"
+
+EffectStack::EffectStack(FXPluginHandler *pluginhandler, KConfig *config)
+ :
+ dispatcher(), server(),
+ m_pluginhandler(pluginhandler),
+ m_config(config)
+{
+}
+
+
+EffectStack::~EffectStack()
+{
+}
+
+bool EffectStack::loadEffects()
+{
+ kdDebug(100200) << "EffectStack::loadEffects()" << endl;
+
+ QStringList c_active;
+ QStringList::Iterator fx_it;
+
+ // create filterstack
+ FX_Stack = server.server().outstack();
+
+ m_config->setGroup("Effect Stack Configuration");
+ c_active = m_config->readListEntry("Activated");
+ for(fx_it=c_active.begin(); fx_it!=c_active.end(); ++fx_it){
+
+ m_pluginhandler->activateEffect(*fx_it, &server, &FX_Stack);
+
+ }
+ return true;
+}
+
+
+bool EffectStack::unloadEffects()
+{
+ kdDebug(100200) << "EffectStack::unloadEffects()" << endl;
+ // remove all effects
+ m_pluginhandler->deactivateEffects(&FX_Stack);
+
+ return true;
+}
+
diff --git a/ksayit/src/effectstack.h b/ksayit/src/effectstack.h
new file mode 100644
index 0000000..0716ef7
--- /dev/null
+++ b/ksayit/src/effectstack.h
@@ -0,0 +1,57 @@
+//
+// C++ Interface: effectstack
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef EFFECTSTACK_H
+#define EFFECTSTACK_H
+
+// KDE includes
+#include <arts/kmedia2.h>
+#include <kconfig.h>
+
+#include <arts/kartsdispatcher.h>
+#include <arts/kartsserver.h>
+#include <arts/soundserver.h>
+
+
+namespace Arts
+{
+ class SoundServerV2;
+}
+using namespace Arts;
+
+// forward declarations
+class FXPluginHandler;
+
+/**
+@author Robert Vogl
+*/
+class EffectStack{
+public:
+ EffectStack(FXPluginHandler *pluginhandler=0, KConfig *config=0);
+ ~EffectStack();
+
+ // KDE::PlayObject *playobj;
+ KArtsDispatcher dispatcher;
+ KArtsServer server;
+ StereoEffectStack FX_Stack;
+
+public: //Methods
+ bool loadEffects();
+ bool unloadEffects();
+
+private:
+ FXPluginHandler *m_pluginhandler;
+ KConfig *m_config;
+
+
+};
+
+#endif
diff --git a/ksayit/src/fx_setup.ui b/ksayit/src/fx_setup.ui
new file mode 100644
index 0000000..60ad57d
--- /dev/null
+++ b/ksayit/src/fx_setup.ui
@@ -0,0 +1,252 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>FX_Setup</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>FX_Setup</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>482</width>
+ <height>327</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Effect Stack Setup</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel_available</cstring>
+ </property>
+ <property name="text">
+ <string>Available:</string>
+ </property>
+ </widget>
+ <widget class="QListBox">
+ <property name="name">
+ <cstring>listBox_Available</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>170</height>
+ </size>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>toolButton_add</cstring>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>image0</iconset>
+ </property>
+ </widget>
+ <widget class="QToolButton">
+ <property name="name">
+ <cstring>toolButton_remove</cstring>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>image1</iconset>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel_active</cstring>
+ </property>
+ <property name="text">
+ <string>Active:</string>
+ </property>
+ </widget>
+ <widget class="QListBox">
+ <property name="name">
+ <cstring>listBox_Active</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>170</height>
+ </size>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Doubleclick opens the setup dialog.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>pushButton_removeAll</cstring>
+ </property>
+ <property name="text">
+ <string>Remove All</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="6143">789c9598c96e1e390e80ef790a23ba050375ed0b067370bcefbb637b3007925279df7f3bb61bf3eec3225995b8ba2f1301c1ff952889e226c97f7c9b3bd9dd9afbf6c797e719cc2e698e2ee069ee5b78b9bd7dfff77ffef5e797af59319795737992cc655ffff1e5ebde6c8ee6b6efef620fb4fb1bf84d06577718bb4ed8f5dcc9bf9edd43cf89fc93feabcffd743191dfff2c8ff544fe45fa9b34e6b9c8879ed33a2b95fdf567790f137e9bf0d667063f59bf9af0fe44fe6ed27f20fd79d7dafc9713fdcf3fcbc3db64fce3447e36b11f4ed6df9af4df4cf637b12fee4dd6eb26f2e7133e16ff1698753affcf9e5ba060fac9feb2a669632bfd79cf550054c6a6e7226ddb2e15f965f117568424fefb2efdb12995fdfb64fd897eb424faa7499e54327f695c287b9a8c8f130e13fb6d4fecf3d43374a136f9db497c1e4c78323fdc4ff4dd11fdba3c56b23f5c90fdb745a60c937ca167e94f591e8465ff699e77cafe43e46337e45b316189c7587499f186f82f207432de497cc572ec7f157f9634c4abd8235663ff0fe3dcf413f9ac68ca28f676b2dfaa00635a91fea48e41fd2bf156d62d28e3a2c867d075282cf1d6b454d8fcdb9fe303a57e64b1b6f820199f52d5622dfdbbd25f579db2177d288fa9f947ec4d594c6c3ff3c2c816d07eb12f41b4f5bdd497b622307d5665fe8cf7db887c6bfbe9942113fd4b327b91e463dad55d08a29fc4474e0d297bd90fe6c1eced0e27f126f9de368436df9aac9f37d8497d0389c7b282d258e2aba9c8fce3c5bfd084c19e9ba67fabf90ba9e41b9bcf58ea63db85c13e127f2d12d9f80df5779b746aff75e17260d8d4fc657d94a53e940534cafe49e7a7213f24bf1b24b33f883dda62883f67f5b7b5fd3ba9e749de9a3e28f327c8e272fea0caf7c3555ef44d0b307fb85ccf0728541e243e53607df5fc127fa6112ad3e748f707adcdaffbafc1e201c49f1940dd49bcc1b1f1e02fd96f86aded0fd55ec8fd6a3f39ffb2d00eeb751adfdc2ff9005a4f3ba04ee205ce8d83b1d4f33c1959e23b4f21dafea43ee619583d804563b3172c8facfa49fdc8f376b0bfd4a3bc1cfa49e76fdb41ff686cfa91f8230766cd57b1678eade987871affad9d17aed0f300077f48bc1525b3d68b758d4f34ffa09e0f34c697e65fc9f54ced25f5bc442ca2cacb795af6e9a3f34bfe56637e90cc57d5bcbf42e49f95f97cd3fdc9f8aac144fb41e55b1eaffd925f1562aafd24f1c9d52a537664e7e560cf1b651ae249f295ab59dd95d22ff5a8e684b37ea95f35216a7cf92363b31f8a7ff9be453ade6bfd49c9f21724be9a9c2c1e9cf8a72998d55f41eb15cf27f94f5eebc7c07863f5a48cea4fc99f86cb8f9edf78a4f57a602ffe6ac290cfa4f9dd511ad5ff1796df962f4eea754b7c7fd0f9a59e411a06fb887e50b2be7abf93f30caa9099fea21f871be9fd82e43c844831aabd24de3019eba9d81bd3d0983f9ec6faabeb89fdb108b9e9fb6a5c687df76bc696ff4ee203cb9859fd90f8403e60cd3f52bf1142a5f3b9c6183ad117c49e88ac8fc68bdce7308460f3497dc62e58fcba2be568f18f67725e2531ef443fd2f3ac084d147b6122cca7b1e587721da2facb493d2096b6faace7238de7a1d41b0acc6a6ff10ff169aef33bd18f933f0f1aff522f42124214f6bbcad1ec4f72be8474e847a99721e3ed4afcd2c3c8727f801b65d65fef7772ff60ef2476df90fd8422d441ef97d7c651f5a33be5419eee47d6f85835b6fc44676cf982521f4319539547392fd89b036f1b67761fc88c2bcd1ff761dcaafd49fc1bea515ef7c3091374bd17e5986b3feaf87660d835ae355ebcdc770307bcc587c443e0f48d9a9f97cab18c7adf3b3226bdfff913638b37a74c6c1f79e9b953e1c0fbd578927ac6d66dac1e9c1a0ff567d178384f245e79f241fe6464cdaf3563b0fbc7c6c8aabfde5f9351feddb83546635026d18fb505adfffe40b91beaa1d887ad6ffdf06a4c767f9a29f3fd56fd21f737b63e3f68a5bf3126654c95595ef591788a05cfa7fb298cad9eba4de5411ea43e717625560f9f8d53cb57a9a7b11ac663666cf90b627fb646d789bf40e2a7b7a6311ae75a6f7c635c597d91788ed80df92ef9d86b6fe34b633bcf40f28bb519b81e59fc8f609c2bc3c7c8fa1edb331eee3b527f793736de2f195bbd00f56737cce7f4fdcfa7b1ce07fa3e4e597fcd974d63abe720f5b09fddee676bc6957135b2e6a3723ef28e716dacefc362e435e3c6eab9ecaf5f4dd9ad1a5bbf5b326e4dfe873198befaf7045eddde6733e3d658fcd5cf6efc6e3cbce75e4696f871608c96df52cffad9adffd5d8ee9bae1c59e353dfb7ed287f613cc8eb7b183abbeff965e3e17ea77fefc0b1bf1a59cf43fd7b0b93b2af47567b48bde87b2d5e4f8dad3e7bc96779ef2a27c6c3fb7ef2f799bdd9d0bcf3e0d1930fdca2effcb9bff097fcedea97ccdeecf731fedadff85b7fe7effd837ff44ffed9cffc8b7ff53fbdfbfb31fecdbffb0f3fefbffb05bfe897fc32b715bfead7fcbadff09b7f1de3b758a36dbfe377fd9edf9fb4037fe88ffcf1e731acd5bbffc12b9cf8536b67f67f62bf529ff9fcd718def98d2f78aed257d66adff8d679e71cf098baffe6d0910be31870d175eedc5d8ced92db95bbe65137fd2aee56bedeb97bf76063d03dba27f7ec66637b61a957f793c778f7d6afe3def9eb879b77df6d0cb905b7e896dc32f7ac589bb955b7e6d679cc86db745bdcb7ed76dcaedb73fb124307eed01df1b763f783db893be576e61297bacce53caa70bc5357b9da35ae052f71e580df68407c11e36208e77021ed1c2ee142c678b8e29556e11a6ee016ee64cc3d3cc0233cc1b3e8ff77ed1a7897f002aff013de643fb7f00e1f300fdf610116610996b92df1af056e2bb2ceaa3f853558870dd8842d59671b766017f6601f0edcad7a88edb6ec2a3884231e710c3fe0044ee10c1248758c27c82087024aa8605f6cbdc2dad7d000fb15d915fe941f9d88fc72c0a8ba710a9fe3055efed6aee014aff1a6d70b6fd9a715dec9f77b7c501be0233ee133cef06568708657f88aec537ce338a8f01d3ff8fb3c7ec705b5759f67b8884bb86c6d0557710dd99fb881ec4fdcc26df9be83bb683ef50ef7f1000ff1088fa5fdc0133cc5334c30e5353296eebfe6586089d5900b58fb376cb0250e236ec0cfa655f6fb0a3fc80897e51b5f6db8149d0f31dac7375df82bbaa42bbaa61bba2587c77447f7f4c0d2b7fce5919ee899666e7f92db9cf3f442aff493dee89d3e689edb07fffa4e0bb4484bbcc6fe5f6b48dfdc032dd30aadd21aadd3066dd2166dd30eee61d56bf5f76364dc3e78b88337d8e2f6c6bffcb0c2af31b4fbffb5affffde797ff015a490cc1</data>
+ </image>
+ <image name="image1">
+ <data format="XPM.GZ" length="6079">789c95984973dd380e80eff915aee0969a623fed524dcdc1bb1dafcfbb3d35070092bcefcf6bd7fcf781004889d57d99b09cf4671024b192ea3f7ecc9dec6ecdfdf8e3dbf30c67973cc717f834f7a37eb9bdfdf8f77ffef5e7b7ef713a1767737195cfc5dffff1edfb7436c773dbf7774d07bcf91b840ea068a9695b65e8b8d53f1dc363c713fda3f2abaf72e6d1fce9d7f9148fe6db7a65d42489ceaf3b8e8a38330ed75fe7071cf1fb88b746fb57a3fda3116f7e9d8fd723b9ad97b495af7f393a3f7d9d8fb391fec568fec3c87f34da7f6d24bf19d9375a8f3646fb57a3f9e7233ed4f8a614b7b6fe5bc71572ede753ffc765593595ca355e798d644c49c76954556da4f317345e9433b1fa7b59e54d9919878fd1feedc81ff37afe68924c725d7fe29c1a87513e8566c4f5c87feb23ff68bcb0ad0b9f7f3bca8fbd118fd6c791ffd9fcdd264daef6d1abda5fa5b13186d1fc7b9547321f95357fa324698dc3a7ce6fdabede9211df75dca46decacfb173561abfaf0a4f26c90eb79aa8cfb7cdd56793ec88f9c133f9feac7699935ea6fd0fccc5374e645954f8aa6b6f8ee769c15151a93e64f1e63db92b2da5f569cfafa3fbfe607693ec64de1f9c16a7fc4794585ca757e5ce4ad7150ff71d2441e9f15e5b899b83d9a3f4ce201936b7e3136be7f78517fe48c7e9e255d3f167b4b9d5fba3dad316a7d9419bbbf58f3296a8bb6ae55aef3132ed938a8bf28a9dddfb03fca37ed0755c9e4eb697dc44949adf637d4fe99e59839abfd65ce1e9fa0fd11cbbaf7e79a9fbfb2fac503ad37719fb3f6ebaaad7bff3c2b13b3ebaf5abcab496bfe577fc659cfb86af52be73156fd2cc5d2383cd9fadcd787fab72476ffa3d65795f6f907c1fa53e5f683d6d324a9fc3c68f54e555fafd61f19fdfca0f91ec518b5ea6f38552ed1fd81b573bfbfe513f60cea8fa8418f0759fc339480ebfc1dcb37445b1f7707367f69fdc554f97aacfd21aeabdcd7b378b6e8fd1335bf9389b0ada7f99844d8d87e70a21c63eef16a9c5d8e0bcebd3fce9493cafd89f3c6e8fd01179dfb7ea8fd3fc9c8fdc7da7f459d3cdee0cc763ed6f826286cf5992a53e5e7a76dcbf7caed03bd2fd382dc7ed478a548a59f57f321e53e7fe8deea8bc8fa03eafd9b11f5f6eaf932e90eadde2fa8fd3ecf286eb41e58eff7bc10fb525defca58ee2fb347eb2b2fc55e95b3e65f4e1419c3b5314f5aeb671a0fe946b1c9f1c2ee37c95f3b8fe647deb0db07ecf7a5fb9fb41f48f72ada4ce53abf9002337dd2f50b167bad7f1d38bbff48ed91f7159b7e507f9411f7f1b2fe99c97c7b3f64d60f7a06f55759f4f54d5a0fa5b413bb8f69c7fa6fcfc1fa49ddd7275bbdb61c35165ff07a2decbcc4767fd4516bfd51cf2bef83b2317b75fd8ae5bd60f1d5faab9abaf47c2fb45f65dc583f038d3fe675ecf9a6f52fe9c6f69e60ad17c481f5fec2869bc6fca7fd9426433fd5fd29aa3ddfe079e8bf565f6a2fa59cd7e6bf99719d98bd61ddd9eb1bf53ea4a2ceedbc61c1d9fb1569fe10d6b9e943e18c96afa0ef37aaebdaf60fdacfa89570db796efdfef2f3b2de979cd6a5e5379e193789e7d3b172c6f222535e3596fbcffab1fa838bbaf1781f1837de9f49ef2fae9a3e1e767f721335e6bf45e7be3faaffb916b6f8a8bd2cb7bd9d8ff28eeb495d37562f1bc64decf9b5ebdcf757ed3f75d4cf2793c7e21eb58f2f06d67ac44b637991d8fb4ffba3446be2ef9103e7c2fc4d8fcedeaf58fb419df6f3f97260cb9f35e7be7eb57e6af1a7c9c9e4f9c09fceb1bf0f169d2b7fdfe8fd5f17bd9c34ffba683a6b7ed755cf41fb692d09edfd41df7fb5bc571a7bff1d3b7bfe80e647ddc8792cbefbceadbdf7c2d2c0668fde1fa25c3616ffe3812dfe2bce68f1427426f337a8ffc45bbe1f9273e6fe2b0736fb7a79bf7eee5c391f3ba3d78bd69baceeef492a9cb1b17ebbed5c7bfded19b77d7fb3f76d3cccef996d3e2d3a379e3f7a3f8af7c9f21d5f7bf67ad17a6a52d1b7fb3773eefbabf60ba986c8e3addfaf4dde78bde1ddc0d6dfce8cdbd4ebcdce5ff4f341dff35d74fcfc7a7f8ab7da56bfc441f3a3b3cefbbdad8f62bfc9f5fbabb3c6f77f3716b9d97fe4ecf76d581dd8fca7fd4cacf5fb104f9dfdfe0374f6fa055baf96f9b6fead737f5f9e387bbf0afafe91d3bb3eeaf7b29cd6e5b8ec9c7a7cec7b6bd233e8fd27bb6576ffe0d4b97f9f693dc8eeb9cbd381ad3eb5dfc96eceb4e25c993f40eb5b762b7cbec65b762bbd7f6f3b57fefeb0ef2f59cdbfaf169c2baf3fcddf6e359f1f3bbb1c5e9cfbefb3d781359fc0fe7f4239b0d64fa7ed7ce1ecef25d0fba493ba3d97cedeffc28a73ff3ed3fce966bb3c1bd8f253fb6747c6211fd8fa8fd64f27f5fbecc4d9df6b41f347bf4f6dfef8fbf5ccb97f8f5a3c87efe1e9ac1f0102060a1c6a194d68c379b80897f2bbab5f73a6b3df75c275b809b7e12edc8787f0189ec273988597f01ade02fcbd4e780f1fe133cc8785b01896c2725891b11ad6c27af81936c2e65f75c2969c683bec845d993d1d8dbdb01f0ec2e1571d39d54738921d8ec34938959feeef331927c3988428c4bf74c4f29b90c85a69c8421e8a50860a0200a050d60f2060a8071d84065a38870bb8949f2bb8168d1bb80d677027fc6bdcc3033cba0ec1133cc30c5ee015dee05d34027cc027cc0b2ffc36166109965d87610556614d7ebb0e3f61433436c38968dcc196acf3227f5fc8cfb6ccd8815d986a0eecc13e1cc0211cc1319c88c6299cc144568820860452f937835c7e730805946075230621c21a1272772e7950491394a2391f468b17b2eb1a5ee2155eabce0ddee29d7cdcdd8be5e1ef073ee0231ce2133ea3d9738b2ff88a6ff88e1f2affc479190bc398c7455cc2475cc6155cc535dd671d7fe2066ee2166ee38ee8ece2b4f3013e5a64e4df3ce490e11eeee381e904c6433cc2633cc1533cc38968453e3bee7c8c09a622c930c7024b3b1b562421222492dddf49fd4035e4985223bffd7db4746e3ea00bbaa42bbaa61bcce996eee85e741ee811b6e8899e7f1b337aa157f3755767f446eff4419f344f0bb4484ba2b54c2bb44a6bf2db7eacd34fdab09806a04ddaa26ddaa15d914c698ff6e9800ee9888ee9447e67e394ce6842515f0b1487774a28a58c72d12a2412b17cecad524995fc46064b82c9db96fa1cedf29b395cb13c38a5659dcb8c0bbee42b593be76b19377ccb777ccf0f301dd5b6d43c3ff2133ff38c5ff895df64bcca7fbdf3077ff2bcec31fd6b0fe9063cf2022ff2122ff30aaff21aaff34fdea00d8aba53fdbd8eea4de543e81a67b8266386d750f53bfcd2e1cdff6f7cffef3fbffd0fd1b4fa7d</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>toolButton_add</sender>
+ <signal>clicked()</signal>
+ <receiver>FX_Setup</receiver>
+ <slot>slotAdd()</slot>
+ </connection>
+ <connection>
+ <sender>toolButton_remove</sender>
+ <signal>clicked()</signal>
+ <receiver>FX_Setup</receiver>
+ <slot>slotRemove()</slot>
+ </connection>
+ <connection>
+ <sender>pushButton_removeAll</sender>
+ <signal>clicked()</signal>
+ <receiver>FX_Setup</receiver>
+ <slot>slotRemoveAll()</slot>
+ </connection>
+ <connection>
+ <sender>listBox_Active</sender>
+ <signal>doubleClicked(QListBoxItem*)</signal>
+ <receiver>FX_Setup</receiver>
+ <slot>slotConfigureEffect(QListBoxItem*)</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>slotAdd()</slot>
+ <slot>slotRemove()</slot>
+ <slot>slotRemoveAll()</slot>
+ <slot>slotConfigureEffect(QListBoxItem*)</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/ksayit/src/fxpluginhandler.cpp b/ksayit/src/fxpluginhandler.cpp
new file mode 100644
index 0000000..8e6f68d
--- /dev/null
+++ b/ksayit/src/fxpluginhandler.cpp
@@ -0,0 +1,239 @@
+//
+// C++ Implementation: fxpluginhandler
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// QT includes
+#include <qdir.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <kapplication.h>
+#include <ktrader.h>
+#include <klibloader.h>
+#include <kservice.h>
+
+// App specific includes
+#include "fxpluginhandler.h"
+#include "ksayit_fxplugin.h"
+#include "ksayit_ttsplugin.h"
+
+
+FXPluginHandler::FXPluginHandler(QObject *parent, const char *name, KConfig *config)
+ : QObject(parent, name), m_config(config)
+{
+ m_mapPluginList.clear();
+ m_lstActivePlugins.clear();
+}
+
+
+FXPluginHandler::~FXPluginHandler()
+{
+ QMap<QString, fx_struct>::Iterator mit;
+
+ for (mit=m_mapPluginList.begin(); mit!=m_mapPluginList.end(); ++mit){
+ if ( (*mit).p != 0 ){
+ delete (*mit).p;
+ }
+ }
+}
+
+
+void FXPluginHandler::searchPlugins()
+{
+ kdDebug(100200) << "FXPluginHandler::searchPlugins()" << endl;
+
+ QStringList sRegistered;
+ fx_struct plugin;
+
+ sRegistered.clear();
+ m_mapPluginList.clear();
+
+ KTrader::OfferList offers = KTrader::self()->query("KSayIt/FXPlugin");
+ KLibFactory *factory = NULL;
+ QString library = QString::null;
+ QString name = QString::null;
+
+ KTrader::OfferList::Iterator it=offers.begin();
+ for ( ;it!=offers.end(); ++it ){
+ KService::Ptr ptr = (*it);
+ library = ptr->library();
+ name = ptr->name();
+ factory = KLibLoader::self()->factory( library.latin1() );
+ if ( factory ){
+ kdDebug(100200) << "FXPluginHandler::searchPlugins(): Plugin factory found." << endl;
+ // register found plugin
+ if ( !sRegistered.contains( QString(name) )){
+ sRegistered.append( QString(name) );
+ plugin.name = name;
+ plugin.library = library;
+ plugin.description = QString::null;
+ plugin.EffectID = 0;
+ plugin.p = NULL;
+ m_mapPluginList[plugin.name] = plugin; // update Plugin Map
+ kdDebug(100200) << "FXPluginHandler::searchPlugins(): " << plugin.name << " registered." << endl;
+ }
+ }
+ }
+}
+
+
+void FXPluginHandler::readConfiguration()
+{
+ kdDebug(100200) << "+++ entering FXPluginHandler::readConfiguration()" << endl;
+
+ fx_struct plugin;
+ QMap<QString, fx_struct>::Iterator mit;
+ QStringList::Iterator lit;
+
+ // unload all plugins and destroy the effect objects
+ lit = m_lstActivePlugins.begin();
+ while ( lit != m_lstActivePlugins.end() ){
+ mit = m_mapPluginList.find( *lit );
+ if ( mit!=m_mapPluginList.end() ){
+ plugin = *mit;
+ if ( (plugin.p != NULL) && (plugin.EffectID == 0) ){
+ delete plugin.p;
+ plugin.p = NULL;
+ m_mapPluginList[plugin.name] = plugin; // update Plugin Map
+ lit = m_lstActivePlugins.remove( lit );
+ } else {
+ lit++;
+ }
+ }
+ }
+
+ // load active plugins as given in config file
+ m_config->setGroup("Effect Stack Configuration");
+ QStringList conf_active = m_config->readListEntry("Activated");
+ KLibFactory *factory = NULL;
+
+ for (lit=conf_active.begin(); lit!=conf_active.end(); ++lit){ // for all in config
+ mit = m_mapPluginList.find(*lit);
+ if( mit!=m_mapPluginList.end() ){
+ // plugin found in list of registered plugins
+ plugin = *mit;
+ // load plugin
+ factory = KLibLoader::self()->factory( (plugin.library).latin1() );
+ if ( factory ){
+ plugin.p = static_cast<FXPlugin*>( factory->create( (QObject*)this, (plugin.name).latin1() ) );
+ if ( plugin.p ){ // Plugin found
+ plugin.p->setApplication( KApplication::kApplication() );
+ plugin.description = plugin.p->getDescription_KS();
+ // append to list of active plugins
+ m_lstActivePlugins.append( plugin.name );
+ m_mapPluginList[plugin.name] = plugin; // update Plugin Map
+ kdDebug(100200) << "FXPluginHandler: FX-Plugin " << plugin.name << " active." << endl;
+ }
+ }
+ }
+ }
+}
+
+
+void FXPluginHandler::showEffectGUI(const QString &pname)
+{
+ kdDebug(100200) << "FXPluginHandler::showEffectGUI(): " << pname << endl;
+
+ QMap<QString, fx_struct>::Iterator mit;
+ fx_struct plugin;
+
+ // find plugin with name==pname in list and show its GUI
+ mit = m_mapPluginList.find(pname);
+ if ( mit != m_mapPluginList.end() ){
+ plugin = *mit;
+ if ( plugin.p != NULL ){ // plugin loaded
+ plugin.p->showGUI_KS();
+ return;
+ } else {
+ kdDebug(100200) << "Effect not active yet. Loading..." << endl;
+ KLibFactory *factory = KLibLoader::self()->factory( (plugin.library).latin1() );
+ if ( factory ){
+ plugin.p = static_cast<FXPlugin*>( factory->create( (QObject*)this, (plugin.name).latin1() ) );
+ if ( plugin.p ){ // Plugin found
+ plugin.p->setApplication( KApplication::kApplication() );
+ plugin.description = plugin.p->getDescription_KS();
+ // append to list of active plugins
+ m_lstActivePlugins.append( plugin.name );
+ m_mapPluginList[plugin.name] = plugin; // update Plugin Map
+ kdDebug(100200) << "FXPluginHandler: FX-Plugin " << plugin.name << " active." << endl;
+ plugin.p->showGUI_KS();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+
+void FXPluginHandler::getPlugins(QStringList &pluginlist)
+{
+ // kdDebug(100200) << "FXPluginHandler::getPlugins" << endl;
+
+ pluginlist.clear();
+ QString sPname;
+
+ QMap<QString, fx_struct>::Iterator mit;
+ for (mit=m_mapPluginList.begin(); mit!=m_mapPluginList.end(); ++mit){
+ sPname = (*mit).name; //testing
+ pluginlist.append( sPname );
+ }
+}
+
+
+void FXPluginHandler::activateEffect(const QString &pname,
+ KArtsServer *server,
+ StereoEffectStack *fx_stack)
+{
+ kdDebug(100200) << "FXPluginHandler::activateEffect: " << pname << endl;
+
+ QMap<QString, fx_struct>::Iterator mit;
+ fx_struct plugin;
+
+ // find plugin with name==pname
+ mit = m_mapPluginList.find(pname);
+ if ( mit!=m_mapPluginList.end() ){
+ plugin = *mit;
+ if ( plugin.p != NULL ){
+ plugin.EffectID = plugin.p->activate_KS(server, fx_stack);
+ m_mapPluginList[plugin.name] = plugin; // update Plugin Map
+ } else {
+ kdDebug(100200) << "Effect " << pname << " not found or inactive." << endl;
+ }
+ }
+}
+
+
+void FXPluginHandler::deactivateEffects(StereoEffectStack *fx_stack)
+{
+ kdDebug(100200) << "FXPluginHandler::deactivateEffects." << endl;
+
+ QMap<QString, fx_struct>::Iterator mit;
+ fx_struct plugin;
+
+ for (mit=m_mapPluginList.begin(); mit!=m_mapPluginList.end(); ++mit){
+ if ( mit != m_mapPluginList.end() ){
+ plugin = *mit;
+ if ( (plugin.EffectID != 0) && (plugin.p != NULL) ){
+ // effect active and on stack
+ plugin.p->deactivate_KS(fx_stack, plugin.EffectID);
+ kdDebug(100200) << plugin.name << " with Effect ID " << plugin.EffectID << " removed." << endl;
+ plugin.EffectID = 0;
+ m_mapPluginList[plugin.name] = plugin; // update Plugin Map
+ }
+ }
+ }
+}
+
+
+
+
+
+#include "fxpluginhandler.moc"
diff --git a/ksayit/src/fxpluginhandler.h b/ksayit/src/fxpluginhandler.h
new file mode 100644
index 0000000..1a3d54a
--- /dev/null
+++ b/ksayit/src/fxpluginhandler.h
@@ -0,0 +1,99 @@
+//
+// C++ Interface: fxpluginhandler
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef FXPLUGINHANDLER_H
+#define FXPLUGINHANDLER_H
+
+// QT includes
+#include <qobject.h>
+#include <qlibrary.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qmap.h>
+// #include <qvaluelist.h>
+
+// KDE includes
+#include <kconfig.h>
+#include <arts/kartsserver.h>
+#include <arts/artsflow.h>
+
+using namespace Arts;
+
+// App specific includes
+#include "ksayit_fxplugin.h"
+
+/**
+@author Robert Vogl
+*/
+/** Internal structure of the effect plugin
+ */
+typedef struct {
+ QString name; // KService::Ptr->name()
+ QString library; // KService::Ptr->library()
+ QString description;
+ long EffectID; // !=0, if effect is on the effect stack.
+ FXPlugin *p; // factory->create(...)
+} fx_struct;
+
+
+class FXPluginHandler : public QObject
+{
+Q_OBJECT
+public:
+ FXPluginHandler(QObject *parent = 0, const char *name = 0, KConfig *config=0);
+ ~FXPluginHandler();
+
+public: // Methods
+ /** Loads the activated plugins.
+ */
+ void readConfiguration();
+
+ /** Loads any available plugin from the directories containing KSayIt plugins,
+ * fills the plugin_struct with the corresponding data and unloads the plugin.
+ */
+ void searchPlugins();
+
+ /** Shows the GUI to setup the effect named name
+ \param pname The name of the effect to configure.
+ */
+ void showEffectGUI(const QString &pname);
+
+ /** Activates the named effect
+ \param pname Name of the effect to activate.
+ \param server A pointer to the soundserver instance.
+ \param fx_stack A pointer to the effect stack of the soundserver.
+ */
+ void activateEffect(const QString &pname,
+ KArtsServer *server,
+ StereoEffectStack *fx_stack);
+
+ /** Removes all effects from the soundservers effect stack.
+ \param fx_stack A pointer to the effect stack of the soundserver.
+ */
+ void deactivateEffects(StereoEffectStack *fx_stack);
+
+ /** Returns a list of all available plugins.
+ \param pluginlist A reference to a QStringList that contains the available plugins.
+ */
+ void getPlugins(QStringList &pluginlist);
+
+private: // Attributes
+ KConfig *m_config;
+ QMap<QString, fx_struct> m_mapPluginList; // holds all plugins found on the system
+ // QMap<QString, fx_struct> m_mapActivePlugins; // holds the active effects
+ QStringList m_lstActivePlugins;
+
+
+};
+
+
+
+#endif
diff --git a/ksayit/src/fxsetupimpl.cpp b/ksayit/src/fxsetupimpl.cpp
new file mode 100644
index 0000000..cb85080
--- /dev/null
+++ b/ksayit/src/fxsetupimpl.cpp
@@ -0,0 +1,159 @@
+/***************************************************************************
+ fxsetupimpl.cpp - description
+ -------------------
+ begin : Mo Nov 24 2003
+ copyright : (C) 2003 by voglrobe
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// QT includes
+#include <qstringlist.h>
+#include <qpushbutton.h>
+
+// KDE includes
+#include <kdebug.h>
+
+// App specific inlcudes
+#include "fxsetupimpl.h"
+// #include "freeverbsetupimpl.h"
+#include "fxpluginhandler.h"
+
+FX_SetupImpl::FX_SetupImpl(QWidget *parent, const char *name,
+ KConfig *config,
+ FXPluginHandler *fxpluginhandler )
+ : FX_Setup(parent,name), m_config(config), m_fxpluginhandler(fxpluginhandler)
+{
+ m_fxpluginhandler->getPlugins(pluginlist);
+
+ Init(pluginlist);
+}
+
+
+FX_SetupImpl::~FX_SetupImpl()
+{
+}
+
+void FX_SetupImpl::slotAdd()
+{
+ // move effect from Available-List to Active-List
+ int index = listBox_Available->currentItem();
+ if ( index == -1 )
+ return;
+ listBox_Active ->insertItem( listBox_Available->text(index), -1 );
+ listBox_Available->removeItem( index );
+ pushButton_removeAll->setEnabled(true);
+}
+
+
+void FX_SetupImpl::slotRemove()
+{
+ // move effect from Active-List to Available-List
+ int index = listBox_Active->currentItem();
+ if ( index == -1 )
+ return;
+ listBox_Available->insertItem( listBox_Active->text(index), -1 );
+ listBox_Active ->removeItem( index );
+
+ if (listBox_Active->count() == 0)
+ pushButton_removeAll->setEnabled(false);
+}
+
+
+void FX_SetupImpl::slotRemoveAll()
+{
+ kdDebug() << "FX_SetupImpl::slotRemoveAll()" << endl;
+
+ // move all from Active-List to Available-List
+ for(uint i=0; i<listBox_Active->count(); i++){
+ listBox_Available->insertItem( listBox_Active->text((int)i) );
+ }
+ listBox_Active->clear();
+ pushButton_removeAll->setEnabled(false);
+}
+
+
+void FX_SetupImpl::slotReload()
+{
+ kdDebug() << "FX_SetupImpl::slotReload()" << endl;
+
+ Init(pluginlist);
+}
+
+
+void FX_SetupImpl::slotConfigureEffect(QListBoxItem *item)
+{
+ m_fxpluginhandler->showEffectGUI(item->text());
+}
+
+
+void FX_SetupImpl::Init(QStringList c_avail)
+{
+ m_config->setGroup("Effect Stack Configuration");
+ QStringList conf_active = m_config->readListEntry("Activated");
+ QStringList c_active;
+ QStringList::Iterator sit, it;
+
+ listBox_Available->clear();
+ listBox_Active->clear();
+ c_active.clear();
+
+ pushButton_removeAll->setEnabled(false);
+
+ for (sit=conf_active.begin(); sit!=conf_active.end(); ++sit){
+ it = c_avail.find(*sit);
+ if ( it!=c_avail.end() ){ // active plugin as per config-file in pluginlist found
+ c_active.append(*sit); // append to active list
+ c_avail.remove(*sit); // remove active plugin from the list of avail plugins
+ }
+ }
+
+ if ( !c_active.isEmpty() ){
+ pushButton_removeAll->setEnabled(true);
+ }
+
+ // Fill ListBoxes
+ for(it=c_avail.begin(); it!=c_avail.end(); ++it){
+ listBox_Available->insertItem( (*it), -1 );
+ }
+ for(it=c_active.begin(); it!=c_active.end(); ++it){
+ listBox_Active->insertItem( (*it), -1 );
+ }
+}
+
+
+void FX_SetupImpl::slotSaveWasClicked()
+{
+ m_config->setGroup("Effect Stack Configuration");
+
+ // Read ListBox Available FX
+ QStringList slist;
+ for(uint i=0; i<listBox_Available->count(); i++){
+ slist.append( listBox_Available->text( (int)i) );
+ }
+ // Write StringList
+ m_config->writeEntry("Available", slist);
+
+ // Read ListBox Activated FX
+ slist.clear();
+ QString t;
+ for(uint i=0; i<listBox_Active->count(); i++){
+ t = listBox_Active->text( (int)i );
+ slist.append( t );
+ }
+ // Write StringList
+ m_config->writeEntry("Activated", slist);
+ m_config->sync();
+ slist.clear();
+}
+
+
+#include "fxsetupimpl.moc"
diff --git a/ksayit/src/fxsetupimpl.h b/ksayit/src/fxsetupimpl.h
new file mode 100644
index 0000000..403631d
--- /dev/null
+++ b/ksayit/src/fxsetupimpl.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ fxsetupimpl.h - description
+ -------------------
+ begin : Mo Nov 24 2003
+ copyright : (C) 2003 by voglrobe
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef FXSETUPIMPL_H
+#define FXSETUPIMPL_H
+
+// QT includes
+#include <qwidget.h>
+#include <qlistbox.h>
+
+
+// KDE includes
+#include <kconfig.h>
+
+// App specific includes
+#include "fx_setup.h"
+
+// forward declaration
+class FXPluginHandler;
+
+/**
+ *@author voglrobe
+ */
+class FX_SetupImpl : public FX_Setup {
+ Q_OBJECT
+
+public:
+ FX_SetupImpl(QWidget *parent=0, const char *name=0,
+ KConfig *config=0,
+ FXPluginHandler *fxpluginhandler=0);
+ ~FX_SetupImpl();
+
+public slots:
+ /** Adds an effect to the list of active effects.
+ */
+ void slotAdd();
+
+ /** Removes an effect from the list of active effects.
+ */
+ void slotRemove();
+
+ /** Removes all effects from the list of active effects.
+ */
+ void slotRemoveAll();
+
+ /** Recovers last saved state.
+ */
+ void slotReload();
+
+ /** Called by a double click on an effect in the list of active effects.
+ Opens a modal dialog to configure the efffect.
+ \param item The double clicked item.
+ */
+ void slotConfigureEffect(QListBoxItem *item);
+
+ /** Saves the configuration
+ */
+ void slotSaveWasClicked();
+
+private: // Methods
+ /** Loads the configuration and initializes the widget.
+ \param c_avail List of available plugins.
+ */
+ void Init(QStringList c_avail);
+
+private:
+ KConfig *m_config;
+ FXPluginHandler *m_fxpluginhandler;
+ QStringList pluginlist;
+
+};
+
+
+
+#endif
+
diff --git a/ksayit/src/hi16-app-ksayit.png b/ksayit/src/hi16-app-ksayit.png
new file mode 100644
index 0000000..fcd7183
--- /dev/null
+++ b/ksayit/src/hi16-app-ksayit.png
Binary files differ
diff --git a/ksayit/src/hi32-app-ksayit.png b/ksayit/src/hi32-app-ksayit.png
new file mode 100644
index 0000000..8bee3ef
--- /dev/null
+++ b/ksayit/src/hi32-app-ksayit.png
Binary files differ
diff --git a/ksayit/src/hi32-app-ksayit_clipempty.png b/ksayit/src/hi32-app-ksayit_clipempty.png
new file mode 100644
index 0000000..6992a16
--- /dev/null
+++ b/ksayit/src/hi32-app-ksayit_clipempty.png
Binary files differ
diff --git a/ksayit/src/hi32-app-ksayit_talking.png b/ksayit/src/hi32-app-ksayit_talking.png
new file mode 100644
index 0000000..44717e6
--- /dev/null
+++ b/ksayit/src/hi32-app-ksayit_talking.png
Binary files differ
diff --git a/ksayit/src/ksayit.cpp b/ksayit/src/ksayit.cpp
new file mode 100644
index 0000000..131db8c
--- /dev/null
+++ b/ksayit/src/ksayit.cpp
@@ -0,0 +1,908 @@
+/***************************************************************************
+ ksayit.cpp - description
+ -------------------
+ begin : Son Aug 10 13:26:57 EDT 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include <stdlib.h> // getenv, system
+
+// include files for QT
+#include <qdir.h>
+#include <qapplication.h>
+#include <qdockwindow.h>
+#include <qfileinfo.h>
+#include <qfile.h>
+
+// include files for KDE
+#include <klocale.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kdialogbase.h>
+#include <kfiledialog.h>
+#include <kmenubar.h>
+#include <kpopupmenu.h>
+#include <kstatusbar.h>
+#include <kconfig.h>
+#include <kstdaction.h>
+#include <kedittoolbar.h>
+#include <kkeydialog.h>
+#include <kurl.h>
+#include <kstandarddirs.h>
+
+// application specific includes
+#include "ksayit.h"
+#include "ksayitviewimpl.h"
+#include "voicesetupdlg.h"
+#include "ksayitsystemtray.h"
+#include "effectstack.h"
+#include "fxpluginhandler.h"
+#include "kttsdlib.h"
+#include "doctreeviewimpl.h"
+#include "ksayitbookmarkhandler.h"
+
+// #define KSAYITUI "/home/voglrobe/Projekte/ksayit/ksayit/ksayitui.rc"
+#define KSAYITUI "ksayitui.rc"
+#define ID_STATUS_MSG 1
+
+KSayItApp::KSayItApp(QWidget* parent, const char* name, WFlags f,
+ const QCString &objID)
+ : KMainWindow(parent, name, f), DCOPObject(objID)
+{
+ config = NULL;
+ view = NULL;
+ tray = NULL;
+ es = NULL;
+ treeview = NULL;
+ bkManager = NULL;
+ bkHandler = NULL;
+ bkMenu = NULL;
+ m_currentBookmarkFile = QString::null;
+
+ config=kapp->config();
+ m_kttslib = new KTTSDLib(this, "KTTSD-Library", kapp);
+
+ initView();
+ initStatusBar();
+ initActions();
+ initBookmarkManager( i18n("Untitled") );
+
+ createGUI(KSAYITUI);
+ setAutoSaveSettings("MainWindow");
+
+ readOptions();
+
+ // connect TTS plugin handler to this object
+ connect(m_kttslib, SIGNAL(signalFinished()),
+ this, SLOT(slotTTSFinished()) );
+
+ // only used if library thinks it has to call the preferences dialog.
+ // e.g. when it detects a bad configuration.
+ connect(m_kttslib, SIGNAL(signalCallPreferences()),
+ this, SLOT(slotPreferences()) );
+
+ // init Clipboard
+ cb = QApplication::clipboard();
+ connect(cb, SIGNAL(dataChanged()), this, SLOT(slotClipboardChanged()) );
+
+ // create SystemTray object
+ tray = new KSayItSystemTray(this, "system_tray");
+ connect(tray, SIGNAL(signalCallPreferences()), this, SLOT(slotPreferences()) );
+ connect(tray, SIGNAL(signalSayActivated()), this, SLOT(slotSayText()) );
+ connect(tray, SIGNAL(signalSayClipboard()), this, SLOT(slotSayClipboard()) );
+ connect(tray, SIGNAL(signalShutUpActivated()), this, SLOT(slotStopActivated()) );
+ connect(tray, SIGNAL(signalPauseActivated()), this, SLOT(slotPauseActivated()) );
+ connect(tray, SIGNAL(signalNextActivated()), this, SLOT(slotNextSentenceActivated()) );
+ connect(tray, SIGNAL(signalPrevActivated()), this, SLOT(slotPrevSentenceActivated()) );
+ tray->show();
+ tray->setEnabled(true);
+
+ // create the FX plugin handler
+ m_fxpluginhandler = new FXPluginHandler(this, "fxpluginhandler", config);
+ m_fxpluginhandler->searchPlugins();
+
+ // create object for effectstack
+ es = new EffectStack(m_fxpluginhandler, config);
+
+ // emit signalConfigChanged();
+ m_kttslib->reloadConfiguration();
+ m_fxpluginhandler ->readConfiguration();
+
+ // init docview
+ // treeview->clear();
+ // treeview->createEmptyDocument();
+ slotClear();
+}
+
+KSayItApp::~KSayItApp()
+{
+ // delete kapp->mainWidget();
+ delete m_kttslib;
+ delete tray;
+ delete m_fxpluginhandler;
+ delete es;
+ delete view;
+ if (bkHandler)
+ delete bkHandler;
+ if (bkMenu)
+ delete bkMenu;
+}
+
+void KSayItApp::initActions()
+{
+ // Standard-Actions
+ open = KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
+ save = KStdAction::save(this, SLOT(slotFileSave()), actionCollection());
+ saveAs = KStdAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
+ KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
+ KStdAction::close(this, SLOT(slotCloseMainWindow()), actionCollection());
+ cut = KStdAction::cut(view, SLOT(slotCut()), actionCollection());
+ copy = KStdAction::copy(view, SLOT(slotCopy()), actionCollection());
+ paste = KStdAction::paste(view, SLOT(slotPaste()), actionCollection());
+ preferences = KStdAction::preferences(this, SLOT(slotPreferences()), actionCollection());
+ KStdAction::keyBindings(this, SLOT(slotEditKeys()), actionCollection());
+ KStdAction::configureToolbars(this, SLOT(slotConfigureToolbar()), actionCollection());
+ KStdAction::showToolbar("mainToolBar", actionCollection());
+ statusBarAction = KStdAction::showStatusbar(this, SLOT(slotToggleStatusBar()), actionCollection());
+
+ // User defined actions
+ say = new KAction (i18n("Say"),
+ Qt::Key_F9,
+ this, SLOT (slotSayText()),
+ actionCollection(),
+ "say_it");
+
+ pause = new KAction (i18n("Pause"),
+ Qt::Key_Pause,
+ this, SLOT (slotPauseActivated()),
+ actionCollection(),
+ "pause");
+
+ shutup = new KAction (i18n("Shut Up"),
+ Qt::Key_F10,
+ this, SLOT (slotStopActivated()),
+ actionCollection(),
+ "shut_up");
+
+ next_sentence = new KAction (i18n("Next Sentence"),
+ Qt::Key_Next,
+ this, SLOT (slotNextSentenceActivated()),
+ actionCollection(),
+ "next_sentence");
+
+
+ prev_sentence = new KAction (i18n("Previous Sentence"),
+ Qt::Key_Prior,
+ this, SLOT(slotPrevSentenceActivated()),
+ actionCollection(),
+ "prev_sentence");
+
+ clear = new KAction (i18n("Clear"),
+ Qt::Key_F12,
+ this, SLOT(slotClear()),
+ actionCollection(),
+ "clear");
+
+ edit = new KToggleAction( i18n("Edit Text"),
+ 0,
+ this, SLOT(slotEditToggled()),
+ actionCollection(),
+ "edittext");
+
+ bookmarkmenu = new KActionMenu( i18n("Bookmarks"),
+ "bookmark", // icon
+ actionCollection(),
+ "bookmarks"); // name
+ bookmarkmenu->setDelayed(false);
+
+ // default disable/enable
+ save ->setEnabled(false);
+ saveAs ->setEnabled(false);
+ copy ->setEnabled(false);
+ cut ->setEnabled(false);
+ paste ->setEnabled(false);
+ say ->setEnabled(false);
+ pause ->setEnabled(false);
+ shutup ->setEnabled(false);
+ next_sentence->setEnabled(false);
+ prev_sentence->setEnabled(false);
+ preferences ->setEnabled(true);
+ edit ->setChecked(false);
+ bookmarkmenu ->setEnabled(false);
+ m_ap_saying = false;
+ m_ap_paused = false;
+ m_textview_empty = true;
+}
+
+
+void KSayItApp::initBookmarkManager(const QString &filename)
+{
+ QString bkFile = getBookmarkDir( filename );
+ if ( bkFile.isNull() )
+ return;
+
+ m_currentBookmarkFile = bkFile;
+ bkManager = KBookmarkManager::managerForFile( bkFile, false );
+
+ // create BookmarkHandler object
+ if ( bkHandler )
+ delete bkHandler;
+ bkHandler = new KSayItBookmarkHandler(bkManager, this);
+
+ // create Bookmarkmenu
+ KPopupMenu *bkPopupMenu = bookmarkmenu->popupMenu();
+ if ( bkMenu )
+ delete bkMenu;
+ bkMenu = new KBookmarkMenu(bkManager, bkHandler, bkPopupMenu, 0, true );
+}
+
+
+void KSayItApp::slotNotifyBookmarkHandler(const QString &ID, const QString &title)
+{
+ if ( bkHandler )
+ bkHandler->notifyBookmarkHandler(ID, title);
+}
+
+
+void KSayItApp::slotDeleteBookmark(const QString &url, const QString &title)
+{
+ kdDebug(100200) << "KSayItApp::slotDeleteBookmark(" << url << ")" << endl;
+ if ( bkHandler )
+ bkHandler->deleteBookmark( url, title );
+}
+
+
+QString KSayItApp::getBookmarkDir(const QString &filename)
+{
+ QString bkRelPath = "ksayit/ksayit_bookmarks/" + filename + ".bookmarks";
+ QString bkFile;
+ bkFile = locateLocal("data", bkRelPath);
+ return bkFile;
+}
+
+
+void KSayItApp::slotSetBookmarkFilename(const QString &newname)
+{
+ kdDebug(100200) << "KSayItApp::slotSetBookmarkFilename(" << newname << ")" << endl;
+
+ initBookmarkManager(newname);
+}
+
+
+void KSayItApp::slotChangeBookmarkFilename(const QString &newname)
+{
+ kdDebug(100200) << "KSayItApp::slotChangeBookmarkFilename(" << newname << ")" << endl;
+
+ if ( m_currentBookmarkFile.isNull() )
+ return;
+
+ QString newbkFile = getBookmarkDir(newname);
+ if ( newbkFile.isNull() )
+ return;
+
+ // copy old bookmarkfile to new file
+ if ( m_currentBookmarkFile != newbkFile ){
+ if ( QFile::exists(m_currentBookmarkFile) ){
+ QString command = QString("cp %1 %2").arg(m_currentBookmarkFile).arg(newbkFile);
+ system( command.ascii() );
+ }
+ // install new BookmarkHandler based on the new file
+ initBookmarkManager(newname);
+ }
+}
+
+
+QString KSayItApp::setItemByBookmark( const QString &ID, const QString &title )
+{
+ QString result;
+ result = treeview->selectItemByID( ID, title );
+ return result;
+}
+
+
+void KSayItApp::initStatusBar()
+{
+ // STATUSBAR
+ statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG, 1);
+ statusBar()->setItemAlignment(ID_STATUS_MSG, Qt::AlignLeft);
+}
+
+
+void KSayItApp::initView()
+{
+ // create the main widget
+ view = new KSayItViewImpl(this);
+ view->setMinimumSize(view->sizeHint());
+ setCentralWidget(view);
+ // connections
+ connect( view, SIGNAL(signalEnableCopyCut(bool)),
+ this, SLOT(slotEnableCopyCut(bool)));
+ connect( view, SIGNAL(signalShowStatus(const QString &)),
+ this, SLOT(slotStatusMsg(const QString &)));
+ connect( view, SIGNAL(signalSetCaption(const QString &)),
+ this, SLOT(slotSetCaption(const QString &)));
+ connect( view, SIGNAL(signalTextChanged(bool)),
+ this, SLOT(slotTextChanged(bool)) );
+
+ // DockWindow
+ QDockWindow *docview = new QDockWindow(QDockWindow::InDock, this, "docview");
+ treeview = new DocTreeViewImpl(docview, "treeview");
+ treeview->enableContextMenus( true );
+ // treeview->clear();
+ docview->setWidget(treeview);
+ docview->setResizeEnabled(true);
+ this->setDockEnabled(docview, Qt::DockTop, false);
+ this->setDockEnabled(docview, Qt::DockBottom, false);
+ this->moveDockWindow(docview, Qt::DockLeft);
+ connect( treeview, SIGNAL(signalContentChanged(const QString&)),
+ this, SLOT(slotTreeViewChanged(const QString&)) );
+ connect( treeview, SIGNAL(signalSetText(const QString&)),
+ this, SLOT(slotSetText(const QString&)) );
+ connect( treeview, SIGNAL(signalAllNodesProcessed()),
+ this, SLOT(slotSayNode()) );
+ connect( treeview, SIGNAL(signalEnableTextedit(bool)),
+ this, SLOT(slotEnableTextedit(bool)) );
+ connect( treeview, SIGNAL(signalNotifyBookmarkManager(const QString&, const QString&)),
+ this, SLOT(slotNotifyBookmarkHandler(const QString&, const QString&)) );
+ connect( treeview, SIGNAL(signalSetBookmarkFilename(const QString&)),
+ this, SLOT(slotSetBookmarkFilename(const QString&)) );
+ connect( treeview, SIGNAL(signalChangeBookmarkFilename(const QString&)),
+ this, SLOT(slotChangeBookmarkFilename(const QString&)) );
+ connect( treeview, SIGNAL(signalDeleteBookmark(const QString&, const QString&)),
+ this, SLOT(slotDeleteBookmark(const QString&, const QString&)) );
+}
+
+
+void KSayItApp::readOptions()
+{
+ applyMainWindowSettings( config, "MainWindow" );
+ statusBarAction->setChecked(!statusBar()->isHidden());
+}
+
+void KSayItApp::closeEvent(QCloseEvent *ce)
+{
+ ce->ignore();
+ if ( !this->isVisible() ){
+ slotFileQuit();
+ } else {
+ this->hide();
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// DCOP FUNCTIONS
+/////////////////////////////////////////////////////////////////////
+
+ASYNC KSayItApp::dcopSayText(QString msg)
+{
+ slotSetText( msg );
+ sayActivated();
+}
+
+ASYNC KSayItApp::dcopStop()
+{
+ slotStopActivated();
+}
+
+
+ASYNC KSayItApp::dcopSayXmlFile(KURL url)
+{
+ slotStatusMsg(i18n("Say XML file..."));
+ m_enableChangeNotifications = false;
+
+ try{
+ if ( !url.isEmpty() ){
+ resetView();
+ treeview->openFile( url );
+ setActions(ACTIONS::PLAY | ACTIONS::FFWD);
+ save ->setEnabled(false);
+ saveAs->setEnabled(true);
+ edit->setChecked(false);
+ treeview->setEditMode( false );
+ }
+ }
+ catch( QString err ){
+ KMessageBox::error(this, err);
+ save ->setEnabled(false);
+ saveAs->setEnabled(true);
+ }
+
+ m_enableChangeNotifications = true;
+
+ slotSayText();
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// SLOT IMPLEMENTATION
+/////////////////////////////////////////////////////////////////////
+
+void KSayItApp::slotEditToggled()
+{
+ if ( edit->isChecked() ){
+ treeview->setEditMode( true );
+ slotStatusMsg(i18n("Edit Mode ON."));
+ } else {
+ treeview->setEditMode( false );
+ slotStatusMsg(i18n("Edit Mode OFF."));
+ }
+}
+
+
+void KSayItApp::slotSaveOptions()
+{
+ saveMainWindowSettings( config, "MainWindow" );
+ config->sync();
+}
+
+
+void KSayItApp::slotConfigureToolbar()
+{
+ saveMainWindowSettings( config, "MainWindow" );
+ KEditToolbar dlg(actionCollection(), KSAYITUI);
+ connect(&dlg,SIGNAL(newToolbarConfig()),this,SLOT(slotNewToolbarConfig()));
+ if (dlg.exec())
+ {
+ createGUI(KSAYITUI);
+ }
+}
+
+
+void KSayItApp::slotNewToolbarConfig()
+{
+ applyMainWindowSettings( config, "MainWindow" );
+}
+
+
+void KSayItApp::slotFileOpen()
+{
+ slotStatusMsg(i18n("Open file..."));
+ m_enableChangeNotifications = false;
+
+ // open filerequester
+ QString fn;
+ QString usershome( getenv("HOME") );
+ KURL url = KFileDialog::getOpenURL(usershome, QString::null, this, i18n("File to Speak") );
+ try{
+ if ( !url.isEmpty() ){
+ resetView();
+ treeview->openFile( url );
+ setActions(ACTIONS::PLAY | ACTIONS::FFWD);
+ save ->setEnabled(false);
+ saveAs->setEnabled(true);
+ edit->setChecked(false);
+ treeview->setEditMode( false );
+ bookmarkmenu->setEnabled(true);
+ }
+ }
+ catch( QString err ){
+ KMessageBox::error(this, err);
+ save ->setEnabled(false);
+ saveAs->setEnabled(true);
+ bookmarkmenu->setEnabled(false);
+ }
+
+ m_enableChangeNotifications = true;
+}
+
+
+void KSayItApp::slotFileSave()
+{
+ slotStatusMsg(i18n("Save file..."));
+ try {
+ treeview->saveFile();
+ save ->setEnabled(false);
+ saveAs->setEnabled(true);
+ }
+ catch ( QString err )
+ {
+ KMessageBox::error(this, err);
+ save ->setEnabled(false);
+ saveAs->setEnabled(true);
+ }
+}
+
+
+void KSayItApp::slotFileSaveAs()
+{
+ slotStatusMsg(i18n("Save file as..."));
+ try {
+ treeview->saveFileAs();
+ save ->setEnabled(true);
+ saveAs->setEnabled(true);
+ bookmarkmenu->setEnabled(true);
+ }
+ catch ( QString err )
+ {
+ KMessageBox::error(this, err);
+ save ->setEnabled(true);
+ saveAs->setEnabled(true);
+ bookmarkmenu->setEnabled(false);
+ }
+}
+
+
+void KSayItApp::slotEnableCopyCut(bool enable)
+{
+ copy->setEnabled(enable);
+ cut ->setEnabled(enable);
+}
+
+
+void KSayItApp::slotEditKeys()
+{
+ KKeyDialog::configure( actionCollection() ); //, xmlFile());
+}
+
+
+void KSayItApp::slotFileQuit()
+{
+ slotStatusMsg(i18n("Exiting..."));
+ int really = KMessageBox::questionYesNo( this, i18n("Do you really want to quit?"), QString::null, KStdGuiItem::quit(), KStdGuiItem::cancel() );
+ if (really == KMessageBox::Yes){
+ slotSaveOptions();
+ kapp->quit();
+ } else {
+ slotStatusMsg(i18n("Ready."));
+ }
+}
+
+
+void KSayItApp::slotCloseMainWindow()
+{
+ this->hide();
+}
+
+
+void KSayItApp::slotToggleStatusBar()
+{
+ slotStatusMsg(i18n("Toggle the statusbar..."));
+ //turn Statusbar on or off
+ if(statusBar()->isVisible())
+ statusBar()->hide();
+ else
+ statusBar()->show();
+
+ slotStatusMsg(i18n("Ready."));
+}
+
+
+void KSayItApp::slotStatusMsg(const QString &text)
+{
+ // change status message permanently
+ statusBar()->clear();
+ statusBar()->changeItem(text, ID_STATUS_MSG);
+}
+
+
+void KSayItApp::slotSetCaption(const QString &caption)
+{
+ this->setCaption(caption);
+}
+
+
+void KSayItApp::slotPreferences()
+{
+ // create Preferences object and open it
+ VoiceSetupDlg *prefs = new VoiceSetupDlg(this, "preferences", i18n("Setup"), true,
+ config,
+ m_fxpluginhandler,
+ m_kttslib);
+
+ if (prefs->exec() == QDialog::Accepted){
+ delete prefs;
+ m_kttslib->reloadConfiguration();
+ m_fxpluginhandler ->readConfiguration();
+ } else {
+ delete prefs;
+ }
+}
+
+
+void KSayItApp::slotClipboardChanged()
+{
+ if ( cb->text().isEmpty() ){
+ tray->changeState( StateCLIPEMPTY::Instance() );
+ paste->setEnabled(false);
+ return;
+ }
+
+ if ( cb->data(QClipboard::Clipboard)->provides("text/plain") ){
+ tray->changeState( StateWAIT::Instance() );
+ paste->setEnabled(true);
+ } else {
+ tray->changeState( StateCLIPEMPTY::Instance() );
+ paste->setEnabled(false);
+ }
+}
+
+
+void KSayItApp::slotTextChanged(bool empty)
+{
+ m_textview_empty = empty;
+
+ // do nothing if change notifications from the Textedit are
+ // currently not welcome.
+ if ( !m_enableChangeNotifications )
+ return;
+
+ // do nothing if say is in progress
+ if ( m_ap_saying )
+ return;
+
+ kdDebug(100200) << "KSayItApp::slotTextChanged( " << empty << " )" << endl;
+
+ // Update actions
+ if ( empty ){
+ setActions(0);
+ } else {
+ setActions(ACTIONS::PLAY);
+ }
+ // save ->setEnabled(!empty);
+ saveAs->setEnabled(!empty);
+
+ // update TreeView-Item
+ treeview->setNodeContent( view->getText() );
+
+}
+
+
+void KSayItApp::slotClear()
+{
+ m_enableChangeNotifications = false;
+ // TextEdit clear
+ view->textClear();
+
+ // TreeView clear
+ treeview->clear();
+ treeview->createEmptyDocument();
+ treeview->setEditMode( true );
+ edit->setChecked(true);
+ slotStatusMsg(i18n("Edit Mode ON."));
+
+ // set actions
+ save ->setEnabled(false);
+ saveAs->setEnabled(false);
+ setActions(0);
+ bookmarkmenu->setEnabled(false);
+ m_enableChangeNotifications = true;
+}
+
+
+void KSayItApp::slotSayClipboard()
+{
+ // get Text from clipboard
+ slotStatusMsg(i18n("speaking Clipboard..."));
+ setActions(ACTIONS::PAUSE | ACTIONS::STOP | ACTIONS::FFWD | ACTIONS::FREV);
+ tray->changeState( StateSAY::Instance() );
+
+ clip = cb->text();
+ // sayActivated( clip.stripWhiteSpace() );
+ // set text and say it
+ slotSetText( clip.stripWhiteSpace() );
+ sayActivated();
+}
+
+
+void KSayItApp::slotSayText()
+{
+ // say Text from text-window
+ setActions(ACTIONS::PAUSE | ACTIONS::STOP | ACTIONS::FFWD | ACTIONS::FREV);
+ tray->changeState( StateSAY::Instance() );
+
+ slotStatusMsg(i18n("synthesizing..."));
+
+ if ( m_ap_paused ){
+ m_ap_paused = false;
+ m_kttslib->resume();
+ } else {
+ es->loadEffects();
+ treeview->sayActiveNodeAndChilds();
+ }
+}
+
+
+void KSayItApp::slotSayNode()
+{
+ sayActivated();
+}
+
+
+void KSayItApp::slotSetText(const QString &text)
+{
+ // also invoked by the treeview for the each node
+ if ( text.isNull() )
+ return;
+
+ // put text on the stack of KTTS
+ m_kttslib->setText( text );
+}
+
+void KSayItApp::sayActivated()
+{
+ kdDebug(100200) << "KSayItApp::sayActivated()" << endl;
+
+ preferences->setEnabled(false);
+ m_ap_saying = true;
+
+ try {
+ m_kttslib->sayText();
+ }
+ catch (QString err){
+ kdDebug(100200) << "Exception catched in KSayItApp::sayActivated()" << endl;
+ KMessageBox::sorry(0, err, i18n("Unable to speak text"));
+ slotFinished();
+ }
+}
+
+
+void KSayItApp::slotTTSFinished()
+{
+ kdDebug(100200) << "KSayItApp::slotTTSFinished()" << endl;
+ es->unloadEffects();
+ slotFinished();
+}
+
+
+void KSayItApp::slotFinished()
+{
+ kdDebug(100200) << "KSayItApp::slotFinished()" << endl;
+
+ // disable/enable actions
+ m_ap_paused = false;
+
+ if ( m_textview_empty ){
+ setActions(0);
+ } else {
+ setActions(ACTIONS::PLAY);
+ }
+ tray->changeState( StateWAIT::Instance() );
+ preferences->setEnabled(true);
+ m_ap_saying = false;
+ slotStatusMsg(i18n("Ready."));
+}
+
+
+void KSayItApp::slotStopActivated()
+{
+ m_kttslib->stop();
+ // slotFinished();
+}
+
+
+void KSayItApp::slotPauseActivated()
+{
+ kdDebug(100200) << "KSayItApp::slotPauseActivated()" << endl;
+
+ m_kttslib->pause();
+ m_ap_paused = true;
+ setActions(ACTIONS::PLAY | ACTIONS::STOP);
+ tray->changeState( StateSAY::Instance() );
+ slotStatusMsg(i18n("Paused..."));
+}
+
+
+void KSayItApp::slotNextSentenceActivated()
+{
+ kdDebug(100200) << "KSayItApp::slotNextSentenceActivated()" << endl;
+ m_kttslib->ffwd();
+}
+
+
+void KSayItApp::slotPrevSentenceActivated()
+{
+ kdDebug(100200) << "KSayItApp::slotPrevSentenceActivated()" << endl;
+ m_kttslib->frev();
+}
+
+
+void KSayItApp::setActions(int actions)
+{
+ // ACTIONS::PLAY | ACTIONS::STOP | ACTIONS::PAUSE | ACTIONS::FFWD | ACTIONS::FREV;
+
+ // Get the mask of supported actions from the plugin.
+ int mask = m_kttslib->getActions();
+ kdDebug(100200) << QString("KSayItApp:PSA: %1").arg(mask, 0, 2) << endl;
+
+ // disable actions not supported by the plugin
+ int ma = actions & mask;
+
+ if (ma & ACTIONS::PLAY){
+ say->setEnabled(true);
+ } else {
+ say->setEnabled(false);
+ }
+ if (ma & ACTIONS::STOP){
+ shutup->setEnabled(true);
+ } else {
+ shutup->setEnabled(false);
+ }
+ if (ma & ACTIONS::PAUSE){
+ pause->setEnabled(true);
+ } else {
+ pause->setEnabled(false);
+ }
+ if (ma & ACTIONS::FFWD){
+ next_sentence->setEnabled(true);
+ } else {
+ next_sentence->setEnabled(false);
+ }
+ if (ma & ACTIONS::FREV){
+ prev_sentence->setEnabled(true);
+ } else {
+ prev_sentence->setEnabled(false);
+ }
+
+ tray->setActions( say->isEnabled(), pause->isEnabled(), shutup->isEnabled(),
+ next_sentence->isEnabled(), prev_sentence->isEnabled() );
+}
+
+
+void KSayItApp::slotTreeViewChanged(const QString &str)
+{
+ kdDebug(100200) << "KSayItApp::slotTreeViewChanged()" << endl;
+
+ if ( !m_ap_saying )
+ setActions(ACTIONS::PLAY);
+
+ m_enableChangeNotifications = false;
+ view->textClear();
+ view->setText(str);
+ m_enableChangeNotifications = true;
+}
+
+
+void KSayItApp::slotEnableTextedit(bool enable)
+{
+ kdDebug(100200) << "KSayItApp::slotEnableTextedit( " << enable << " )" << endl;
+
+ view->enableTextedit( enable );
+}
+
+
+void KSayItApp::resetView()
+{
+ m_enableChangeNotifications = false;
+ // TextEdit clear
+ view->textClear();
+
+ // TreeView clear
+ treeview->clear();
+
+ // set actions
+ save ->setEnabled(false);
+ saveAs->setEnabled(false);
+ setActions(0);
+ m_enableChangeNotifications = true;
+}
+
+
+void KSayItApp::slotAddBookmark()
+{
+ kdDebug(100200) << "KSayItApp::slotAddBookmark()" << endl;
+
+
+}
+
+
+void KSayItApp::slotEditBookmarks()
+{
+ kdDebug(100200) << "KSayItApp::slotEditBookmark()" << endl;
+
+
+}
+
+
+
+#include "ksayit.moc"
diff --git a/ksayit/src/ksayit.desktop b/ksayit/src/ksayit.desktop
new file mode 100644
index 0000000..424b09e
--- /dev/null
+++ b/ksayit/src/ksayit.desktop
@@ -0,0 +1,64 @@
+[Desktop Entry]
+Type=Application
+Exec=ksayit -caption "%c" %i
+Icon=ksayit
+DocPath=ksayit/index.html
+Terminal=false
+Name=KSayIt
+Name[hi]=के-से-इट
+Name[mk]=KSaylt
+Name[ne]=के से इट
+Name[sk]=PovedzTo
+Name[sv]=Ksayit
+Name[tg]=KSayIt
+Name[tr]=Ksayit
+Name[vi]=Nói K
+GenericName=Text-to-Speech Frontend
+GenericName[bg]=Синтез на глас
+GenericName[bs]=Program za izgovaranje teksta
+GenericName[ca]=Frontal per text a veu
+GenericName[cs]=Rozhraní hlasové syntézy
+GenericName[da]=Forende for tekst-til-tale
+GenericName[de]=Oberfläche für die Sprachausgabe
+GenericName[el]=Μετατροπή κειμένου σε ομιλία
+GenericName[es]=Interfaz de administración del sistema de texto a voz de KDE
+GenericName[et]=Teksti kõneks muutmine
+GenericName[eu]=Testutik hizketarako interfazea
+GenericName[fa]=پایانۀ متن به گفتار
+GenericName[fi]=Teksti puheeksi käyttöliittymä
+GenericName[fr]=Interface pour la synthèse vocale
+GenericName[ga]=Comhéadan Téacs-go-Caint
+GenericName[gl]=Interface de Texto-para-Fala
+GenericName[hu]=Szövegfelolvasó
+GenericName[is]=Texti-í-tal myndrænt viðmót
+GenericName[it]=Interfaccia di pronuncia
+GenericName[ja]=テキスト読み上げフロントエンド
+GenericName[ka]=ტექსტი-გახმოვანების ინტერფეისი
+GenericName[km]=ផ្នែក​ខាង​មុខ​អត្ថបទ​ដែល​ត្រូវ​និយាយ
+GenericName[lt]=Teksto vertimo kalba naudotojo sąsaja
+GenericName[mk]=Преден дел за текст-во-говор
+GenericName[ms]=Antaramuka Teks-ke-Tutur
+GenericName[mt]=Programm għal Test-għal-Vuċi
+GenericName[nb]=Brukerflate for tekst til tale
+GenericName[nds]=Böversiet för den Vörleser
+GenericName[ne]=पाठ वाचक फ्रन्टइन्ड
+GenericName[nl]=Tekst-tot-spraak-schil
+GenericName[pa]=ਪਾਠ ਤੋਂ ਬੋਲੀ ਮੁੱਖ
+GenericName[pl]=Program obsługujący syntezator mowy
+GenericName[pt]=Interface de Texto para Fala
+GenericName[pt_BR]=Interface para a Conversão de Texto para Fala
+GenericName[ru]=Интерфейс к средствам синтеза речи
+GenericName[sk]=Rozhranie text-na-reč
+GenericName[sl]=Vmesnik »besedila v govor«
+GenericName[sr]=Интерфејс за текст-у-говор
+GenericName[sr@Latn]=Interfejs za tekst-u-govor
+GenericName[sv]=Text-till-tal gränssnitt
+GenericName[ta]=பேச்சில் இருந்து உரை முன்னணி
+GenericName[tg]=Интерфейс барои таҳлили овоз
+GenericName[th]=ฟร้อนเอนด์แปลงข้อความเป็นคำพูด
+GenericName[tr]= Metinden Konuşmaya Önyüzü
+GenericName[uk]=Інтерфейс синтезу мовлення з тексту
+GenericName[vi]=Giao diện chuyển Văn bản thành Tiếng nói
+GenericName[zh_CN]=文本到语音前端
+GenericName[zh_TW]=文字轉語音前端程式
+Categories=Qt;KDE;Accessibility;Utility;
diff --git a/ksayit/src/ksayit.h b/ksayit/src/ksayit.h
new file mode 100644
index 0000000..6da1465
--- /dev/null
+++ b/ksayit/src/ksayit.h
@@ -0,0 +1,364 @@
+/***************************************************************************
+ ksayit.h - description
+ -------------------
+ begin : Son Aug 10 13:26:57 EDT 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KSAYIT_H
+#define KSAYIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+using namespace std;
+
+// include files for Qt
+#include <qstringlist.h>
+#include <qclipboard.h>
+
+// include files for KDE
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <kaccel.h>
+#include <kaction.h>
+#include <kactionclasses.h>
+#include <kurl.h>
+#include <dcopobject.h>
+#include <kbookmarkmanager.h>
+#include <kbookmarkmenu.h>
+
+// App specific includes
+
+// appended to $HOME
+#define KSAYIT_BOOKMARKXMLFILE "/.ksayitbookmarks.xml"
+
+// forward declaration of the KSayIt classes
+class KSayItViewImpl;
+class DocTreeViewImpl;
+class KSayItSystemTray;
+class FXPluginHandler;
+class EffectStack;
+class KTTSDLib;
+class KSayItBookmarkHandler;
+
+/**
+ * The base class for KSayIt application windows. It sets up the main
+ * window and reads the config file as well as providing a menubar, toolbar
+ * and statusbar. An instance of KSayItView creates the center view.
+ * KSayItApp reimplements the methods that KMainWindow provides for main window handling and supports
+ * full session management as well as using KActions.
+ * @see KMainWindow
+ * @see KApplication
+ * @see KConfig
+ *
+ * @author Robert Vogl
+ */
+class KSayItApp : public KMainWindow, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+public:
+ /** construtor of KSayItApp, calls all init functions to create the application.
+ */
+ KSayItApp(QWidget* parent=0, const char* name=0, WFlags f=0,
+ const QCString &objID=0);
+ ~KSayItApp();
+
+k_dcop:
+ /** DCOP interface for say operation
+ \param msg The text to speak.
+ */
+ ASYNC dcopSayText(QString msg);
+
+ /** DCOP interface for stop operation
+ */
+ ASYNC dcopStop();
+
+ /** DCOP interface to say DocBook file
+ */
+ ASYNC dcopSayXmlFile(KURL url);
+
+
+signals:
+ /** emitted when the Configuration was modified
+ */
+ void signalConfigChanged();
+
+private slots:
+ /** Puts the given text on the Job-Stack of KTTSD.
+ * \param text The text to say.
+ */
+ void slotSetText(const QString &text);
+
+ /** Called from the ListView widget after one or many
+ * 'setText'-Calls. Starts to say the text.
+ */
+ void slotSayNode();
+
+ /** Called when a node in the treeview was clicked and
+ * new content in the edit window must be shown.
+ * \str The new content of the EditView.
+ */
+ void slotTreeViewChanged(const QString &str);
+
+ /** save general Options like all bar positions and status as well as the geometry to
+ * the configuration file.
+ */
+ void slotSaveOptions();
+
+ /** closes the windows , then quits the application.
+ */
+ void slotFileQuit();
+
+ /** changes the statusbar contents for the standard label permanently, used to indicate
+ * current actions.
+ * @param text the text that is displayed in the statusbar
+ */
+ void slotStatusMsg(const QString &text);
+
+ /** opens the Preferences-Dialog.
+ */
+ void slotPreferences();
+
+ /** activated if "say" from tray was clicked.
+ */
+ void slotSayClipboard();
+
+ /** activated if "say" from app-window was clicked.
+ */
+ void slotSayText();
+
+ /** activated if "shut up" was clicked.
+ */
+ void slotStopActivated();
+
+ /** activated if "pause" was clicked.
+ */
+ void slotPauseActivated();
+
+ /** activated if "next sentence" was clicked.
+ */
+ void slotNextSentenceActivated();
+
+ /** activated if "previous sentence" was clicked.
+ */
+ void slotPrevSentenceActivated();
+
+ /** called if text processing was finished.
+ */
+ void slotFinished();
+
+ /** called to enable the copy/cut action, if text is selected in the TextEdit-View
+ \param enable Enable actions if true, disable actions if false.
+ */
+ void slotEnableCopyCut(bool enable);
+
+ /** sets the Caption of the MainWindow */
+ void slotSetCaption(const QString &caption);
+
+ /** called when the Text was changed.
+ * \param empty True if the TextEdit view is empty.
+ */
+ void slotTextChanged(bool empty);
+
+ /** enabled/disables the textedit window;
+ * \param enable true=enabled, false=disabled
+ */
+ void slotEnableTextedit(bool enable);
+
+ /** toggles the statusbar
+ */
+ void slotToggleStatusBar();
+
+ /** Called when the ToolBar shall be configured by the user.
+ */
+ void slotConfigureToolbar();
+
+ /** Called to add a bookmark.
+ */
+ void slotAddBookmark();
+
+ /** Called to delete a bookmark
+ */
+ void slotDeleteBookmark(const QString &url, const QString &title);
+
+ /** Called to edit bookmarks.
+ */
+ void slotEditBookmarks();
+
+ /** Called from slotConfigureToolbar() if we have a new ToolBar-configuration.
+ */
+ void slotNewToolbarConfig();
+
+ /** called whenever the content of the clipboard changes.
+ * Checks if the content of the Clipboard is of type text/plain.
+ * Disables and enables the SystemTray-object.
+ */
+ void slotClipboardChanged();
+
+ /** Deletes the content of the Textview.
+ */
+ void slotClear();
+
+ /** Hides the MainWindow
+ */
+ void slotCloseMainWindow();
+
+ /** Dialog to edit the Key associations
+ */
+ void slotEditKeys();
+
+ /** Open file action
+ */
+ void slotFileOpen();
+
+ /** Save file
+ */
+ void slotFileSave();
+
+ /** Save file as
+ */
+ void slotFileSaveAs();
+
+ /** Called, when the TTS Library has finished processing.
+ */
+ void slotTTSFinished();
+
+ /** Edit mode switched on/off.
+ */
+ void slotEditToggled();
+
+ /**
+ * Catches the signal from the TreeView object
+ * and forwards it to the BookmarkHandler object.
+ */
+ void slotNotifyBookmarkHandler(const QString &ID, const QString &title);
+
+ /**
+ * Copies the content of the current bookmark file to the
+ * file designated by \p newname and install a new
+ * BookmarkHandler.
+ * \param newname The name of the new bookmark file.
+ */
+ void slotChangeBookmarkFilename(const QString &newname);
+
+ /** Loads bookmark file corresponding to the given file.
+ * \param newname The name of the new file.
+ */
+ void slotSetBookmarkFilename(const QString &newname);
+
+public:
+ /**
+ * Selects the item with the given ID in the TreeView.
+ * \param ID The ID of the item to select.
+ * \param title The title of the bookmark.
+ * \returns <tt>QString::null</tt>, if the operation was successfull,
+ * an error message, if the ID was not found.
+ */
+ QString setItemByBookmark( const QString &ID, const QString &title );
+
+private: // Methods
+ /** read general Options again and initialize all variables.
+ */
+ void readOptions();
+
+ /** initializes the KActions of the application */
+ void initActions();
+
+ /** sets up the statusbar for the main window by initialzing a statuslabel.
+ */
+ void initStatusBar();
+
+ /**
+ */
+ void initBookmarkManager(const QString &filename);
+
+ /** creates the centerwidget of the KTMainWindow instance and sets it as the view.
+ */
+ void initView();
+
+ /** resets the editor. Do not create an empty document.
+ */
+ void resetView();
+
+ /** start to say the text on the KTTSD's Job-Stack.
+ */
+ void sayActivated();
+
+ /** reimplemented from baseclass
+ */
+ virtual void closeEvent(QCloseEvent *ce);
+
+ /** disable/enable Actions.
+ * \param actions An OR'ed integer of enum ACTIONS. A '1' is supposed
+ * as 'Action enabled'.
+ */
+ void setActions(int actions);
+
+ /**
+ * Returns the absolute pathname of the given bookmarkfile.
+ * This is the first KDE resource directory \p (share/apps) in which
+ * the user has write permissions. The relative path is
+ * \p ksayit/ksayit_bookmarks/.
+ * \param filename The name of the bookmark file.
+ * \returns The absolute pathname of the given bookmark file.
+ * Returns \p QString::null if the operation was not successfull.
+ */
+ QString getBookmarkDir(const QString &filename);
+
+
+private:
+ KConfig *config;
+ KSayItViewImpl *view;
+ KSayItSystemTray *tray;
+ EffectStack *es;
+ DocTreeViewImpl *treeview;
+ KBookmarkManager *bkManager;
+ KSayItBookmarkHandler *bkHandler;
+ KBookmarkMenu *bkMenu;
+
+ // KAction pointers
+ KToggleAction *statusBarAction;
+ KAction *say;
+ KAction *pause;
+ KAction *shutup;
+ KAction *next_sentence;
+ KAction *prev_sentence;
+ KAction *clear;
+ KAction *copy;
+ KAction *cut;
+ KAction *paste;
+ KAction *open;
+ KAction *save;
+ KAction *saveAs;
+ KAction *preferences;
+ KToggleAction *edit;
+ KActionMenu *bookmarkmenu;
+
+ // Misc stuff
+ QClipboard *cb;
+ QString clip;
+ KTTSDLib *m_kttslib;
+ FXPluginHandler *m_fxpluginhandler;
+ bool m_ap_saying;
+ bool m_ap_paused;
+ bool m_textview_empty;
+ bool m_enableChangeNotifications;
+ QString m_currentBookmarkFile;
+
+};
+
+#endif // KSAYIT_H
diff --git a/ksayit/src/ksayit_fxplugin.h b/ksayit/src/ksayit_fxplugin.h
new file mode 100644
index 0000000..9956df6
--- /dev/null
+++ b/ksayit/src/ksayit_fxplugin.h
@@ -0,0 +1,88 @@
+//
+// C++ Interface: fxplugin
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef FXPLUGIN_H
+#define FXPLUGIN_H
+
+// QT includes
+#include <qobject.h>
+#include <qstring.h>
+
+// KDE includes
+#include <kapplication.h>
+#include <arts/kartsserver.h>
+#include <arts/artsflow.h>
+
+using namespace Arts;
+
+// App specific includes
+
+/** FXPlugin is an abstract class to create effect plugins for KSayIt.
+ * If you would like to implement a plugin, simply make a class
+ * derived from FXPlugin, include 'ksayit_fxplugin.h' and reimplement all the
+ * pure virtual functions provided herein.
+ * *Appl is a pointer to the main application as delivered by \p KApplication::kApplication().
+ * It can be used for any reason i.e. to install a Qt translator.\n
+ \author Robert Vogl
+ */
+class FXPlugin : public QObject
+{
+// Q_OBJECT
+public:
+ FXPlugin(QObject *parent=0, const char* name=0){};
+
+ /** Sets the Main application object. Useful for config objects etc.
+ */
+ virtual void setApplication(KApplication *Appl) = 0;
+
+ /** Returns the name of the plugin. This name is the unique identifier
+ * for the plugin. A expressive name is recommended because this name
+ * may be shown to the user, i.e. in a configuration dialog.
+ * The PluginHandler internally references to each effect plugin by this name.\n
+ * Has to be reimplemented by the plugin implementation.
+ */
+ virtual QString getName_KS() const = 0;
+
+ /** Returns the description of the plugin.\n
+ * Has to be reimplemented by the plugin implementation.
+ */
+ virtual QString getDescription_KS() const = 0;
+
+ /** Shows the GUI to configure the plugin. The configuration can to be
+ * stored in the global configuration file of KSayIt.\n
+ * Has to be reimplemented by the plugin implementation.
+ */
+ virtual bool showGUI_KS() = 0;
+
+ /** Activates the effect i.e. puts it on the soundservers stack.\n
+ * Returns the ID of the activated effect.
+ * Has to be reimplemented by the plugin implementation.
+ \param server A pointer to the aRts soundserver instance.
+ \param fx_stack A pointer to the effect stack of the soundserver.
+ */
+ virtual long activate_KS(KArtsServer *server,
+ StereoEffectStack *fx_stack) const = 0;
+
+ /** Deactivates the effect i.e. removes it from the effect stack.\n
+ * Has to be reimplemented by the plugin implementation.
+ \param fx_stack A pointer to the effect stack of the soundserver.
+ \param EffectID The ID of the effect as returned by \p activate_KS().
+ */
+ virtual bool deactivate_KS(StereoEffectStack *fx_stack,
+ long EffectID) const = 0;
+
+};
+
+
+
+#endif
+
+
diff --git a/ksayit/src/ksayit_ttsplugin.h b/ksayit/src/ksayit_ttsplugin.h
new file mode 100644
index 0000000..1035993
--- /dev/null
+++ b/ksayit/src/ksayit_ttsplugin.h
@@ -0,0 +1,166 @@
+//
+// C++ Interface: ksayit_ttsplugin
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@lapislazuli>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef KSAYIT_TTSPLUGIN
+#define KSAYIT_TTSPLUGIN
+
+// QT includes
+#include <qobject.h>
+#include <qwidget.h>
+#include <qframe.h>
+#include <qstring.h>
+
+
+// KDE includes
+#include <kapplication.h>
+
+// App specific includes
+
+
+#include "kttsdlib.h"
+
+/** TTSPlugin is an abstract class to integrate various TTS systems as plugins
+ * (Shared Objects) into KSayIt.
+ * If you would like to implement a plugin, simply make a class
+ * inherited from TTSPlugin, include 'ksayit_ttsplugin.h' and reimplement all the
+ * pure virtual functions provided herein.
+ * In addition you must implement two class factories:\n
+ * \p createPlugin() returns a pointer to an instance of your class.
+ * The Plugin Handler of KSayIt calls this function with a parameter pointing
+ * to the main application instance, as delivered by \p KApplication::kApplication().
+ * This pointer can be used for any reason i.e. to install a Qt translator.\n
+ * An instance of your class should be deleted by use of \p destroyPlugin().\n
+ * Example:
+ \code
+ extern "C"
+ {
+ TTSPlugin* createPlugin(KApplication *Appl)
+ {
+ return new MyNewPlugin(Appl);
+ }
+
+ void destroyPlugin(TTSPlugin* p)
+ {
+ delete p;
+ }
+ };
+ \endcode
+ * KSayIt expects two Qt-signals from the plugin:\n
+ * \p signalPluginFinished() must be emitted when the plugin is finished,
+ * i.e. a task to speak text has been finished.\n
+ * \p signalPluginFailed() is optional and shall emitted if the processing
+ * of the plugin has been failed by any reason.
+ \author Robert Vogl
+ */
+
+class TTSPlugin : public QObject
+{
+protected:
+ TTSPlugin(QObject *parent, const char *name) : QObject(parent, name){};
+
+public:
+ /** Returns the name of the plugin. This name is the unique identifier
+ * for the plugin. A expressive name is recommended because this name
+ * may be shown to the user, i.e. in a configuration dialog.
+ * The PluginHandler internally references to each TTS plugin by this name.\n
+ * Has to be reimplemented by the plugin implementation.
+ */
+ virtual QString getName_KS() const = 0;
+
+ /** Returns the description of the plugin.\n
+ * Has to be reimplemented by the plugin implementation.
+ */
+ virtual QString getDescription_KS() const = 0;
+
+ /** Returns the supported control actions of the plugin.
+ * It is represented as an OR'ed value of enum \pACTIONS.
+ */
+ virtual int getActions_KS() = 0;
+
+ /** Returnes a pointer to the GUI widget to configure the plugin.\n
+ * Will be deleted by the PluginHandler.\n
+ * \param frame A pointer to the QFrame object in which the dialog will
+ * be embedded.
+ */
+ virtual const QWidget* getGUI_KS(QFrame *frame) = 0;
+
+ /** Let the plugin (re)load its configuration
+ */
+ virtual void reloadConfiguration_KS() = 0;
+
+ /** Called from the Plugin Handler if the "OK" Button of the main
+ * configuartion dialog was clicked.\n
+ * Returns false if something went wrong otherwise true.
+ */
+ virtual bool saveWasClicked_KS() const = 0;
+
+ /** This method speeches the given Text.\n
+ * If the used TTS system outputs to a sound file
+ * (i.e. a .wav file) it may return its path and filename to KSayIt.
+ * In this case, KSayIt uses a built-in audio player to play back
+ * the file via aRts.\n
+ * If this plugin provides its own audio output mechanisms, then return
+ * \p QString::null.\n
+ * The TTS processing shall be implemented non-blocking, i.e. this function has
+ * to return a valid string as soon as possible, before the typically time
+ * consuming TTS processing starts. The synchronization with KSayIt shall
+ * be performed by the status flags (see \p getStatus_KS()).
+ * \param text The text to speach.
+ */
+ virtual QString sayText_KS(const QString &text) = 0;
+
+ /** Returns an OR'ed value of status bits of the plugin.\n
+ * Currently only \p TTS::AUDIOFILE is defined.\n This
+ * bit indicates that the plugin is configured to output
+ * to an audiofile.\n
+ * If configurable, \p TTS::AUDIOFILE must toggle synchronously with
+ * the setup widget.
+ * This flag must have a valid value during the overall lifetime
+ * of the plugin object.
+ */
+ virtual int getStatus_KS() const = 0;
+
+ /** Processes the stop event from KSayIt.
+ */
+ virtual void stop_KS() = 0;
+
+ /** Processes the pause event from KSayIt.
+ */
+ virtual void pause_KS() = 0;
+
+ /** Processes resume event after pause from KSayIt.
+ */
+ virtual void resume_KS() = 0;
+
+ /** May be used as a fast forward function, e.g.
+ * jump to the next sentence, paragraph or whatever.
+ */
+ virtual void ffwd_KS() = 0;
+
+ /** May be used as a rewind function, e.g.
+ * jumb back to the beginning of the current paragraph,
+ * repeat previous sentence or whatever.
+ */
+ virtual void frev_KS() = 0;
+
+};
+
+// Types of the class factories
+typedef TTSPlugin* (*create_ttspi)(KApplication *Appl);
+typedef void (*destroy_ttspi)(TTSPlugin *p);
+
+
+
+
+#endif
+
+
diff --git a/ksayit/src/ksayitbookmarkhandler.cpp b/ksayit/src/ksayitbookmarkhandler.cpp
new file mode 100644
index 0000000..b52cdd7
--- /dev/null
+++ b/ksayit/src/ksayitbookmarkhandler.cpp
@@ -0,0 +1,238 @@
+//
+// C++ Implementation: ksayitbookmarkhandler
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@web.de>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// Qt include
+#include <qregexp.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kurl.h>
+
+// App specific includes
+#include "ksayitbookmarkhandler.h"
+#include "ksayit.h"
+
+KSayItBookmarkHandler::KSayItBookmarkHandler(KBookmarkManager *bkManager, KSayItApp* parent)
+ : KBookmarkOwner(), m_bkManager(bkManager), m_parent(parent)
+{
+ m_ID = QString::null;
+ m_title = QString::null;
+}
+
+KSayItBookmarkHandler::~KSayItBookmarkHandler()
+{
+}
+
+
+void KSayItBookmarkHandler::notifyBookmarkHandler(const QString &ID, const QString &title)
+{
+ kdDebug(100200) << "KSayItBookmarkHandler::notifyBookmarkManager()" << endl;
+
+ m_ID = ID;
+ m_title = title;
+}
+
+
+void KSayItBookmarkHandler::openBookmarkURL(const QString &url)
+{
+ kdDebug(100200) << "KSayItBookmarkHandler::openBookmarkURL(" << url << ")" << endl;
+
+ QString l_url = url;
+ QString title = QString::null;
+ QString type = l_url.section( "://", 0, 0 );
+ QString ID = l_url.section( QRegExp("/+"), 1, 1 );
+ QString err = QString::null;
+
+ // Some checks
+ if ( type != "ksayit" ){
+ err += i18n("This is not a KSayIt bookmark.\n");
+ }
+
+ // get title
+ KBookmarkGroup bkRoot = m_bkManager->root();
+ if ( bkRoot.isNull() )
+ return;
+
+ KBookmark bookmark;
+ KBookmarkGroup group;
+ bool found = recursiveGetBkByURL( bookmark, group, bkRoot, url );
+ if ( found ){
+ title = bookmark.text();
+ }
+
+ QString result = QString::null;
+ result = m_parent->setItemByBookmark( ID, title );
+ if ( !result.isNull() ){
+ KMessageBox::sorry( 0, result, i18n("Bookmark not found") );
+ }
+}
+
+
+QString KSayItBookmarkHandler::currentTitle() const
+{
+ kdDebug(100200) << "KSayItBookmarkHandler::currentTitle()" << endl;
+
+ QString result;
+ if ( m_title.isEmpty()){
+ result = i18n("untitled");
+ } else {
+ result = m_title;
+ }
+
+ return result;
+}
+
+
+QString KSayItBookmarkHandler::currentURL() const
+{
+ kdDebug(100200) << "KSayItBookmarkHandler::currentURL()" << endl;
+
+ QString url;
+ url = "ksayit://" + m_ID;
+
+ return url;
+}
+
+
+void KSayItBookmarkHandler::deleteBookmark(const QString &url, const QString &title)
+{
+ kdDebug(100200) << "KSayItBookmarkHandler::deleteBookmark()" << endl;
+
+ KBookmarkGroup bkRoot = m_bkManager->root();
+ if ( bkRoot.isNull() )
+ return;
+
+ // search bookmark by URL
+ KBookmark bookmark;
+ KBookmarkGroup group;
+ bool found = false;
+ found = recursiveGetBkByURL( bookmark, group, bkRoot, url );
+ if ( found ){
+ group.deleteBookmark( bookmark );
+ m_bkManager->emitChanged( group );
+ m_bkManager->save(); // make persistent
+ return;
+ }
+
+ // if not found, search bookmark by title
+ int qty = 0;
+ qty = recursiveGetBkByTitle( bookmark, group, bkRoot, title );
+ if ( qty == 1 ){
+ QString url = bookmark.url().url();
+ QString title = bookmark.text();
+ group.deleteBookmark( bookmark );
+ m_bkManager->emitChanged( group );
+ m_bkManager->save(); // make persistent
+ }
+}
+
+
+bool KSayItBookmarkHandler::recursiveGetBkByURL(
+ KBookmark &bookmark,
+ KBookmarkGroup &group,
+ const KBookmarkGroup &bkGroup,
+ const QString &url)
+{
+ KBookmark bkNext;
+ bool found = false;
+
+ KBookmark bk = bkGroup.first();
+ while ( !bk.isNull() && !bk.isSeparator() ){
+ if ( bk.isGroup() ){
+ // recursive call
+ found = recursiveGetBkByURL( bookmark, group, bk.toGroup(), url );
+ if ( found )
+ return true;
+ bkNext = bkGroup.next( bk );
+ } else {
+ QString l_url = bk.url().url();
+ if ( l_url == url ){
+ bookmark = bk;
+ group = bkGroup;
+ return true;
+ }
+ bkNext = bkGroup.next( bk );
+ }
+ bk = bkNext;
+ }
+ return false;
+}
+
+
+int KSayItBookmarkHandler::recursiveGetBkByTitle(
+ KBookmark &bookmark,
+ KBookmarkGroup &group,
+ const KBookmarkGroup &bkGroup,
+ const QString &title)
+{
+ KBookmark bkNext;
+ int qty = 0;
+
+ KBookmark bk = bkGroup.first();
+ while ( !bk.isNull() && !bk.isSeparator() ){
+ if ( bk.isGroup() ){
+ // recursive call
+ qty += recursiveGetBkByTitle( bookmark, group, bk.toGroup(), title );
+ bkNext = bkGroup.next( bk );
+ } else {
+ QString l_title = bk.text();
+ if ( l_title == title ){
+ bookmark = bk;
+ group = bkGroup;
+ qty++;
+ }
+ bkNext = bkGroup.next( bk );
+ }
+ bk = bkNext;
+ }
+ return qty;
+}
+
+
+void KSayItBookmarkHandler::traverseBookmarks(KBookmarkGroup bkGroup)
+{
+ kdDebug(100200) << "### KSayItBookmarkHandler::traverseBookmarks()" << endl;
+
+ if( bkGroup.isNull() )
+ return;
+
+ KURL url;
+ QString title;
+ KBookmark bkNext, bkPrev, bkNew;
+
+ KBookmark bk = bkGroup.first();
+ while ( !bk.isNull() && !bk.isSeparator() ){
+ if ( bk.isGroup() ){
+ traverseBookmarks( bk.toGroup() ); // recursive call
+ bkNext = bkGroup.next( bk );
+ } else {
+ url = bk.url();
+ title = bk.text();
+ bkNext = bkGroup.next( bk );
+ bkPrev = bkGroup.previous( bk );
+ if ( bkPrev.isNull() ) // no predecessor
+ bkPrev = bk;
+
+ // Modifications on URL/Title BEGIN
+ //
+ // Modifications on URL/Title END
+
+ bkNew = bkGroup.addBookmark( m_bkManager, title, url, QString::null, false );
+ bkGroup.moveItem( bkNew, bkPrev );
+ bkGroup.deleteBookmark( bk );
+ }
+ bk = bkNext;
+ }
+ m_bkManager->save(); // make persistent
+}
diff --git a/ksayit/src/ksayitbookmarkhandler.h b/ksayit/src/ksayitbookmarkhandler.h
new file mode 100644
index 0000000..edab6d6
--- /dev/null
+++ b/ksayit/src/ksayitbookmarkhandler.h
@@ -0,0 +1,120 @@
+//
+// C++ Interface: ksayitbookmarkhandler
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@web.de>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef KSAYITBOOKMARKHANDLER_H
+#define KSAYITBOOKMARKHANDLER_H
+
+// Qt includes
+#include <qstring.h>
+
+// KDE includes
+#include <kbookmarkmanager.h>
+
+
+class KSayItApp;
+
+/**
+ Each of the objects in the TreeView that can be bookmarked has an unique ID.
+ The "URL" is to be created as follows: \p ksayit://filename/ID.\n
+ The "Title" is either the content of column 0 of the TreeView or the 32nd leading
+ charcters of the text (e.g. if the item references to a paragraph).
+@author Robert Vogl
+*/
+class KSayItBookmarkHandler : public KBookmarkOwner
+{
+public:
+ KSayItBookmarkHandler(KBookmarkManager *bkManager=0, KSayItApp* parent=0);
+ virtual ~KSayItBookmarkHandler();
+
+public:
+ /**
+ * Reimplemented from base class.\n
+ * Called when a bookmark in the menu was clicked.
+ * \param url The URL of the selected bookmark.
+ */
+ void openBookmarkURL(const QString &url);
+
+ /**
+ * Reimplemented from base class.\n
+ * Returns the Title when a new bookmark is about to be created.
+ * \returns The title of the bookmark.
+ */
+ QString currentTitle() const;
+
+
+ /**
+ * Reimplemented from base class.\n
+ * Returns the URL when a new bookmark is about to be created.
+ * \returns The URL of the bookmark.
+ */
+ QString currentURL() const;
+
+ /**
+ * Sets ID and title of the current TreeView item.
+ * \param ID The unique ID of the item.
+ * \param title The bookmark title of the item.
+ */
+ void notifyBookmarkHandler(const QString &ID, const QString &title);
+
+ /**
+ * Deletes the bookmark designated by the given url.
+ * \param url The url of the bookmark.
+ */
+ void deleteBookmark(const QString &url, const QString &title);
+
+ /**
+ * Iterates recursively through all bookmarks below the
+ * given group.
+ * \param bkGroup The KBookmarkGroup to start.
+ */
+ void traverseBookmarks(KBookmarkGroup bkGroup);
+
+private:
+ /**
+ * Searches the Bookmark designted by its URL.
+ * \param bookmark A reference that will contain the search result (bookmark).
+ * \param group A reference that will contain the search result
+ * (the group the found bookmark belongs to).
+ * \param bkGroup The root-bookmark from which the search will start
+ * (usually the topmost bookmark in the tree).
+ * \param url The URL of the bookmark to search for (including <tt>ksayit://</tt>).
+ * \returns \em true, if the bookmark was found, \em false, if not.
+ */
+ bool recursiveGetBkByURL(
+ KBookmark &bookmark,
+ KBookmarkGroup &group,
+ const KBookmarkGroup &bkGroup,
+ const QString &url);
+
+ /**
+ * Searches the Bookmark designted by its URL.
+ * \param bookmark A reference that will contain the search result (bookmark).
+ * \param group A reference that will contain the search result
+ * (the group the found bookmark belongs to).
+ * \param bkGroup The root-bookmark from which the search will start
+ * (usually the topmost bookmark in the tree).
+ * \param title The title of the bookmark to search for.
+ * \returns Number of bookmarks with the given title.
+ */
+ int recursiveGetBkByTitle(
+ KBookmark &bookmark,
+ KBookmarkGroup &group,
+ const KBookmarkGroup &bkGroup,
+ const QString &title);
+private:
+ QString m_ID;
+ QString m_title;
+ KBookmarkManager *m_bkManager;
+ KSayItApp *m_parent;
+
+};
+
+#endif
diff --git a/ksayit/src/ksayitsystemtray.cpp b/ksayit/src/ksayitsystemtray.cpp
new file mode 100644
index 0000000..82bda61
--- /dev/null
+++ b/ksayit/src/ksayitsystemtray.cpp
@@ -0,0 +1,356 @@
+/***************************************************************************
+ ksayitsystemtray.cpp - description
+ -------------------
+ begin : Die Sep 2 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include <iostream>
+
+// QT includes
+#include <qtranslator.h>
+
+// KDE includes
+#include <kglobal.h>
+#include <klocale.h>
+
+// App specific includes
+#include "ksayitsystemtray.h"
+
+KSayItSystemTray::KSayItSystemTray(QWidget *parent, const char *name)
+ : KSystemTray(parent,name)
+{
+ initActions();
+ changeState( StateCLIPEMPTY::Instance() );
+}
+
+KSayItSystemTray::~KSayItSystemTray()
+{
+ delete StateWAIT::Instance();
+ delete StateSAY::Instance();
+ delete StateCLIPEMPTY::Instance();
+}
+
+void KSayItSystemTray::initActions()
+{
+ // Context-menu
+ menu = this->contextMenu();
+ help = new KHelpMenu(this, kapp->aboutData(), false, actionCollection());
+ // Standard actions
+ settings = KStdAction::preferences(this, SLOT(slotPreferences()), actionCollection());
+ help_about = KStdAction::aboutApp(help, SLOT(aboutApplication()), actionCollection());
+ help_kde = KStdAction::aboutKDE(help, SLOT(aboutKDE()), actionCollection());
+
+ // User defined actions
+ say = new KAction(i18n("Say"),
+ "player_play",
+ 0,
+ this, SLOT (slotSayActivated()),
+ actionCollection(),
+ "say_it");
+
+ shutup = new KAction(i18n("Shut Up"),
+ "player_stop",
+ 0,
+ this, SLOT (slotStopActivated()),
+ actionCollection(),
+ "shut_up");
+
+ pause = new KAction (i18n("Pause"),
+ "player_pause",
+ 0,
+ this, SLOT (slotPauseActivated()),
+ actionCollection(),
+ "pause");
+
+ next_sentence = new KAction (i18n("Next Sentence"),
+ "2rightarrow",
+ 0,
+ this, SLOT (slotNextSentenceActivated()),
+ actionCollection(),
+ "next_sentence");
+
+
+ prev_sentence = new KAction (i18n("Previous Sentence"),
+ "2leftarrow",
+ 0,
+ this, SLOT(slotPrevSentenceActivated()),
+ actionCollection(),
+ "prev_sentence");
+
+ // Actions -> Context-menu
+ settings->plug(menu); menu->insertSeparator();
+ say->plug(menu);
+ shutup->plug(menu);
+ pause->plug(menu);
+ next_sentence->plug(menu);
+ prev_sentence->plug(menu); menu->insertSeparator();
+ help_about->plug(menu);
+ help_kde->plug(menu);
+
+ // default enables/disables
+ say ->setEnabled(false);
+ shutup ->setEnabled(false);
+ pause ->setEnabled(false);
+ next_sentence->setEnabled(false);
+ prev_sentence->setEnabled(false);
+}
+
+
+void KSayItSystemTray::slotPreferences()
+{
+ // call Preferences
+ emit signalCallPreferences();
+}
+
+void KSayItSystemTray::mousePressEvent(QMouseEvent *me)
+{
+ _state->mousePressEvent(this, me);
+}
+
+void KSayItSystemTray::mouseReleaseEvent(QMouseEvent *me)
+{
+ _state->mouseReleaseEvent(this, me);
+}
+
+void KSayItSystemTray::slotSayActivated()
+{
+ // start to say content of clipboard
+ emit signalSayActivated();
+}
+
+void KSayItSystemTray::slotStopActivated()
+{
+ // stop saying
+ emit signalShutUpActivated();
+}
+
+void KSayItSystemTray::slotPauseActivated()
+{
+ // pause saying
+ emit signalPauseActivated();
+}
+
+void KSayItSystemTray::slotNextSentenceActivated()
+{
+ // next sentence
+ emit signalNextActivated();
+}
+
+void KSayItSystemTray::slotPrevSentenceActivated()
+{
+ // previous sentence
+ emit signalPrevActivated();
+}
+
+
+void KSayItSystemTray::changeState(State *state)
+{
+ _state = state;
+ _state->setContext(this);
+}
+
+void KSayItSystemTray::setActions(bool sayEnabled, bool pauseEnabled, bool shutupEnabled,
+ bool nextEnabled, bool prevEnabled)
+{
+ say ->setEnabled(sayEnabled);
+ pause ->setEnabled(pauseEnabled);
+ shutup ->setEnabled(shutupEnabled);
+ next_sentence->setEnabled(nextEnabled);
+ prev_sentence->setEnabled(prevEnabled);
+}
+
+
+void KSayItSystemTray::normalMousePressEvent(QMouseEvent *e)
+{
+ KSystemTray::mousePressEvent(e);
+}
+
+void KSayItSystemTray::normalMouseReleaseEvent(QMouseEvent *e)
+{
+ KSystemTray::mouseReleaseEvent(e);
+}
+
+void KSayItSystemTray::sayClipboard()
+{
+ emit signalSayClipboard();
+}
+
+
+
+
+////////////////////////////////////////////
+State::State(){
+}
+State::~State(){
+}
+
+void State::mousePressEvent(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ // reimplemented by subclasses
+}
+
+void State::mouseReleaseEvent(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ // reimplemented by subclasses
+}
+
+void State::setContext(KSayItSystemTray *caller)
+{
+ // reimplemented by subclasses
+}
+
+void State::changeState(KSayItSystemTray *caller, State *state)
+{
+ caller->changeState(state);
+}
+
+void State::say(KSayItSystemTray *caller)
+{
+ caller->sayClipboard();
+}
+
+void State::mousePressEventCall(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ caller->normalMousePressEvent(e);
+}
+
+void State::mouseReleaseEventCall(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ caller->normalMouseReleaseEvent(e);
+}
+
+
+////////////////////////////////////////////
+StateWAIT::StateWAIT(){
+ m_traypixmap = KGlobal::iconLoader()->loadIcon("ksayit", KIcon::Toolbar);
+}
+StateWAIT::~StateWAIT(){
+}
+StateWAIT* StateWAIT::_instance = 0;
+
+StateWAIT* StateWAIT::Instance()
+{
+ if (_instance == 0){
+ _instance = new StateWAIT();
+ }
+ return _instance;
+}
+
+void StateWAIT::setContext(KSayItSystemTray *caller)
+{
+ caller->setPixmap( m_traypixmap );
+}
+
+void StateWAIT::mousePressEvent(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ if (e->button()==LeftButton){ // left Mouse-button pressed
+ QWidget::mousePressEvent(e); // do nothing (see mouseReleaseEvent)
+ } else {
+ mousePressEventCall(caller, e); // normal mouse-handling
+ }
+}
+
+void StateWAIT::mouseReleaseEvent(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ if (e->button()==LeftButton){ // left Mouse-button released
+ say(caller);
+ } else {
+ mouseReleaseEventCall(caller, e); // normal mouse-handling
+ }
+}
+
+
+
+////////////////////////////////////////////
+StateSAY::StateSAY(){
+ m_traypixmap = KGlobal::iconLoader()->loadIcon("ksayit_talking", KIcon::Toolbar);
+}
+StateSAY::~StateSAY(){
+}
+StateSAY* StateSAY::_instance = 0;
+
+StateSAY* StateSAY::Instance()
+{
+ if (_instance == 0){
+ _instance = new StateSAY();
+ }
+ return _instance;
+}
+
+void StateSAY::setContext(KSayItSystemTray *caller)
+{
+ caller->setPixmap( m_traypixmap );
+}
+
+void StateSAY::mousePressEvent(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ if (e->button()==LeftButton){ // left Mouse-button pressed
+ QWidget::mousePressEvent(e); // do nothing (see mouseReleaseEvent)
+ } else {
+ mousePressEventCall(caller, e); // normal mouse-handling
+ }
+}
+
+void StateSAY::mouseReleaseEvent(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ if (e->button()==LeftButton){ // left Mouse-button released
+ QWidget::mouseReleaseEvent(e); // do nothing (see mouseReleaseEvent)
+ } else {
+ mouseReleaseEventCall(caller, e); // normal mouse-handling
+ }
+}
+
+
+
+
+////////////////////////////////////////////
+StateCLIPEMPTY::StateCLIPEMPTY(){
+ m_traypixmap = KGlobal::iconLoader()->loadIcon("ksayit_clipempty", KIcon::Toolbar);
+}
+StateCLIPEMPTY::~StateCLIPEMPTY(){
+}
+StateCLIPEMPTY* StateCLIPEMPTY::_instance = 0;
+
+StateCLIPEMPTY* StateCLIPEMPTY::Instance()
+{
+ if (_instance == 0){
+ _instance = new StateCLIPEMPTY();
+ }
+ return _instance;
+}
+
+void StateCLIPEMPTY::setContext(KSayItSystemTray *caller)
+{
+ caller->setPixmap( m_traypixmap );
+}
+
+void StateCLIPEMPTY::mousePressEvent(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ if (e->button()==LeftButton){ // left Mouse-button pressed
+ QWidget::mousePressEvent(e); // do nothing (see mouseReleaseEvent)
+ } else {
+ mousePressEventCall(caller, e); // normal mouse-handling
+ }
+}
+
+void StateCLIPEMPTY::mouseReleaseEvent(KSayItSystemTray *caller, QMouseEvent *e)
+{
+ if (e->button()==LeftButton){ // left Mouse-button released
+ QWidget::mouseReleaseEvent(e); // do nothing (see mouseReleaseEvent)
+ } else {
+ mouseReleaseEventCall(caller, e); // normal mouse-handling
+ }
+}
+
+
+#include "ksayitsystemtray.moc"
diff --git a/ksayit/src/ksayitsystemtray.h b/ksayit/src/ksayitsystemtray.h
new file mode 100644
index 0000000..90db592
--- /dev/null
+++ b/ksayit/src/ksayitsystemtray.h
@@ -0,0 +1,228 @@
+/***************************************************************************
+ ksayitsystemtray.h - description
+ -------------------
+ begin : Die Sep 2 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KSAYITSYSTEMTRAY_H
+#define KSAYITSYSTEMTRAY_H
+
+// QT includes
+#include <qwidget.h>
+#include <qpixmap.h>
+
+// KDE includes
+#include <kapplication.h>
+#include <ksystemtray.h>
+#include <kpopupmenu.h>
+#include <kaction.h>
+#include <kmenubar.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+
+// forward declarations
+class State;
+
+/**
+ *@author Robert Vogl
+ */
+class KSayItSystemTray : public KSystemTray {
+ Q_OBJECT
+
+ friend class State;
+
+public:
+ KSayItSystemTray(QWidget *parent=0, const char *name=0);
+ ~KSayItSystemTray();
+
+signals:
+ /** Signal emitted if configuration has been changed
+ */
+ void signalCallPreferences();
+
+ /** Signal emitted if the Tray icon was clicked.
+ */
+ void signalSayClipboard();
+
+ /** Signal emitted by the control actions
+ */
+ void signalSayActivated();
+
+ void signalShutUpActivated();
+
+ void signalPauseActivated();
+
+ void signalNextActivated();
+
+ void signalPrevActivated();
+
+public slots:
+ /** opens the Preferences-Dialog
+ */
+ void slotPreferences();
+
+ /** activated if "say" was clicked
+ */
+ void slotSayActivated();
+
+ /** activated if "shut up" was clicked
+ */
+ void slotStopActivated();
+
+ /** activated if "pause" was clicked
+ */
+ void slotPauseActivated();
+
+ /** activated if "next sentence" was clicked
+ */
+ void slotNextSentenceActivated();
+
+ /** activated if "previous sentence" was clicked
+ */
+ void slotPrevSentenceActivated();
+
+public:
+ /** Changes the state of the statemachine
+ */
+ void changeState(State *state);
+
+ /** Enables/Diasabled the actions in the menu
+ */
+ void setActions(bool sayEnabled, bool pauseEnabled, bool shutupEnabled,
+ bool nextEnabled, bool prevEnabled);
+
+protected: // Methods
+ /** Reimplementation from base class
+ */
+ void mousePressEvent(QMouseEvent *);
+
+ /** Reimplementation from base class
+ */
+ void mouseReleaseEvent(QMouseEvent *);
+
+ /** KSystemTray default mouse handling
+ */
+ void normalMousePressEvent(QMouseEvent *e);
+
+ /** KSystemTray default mouse handling
+ */
+ void normalMouseReleaseEvent(QMouseEvent *e);
+
+ /** Called if the Tray icon was clicked.
+ */
+ void sayClipboard();
+
+private: // Methods
+ /** initializes the KActions of the application */
+ void initActions();
+
+public:
+ KAction *say;
+ KAction *shutup;
+ KAction *pause;
+ KAction *next_sentence;
+ KAction *prev_sentence;
+
+private:
+ KPopupMenu *menu;
+ KHelpMenu *help;
+ KAction *settings;
+ KAction *help_about;
+ KAction *help_kde;
+ State *_state;
+
+};
+
+
+
+
+class State : public KSystemTray {
+ Q_OBJECT
+public:
+ State();
+ ~State();
+
+ virtual void mousePressEvent(KSayItSystemTray *caller, QMouseEvent *e);
+ virtual void mouseReleaseEvent(KSayItSystemTray *caller, QMouseEvent *e);
+ virtual void setContext(KSayItSystemTray *caller);
+
+protected:
+ void changeState(KSayItSystemTray *caller, State *state);
+ void say(KSayItSystemTray *caller);
+ void mousePressEventCall(KSayItSystemTray *caller, QMouseEvent *e);
+ void mouseReleaseEventCall(KSayItSystemTray *caller, QMouseEvent *e);
+};
+
+
+
+
+class StateWAIT : public State {
+
+public:
+ static StateWAIT* Instance();
+ ~StateWAIT();
+
+protected:
+ StateWAIT();
+ void mousePressEvent(KSayItSystemTray *caller, QMouseEvent *e);
+ void mouseReleaseEvent(KSayItSystemTray *caller, QMouseEvent *e);
+ void setContext(KSayItSystemTray *caller);
+
+private:
+ static StateWAIT *_instance;
+ QPixmap m_traypixmap;
+};
+
+
+
+
+class StateSAY : public State {
+
+public:
+ static StateSAY* Instance();
+ ~StateSAY();
+
+protected:
+ StateSAY();
+ void mousePressEvent(KSayItSystemTray *caller, QMouseEvent *e);
+ void mouseReleaseEvent(KSayItSystemTray *caller, QMouseEvent *e);
+ void setContext(KSayItSystemTray *caller);
+
+private:
+ static StateSAY *_instance;
+ QPixmap m_traypixmap;
+};
+
+
+
+
+class StateCLIPEMPTY : public State {
+
+public:
+ static StateCLIPEMPTY* Instance();
+ ~StateCLIPEMPTY();
+
+protected:
+ StateCLIPEMPTY();
+ void mousePressEvent(KSayItSystemTray *caller, QMouseEvent *e);
+ void mouseReleaseEvent(KSayItSystemTray *caller, QMouseEvent *e);
+ void setContext(KSayItSystemTray *caller);
+
+private:
+ static StateCLIPEMPTY *_instance;
+ QPixmap m_traypixmap;
+};
+
+
+#endif
diff --git a/ksayit/src/ksayitui.rc b/ksayit/src/ksayitui.rc
new file mode 100644
index 0000000..4352908
--- /dev/null
+++ b/ksayit/src/ksayitui.rc
@@ -0,0 +1,38 @@
+<!DOCTYPE kpartgui>
+<kpartgui version="0.1" name="ksayit" >
+ <ActionProperties>
+ <Action icon="player_play" name="say_it" />
+ <Action icon="player_pause" name="pause" />
+ <Action icon="player_stop" name="shut_up" />
+ <Action icon="2rightarrow" name="next_sentence" />
+ <Action icon="2leftarrow" name="prev_sentence" />
+ <Action icon="editdelete" name="clear" />
+ <Action icon="edit" name="edittext" />
+ </ActionProperties>
+ <MenuBar>
+ <Menu name="action" >
+ <text>&amp;Action</text>
+ <Action name="prev_sentence" />
+ <Action name="say_it" />
+ <Action name="next_sentence" />
+ <Action name="pause" />
+ <Action name="shut_up" />
+ <Separator lineSeparator="true" />
+ <Action name="edittext" />
+ <Action name="clear" />
+ </Menu>
+ <Action name="bookmarks" />
+ </MenuBar>
+ <ToolBar noMerge="1" name="mainToolBar" >
+ <text>Main Toolbar</text>
+ <Action name="bookmarks" />
+ <Separator name="separator_1" />
+ <Action name="prev_sentence" />
+ <Action name="say_it" />
+ <Action name="next_sentence" />
+ <Action name="pause" />
+ <Action name="shut_up" />
+ <Separator name="separator_0" />
+ <Action name="edittext" />
+ </ToolBar>
+</kpartgui>
diff --git a/ksayit/src/ksayitviewimpl.cpp b/ksayit/src/ksayitviewimpl.cpp
new file mode 100644
index 0000000..e619f8c
--- /dev/null
+++ b/ksayit/src/ksayitviewimpl.cpp
@@ -0,0 +1,115 @@
+/***************************************************************************
+ ksayitviewimpl.cpp - description
+ -------------------
+ begin : Son Aug 10 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include <iostream>
+using namespace std;
+
+ // QT includes
+#include <qradiobutton.h>
+#include <qtextstream.h>
+#include <qstring.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <ktextedit.h>
+#include <kmessagebox.h>
+
+// App specific includes
+#include "ksayitviewimpl.h"
+
+KSayItViewImpl::KSayItViewImpl(QWidget *parent, const char *name ) : KSayItView(parent,name) {
+
+ // some presets
+
+}
+KSayItViewImpl::~KSayItViewImpl(){
+}
+
+QString& KSayItViewImpl::getText(){
+ t = TextEdit->text();
+ return t;
+}
+
+
+void KSayItViewImpl::enableTextedit( bool enable )
+{
+ // if enable==true, we are in Edit Mode => RTF-Mode off.
+ if ( enable ){
+ TextEdit->setTextFormat( Qt::PlainText);
+ } else {
+ TextEdit->setTextFormat( Qt::RichText);
+ }
+ TextEdit->setReadOnly( !enable );
+}
+
+
+void KSayItViewImpl::slotTextChanged()
+{
+ int length = TextEdit->length();
+ if ( length > 2 ){
+ emit signalTextChanged(false);
+ } else {
+ emit signalTextChanged(true);
+ }
+}
+
+void KSayItViewImpl::slotCopyAvailable(bool available)
+{
+ // enable/disable copy/cut-action in the menubar
+ if (available)
+ emit signalEnableCopyCut(true);
+ else
+ emit signalEnableCopyCut(false);
+}
+
+void KSayItViewImpl::slotCopy()
+{
+ // copy selected text to the clipboard
+ TextEdit->copy();
+}
+
+
+void KSayItViewImpl::slotCut()
+{
+ // copy selected text to the clipboard and delete it
+ TextEdit->cut();
+}
+
+
+void KSayItViewImpl::slotPaste()
+{
+ // paste text from the clipboard to the texteditor
+ TextEdit->paste();
+}
+
+void KSayItViewImpl::textClear()
+{
+ // deletes the entire text of the texteditor
+ TextEdit->clear();
+}
+
+void KSayItViewImpl::setText(const QString &text)
+{
+ // set text to text
+ TextEdit->setText( text );
+}
+
+
+
+#include "ksayitviewimpl.moc"
diff --git a/ksayit/src/ksayitviewimpl.h b/ksayit/src/ksayitviewimpl.h
new file mode 100644
index 0000000..fea6c36
--- /dev/null
+++ b/ksayit/src/ksayitviewimpl.h
@@ -0,0 +1,97 @@
+/***************************************************************************
+ ksayitviewimpl.h - description
+ -------------------
+ begin : Son Aug 10 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KSAYITVIEWIMPL_H
+#define KSAYITVIEWIMPL_H
+
+// QT includes
+#include <qwidget.h>
+#include <qstring.h>
+
+// KDE includes
+
+// App includes
+#include <KSayItView.h>
+
+/**
+ *@author Robert Vogl
+ */
+
+class KSayItViewImpl : public KSayItView {
+ Q_OBJECT
+
+public:
+ KSayItViewImpl(QWidget *parent=0, const char *name=0);
+ ~KSayItViewImpl();
+
+signals:
+ void signalSetCaption(const QString &caption);
+ void signalShowStatus(const QString &status);
+ void signalEnableCopyCut(bool enable);
+
+ /** Emitted when the text in the TextEditor view cahnges.
+ * \param empty True if the TextEditor view is empty.
+ */
+ void signalTextChanged(bool empty);
+
+public slots:
+ /** True if text is selected or false if text is deselected.
+ */
+ void slotCopyAvailable(bool available);
+
+ /** Copy selected text to the clipboard.
+ */
+ void slotCopy();
+
+ /** Copy selected text to the clipboard and delete it.
+ */
+ void slotCut();
+
+ /** Paste text from the clipboard to the texteditor.
+ */
+ void slotPaste();
+
+private slots:
+ /** Called from the widget
+ */
+ void slotTextChanged();
+
+public: // Methods
+ /** Returns the text of the TextEdit-Widget
+ */
+ QString& getText();
+
+ /** Set the content of the textEdit-Widget to text
+ */
+ void setText(const QString &text);
+
+ /** Enables/disables the Textedit
+ * \param enable true=enabled, false=diabled
+ */
+ void enableTextedit( bool enable );
+
+ /** Deletes the entire text of the texteditor.
+ */
+ void textClear();
+
+private:
+ QString t;
+
+
+};
+
+#endif
diff --git a/ksayit/src/main.cpp b/ksayit/src/main.cpp
new file mode 100644
index 0000000..9dcf0fe
--- /dev/null
+++ b/ksayit/src/main.cpp
@@ -0,0 +1,62 @@
+/***************************************************************************
+ main.cpp - description
+ -------------------
+ begin : Son Aug 10 13:26:57 EDT 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <stdlib.h>
+
+// QT includes
+
+// KDE includes
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <arts/kartsdispatcher.h>
+#include <dcopclient.h>
+
+// App specific includes
+#include "version.h"
+#include "ksayit.h"
+
+static const char *description =
+ I18N_NOOP("KSayIt - A Text To Speech frontend for KDE");
+// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE
+
+
+int main(int argc, char *argv[])
+{
+
+ KAboutData aboutData( "ksayit", I18N_NOOP("KSayIt"),
+ KSAYIT_VERSION, description, KAboutData::License_GPL,
+ "(c) 1996 - 2005, Robert Vogl", 0, 0, "voglrobe@web.de");
+ aboutData.addAuthor("Robert Vogl",0, "voglrobe@web.de");
+ KCmdLineArgs::init( argc, argv, &aboutData );
+
+ KApplication app;
+
+ // setup MCOP
+ KArtsDispatcher dispatcher;
+
+ // setup DCOP
+ QCString appID = app.dcopClient()->registerAs( app.name(), false );
+
+ KSayItApp *ksayit = new KSayItApp(0, "MainWindow", 0, appID);
+ // ksayit->hide();
+ ksayit->show();
+
+ return app.exec();
+}
diff --git a/ksayit/src/parasaxparser.cpp b/ksayit/src/parasaxparser.cpp
new file mode 100644
index 0000000..575df06
--- /dev/null
+++ b/ksayit/src/parasaxparser.cpp
@@ -0,0 +1,96 @@
+//
+// C++ Implementation: parasaxparser
+//
+// Description: SAX2-Parser for 'para' elements of a DocBook file.
+//
+//
+// Author: Robert Vogl <voglrobe@web.de>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+// #include <iostream> // cout
+// using namespace std;
+
+// Qt includes
+
+// KDE includes
+#include <kdebug.h>
+
+// App specific includes
+#include "parasaxparser.h"
+
+ParaSaxParser::ParaSaxParser()
+{
+ m_reader = new QXmlSimpleReader();
+
+ m_handler = new SaxHandler();
+ m_reader->setContentHandler(m_handler);
+ m_reader->setErrorHandler(m_handler);
+ m_reader->setEntityResolver(m_handler);
+ m_reader->setDeclHandler(m_handler);
+
+ m_XmlInputHeader = QString::null;
+ m_XmlInputBody = QString::null;
+}
+
+ParaSaxParser::~ParaSaxParser()
+{
+ delete m_handler;
+ delete m_reader;
+}
+
+ParaSaxParser* ParaSaxParser::_instance = 0;
+
+ParaSaxParser* ParaSaxParser::Instance()
+{
+ if ( _instance == 0 ){
+ _instance = new ParaSaxParser();
+ }
+ return _instance;
+}
+
+
+void ParaSaxParser::setProcessingInstruction(const QString &data)
+{
+ m_XmlInputHeader = data;
+}
+
+
+void ParaSaxParser::setData(const QString &data)
+{
+ m_XmlInputBody = data;
+}
+
+
+void ParaSaxParser::getText(QString &data)
+{
+ QString XmlPart = m_XmlInputHeader + m_XmlInputBody;
+
+ QXmlInputSource input;
+ input.setData(XmlPart);
+
+ m_handler->reset();
+ m_handler->setRTF(false);
+ m_reader->parse( input );
+ m_handler->getData(data);
+
+}
+
+
+void ParaSaxParser::getRTFText(QString &data)
+{
+ QString XmlPart = m_XmlInputHeader + m_XmlInputBody;
+ kdDebug(100200) << "ParaSaxParser::getRTFText(): " << XmlPart << endl;
+
+ QXmlInputSource input;
+ input.setData(XmlPart);
+
+ m_handler->reset();
+ m_handler->setRTF(true);
+ m_reader->parse( input );
+ m_handler->getData(data);
+}
+
+
+
diff --git a/ksayit/src/parasaxparser.h b/ksayit/src/parasaxparser.h
new file mode 100644
index 0000000..e76d652
--- /dev/null
+++ b/ksayit/src/parasaxparser.h
@@ -0,0 +1,77 @@
+//
+// C++ Interface: parasaxparser
+//
+// Description: SAX2-Parser for 'para' elements of a DocBook file.
+//
+//
+// Author: Robert Vogl <voglrobe@web.de>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef PARASAXPARSER_H
+#define PARASAXPARSER_H
+
+// Qt includes
+#include <qxml.h>
+#include <qstring.h>
+
+// App specific includes
+#include "saxhandler.h"
+
+/**
+This class is a singleton.
+@author Robert Vogl
+*/
+class ParaSaxParser{
+public:
+ ~ParaSaxParser();
+
+ /**
+ * Creates the single instance of this parser (if not
+ * allready exists) and returns a pointer to it.
+ */
+ static ParaSaxParser* Instance();
+
+ /**
+ * Because this parser sees nothing but the 'para'
+ * parts of the document, it requires the documents header
+ * info, e.g. to resolve entities defined in the internal DTD.
+ * \param data The header (preamble) of the DocBook document.
+ */
+ void setProcessingInstruction(const QString &data);
+
+ /**
+ * This is the 'para' element to parse. It has to be encapsulated
+ * in <para> and </para>. Nested 'para' elements are not supported.
+ * \param data See description.
+ */
+ void setData(const QString &data);
+
+ /**
+ * Returns the pure text content of the paragraph without tags.
+ * \param data See description.
+ */
+ void getText(QString &data);
+
+ /**
+ * Returns the text in RTF format, i.e. replaces DocBook tags
+ * with RTF tags.
+ * \param data See description.
+ */
+ void getRTFText(QString &data);
+
+protected:
+ ParaSaxParser();
+
+private:
+ static ParaSaxParser* _instance;
+ SaxHandler* m_handler;
+ QXmlSimpleReader* m_reader;
+ QString m_XmlInputHeader;
+ QString m_XmlInputBody;
+
+
+};
+
+#endif
diff --git a/ksayit/src/saxhandler.cpp b/ksayit/src/saxhandler.cpp
new file mode 100644
index 0000000..2f8d49c
--- /dev/null
+++ b/ksayit/src/saxhandler.cpp
@@ -0,0 +1,187 @@
+//
+// C++ Implementation: saxhandler
+//
+// Description:
+//
+//
+// Author: Robert Vogl <voglrobe@web.de>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+// #include <iostream> // cout
+// using namespace std;
+
+// KDE includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+// App specific includes
+#include "saxhandler.h"
+
+SaxHandler::SaxHandler()
+ : QXmlDefaultHandler()
+{
+ m_output = QString::null;
+ m_rtf = true;
+ m_tagmap["action"] = "B";
+ m_tagmap["application"] = "B";
+ m_tagmap["function"] = "B";
+ m_tagmap["guibutton"] = "B";
+ m_tagmap["guiicon"] = "B";
+ m_tagmap["guilabel"] = "B";
+ m_tagmap["guimenu"] = "B";
+ m_tagmap["guimenuitem"] = "B";
+ m_tagmap["guisubmenu"] = "B";
+ m_tagmap["menuchoice"] = "B";
+ m_tagmap["mousebutton"] = "B";
+ m_tagmap["option"] = "B";
+ m_tagmap["author"] = "B";
+ m_tagmap["corpauthor"] = "B";
+ m_tagmap["warning"] = "FONT color=\"red\"";
+ m_tagmap["command"] = "TT";
+ m_tagmap["email"] = "TT";
+ m_tagmap["filename"] = "TT";
+ m_tagmap["keycap"] = "TT";
+ m_tagmap["keycode"] = "TT";
+ m_tagmap["keycombo"] = "TT";
+ m_tagmap["keysym"] = "TT";
+ m_tagmap["link"] = "TT";
+ m_tagmap["literal"] = "TT";
+ m_tagmap["userinput"] = "TT";
+ m_tagmap["citation"] = "EM";
+ m_tagmap["emphasis"] = "EM";
+ m_tagmap["foreignphrase"] = "EM";
+ m_tagmap["phrase"] = "EM";
+ m_tagmap["comment"] = "EM";
+ m_tagmap["note"] = "EM";
+ m_tagmap["tip"] = "EM";
+ m_tagmap["subscript"] = "small";
+ m_tagmap["superscript"] = "small";
+ m_tagmap["itemizedlist"] = "UL";
+ m_tagmap["listitem"] = "LI";
+}
+
+SaxHandler::~SaxHandler()
+{
+}
+
+
+void SaxHandler::setRTF(bool rtf)
+{
+ m_rtf = rtf;
+}
+
+
+bool SaxHandler::startElement(const QString &,
+ const QString &,
+ const QString & qName,
+ const QXmlAttributes & atts )
+{
+ if ( !m_rtf )
+ return true;
+
+ QString tag = qName.lower();
+
+ TagMapT::iterator it;
+ it = m_tagmap.find(tag);
+ if ( it != m_tagmap.end() ){
+ // tag found in hash table
+ QString rtftag = (*it).second;
+ m_output += "<" + rtftag + ">";
+ }
+
+ return true;
+}
+
+
+bool SaxHandler::endElement(const QString &,
+ const QString &,
+ const QString & qName)
+{
+ if ( !m_rtf )
+ return true;
+
+ QString tag = qName.lower();
+
+ TagMapT::iterator it;
+ it = m_tagmap.find(tag);
+ if ( it != m_tagmap.end() ){
+ // tag found in hash table
+ QString rtftag = (*it).second;
+ m_output += "</" + rtftag.section(" ", 0, 0) + ">";
+ }
+
+ return true;
+}
+
+
+bool SaxHandler::characters(const QString & ch)
+{
+ m_output += ch;
+ return true;
+}
+
+
+bool SaxHandler::fatalError(const QXmlParseException &exc)
+{
+ QString err = i18n("Fatal error while parsing XML-Paragraph:\n");
+ err += i18n("%1, Line: %2").arg(exc.message()).arg(exc.lineNumber());
+ KMessageBox::error(0, err, i18n("Fatal error") );
+ return false;
+}
+
+
+bool SaxHandler::resolveEntity(const QString &publicId,
+ const QString &systemId,
+ QXmlInputSource* &ret)
+{
+ return true;
+}
+
+
+bool SaxHandler::externalEntityDecl(const QString & name,
+ const QString & publicId,
+ const QString & systemId)
+{
+ kdDebug(100200) << "externalEntityDecl(): " << name << ", " << publicId << ", " << systemId << endl;
+ return true;
+}
+
+
+bool SaxHandler::internalEntityDecl(const QString & name,
+ const QString & value)
+{
+ kdDebug() << "internalEntityDecl(): " << name << ", " << value << endl;
+ return true;
+}
+
+
+bool SaxHandler::skippedEntity(const QString &name)
+{
+ QString warn = i18n("Unresolved entity found: %1.\n").arg(name);
+ warn += i18n("KSayIt does not support DocBook files with external entities. ");
+ warn += i18n("Parsing can continue, but the resulting text will contain gaps.");
+
+ int res;
+ // TODO: "Option: don't show again this warning."
+ res = KMessageBox::warningContinueCancel(0, warn, i18n("Parser problem") );
+ if ( res == KMessageBox::Cancel )
+ return false;
+ return true;
+}
+
+
+void SaxHandler::getData( QString &data ) const
+{
+ data = m_output;
+}
+
+
+void SaxHandler::reset()
+{
+ m_output = QString::null;
+}
+
+
diff --git a/ksayit/src/saxhandler.h b/ksayit/src/saxhandler.h
new file mode 100644
index 0000000..45061f3
--- /dev/null
+++ b/ksayit/src/saxhandler.h
@@ -0,0 +1,87 @@
+//
+// C++ Interface: saxhandler
+//
+// Description: Qt SAX2-Handler
+//
+//
+// Author: Robert Vogl <voglrobe@web.de>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef SAXHANDLER_H
+#define SAXHANDLER_H
+
+// STL includes
+#include <map>
+using namespace std;
+
+// Qt includes
+#include <qxml.h>
+#include <qstring.h>
+
+typedef map<QString, QString> TagMapT;
+
+
+/**
+@author Robert Vogl
+*/
+class SaxHandler : public QXmlDefaultHandler
+{
+public:
+ SaxHandler();
+ ~SaxHandler();
+
+ // Reimplementations from base class
+ bool startElement(const QString &namespaceURI,
+ const QString &localName,
+ const QString &qName,
+ const QXmlAttributes &atts );
+
+ bool endElement(const QString &namespaceURI,
+ const QString &localName,
+ const QString &qName);
+
+ bool characters(const QString &ch);
+
+ bool fatalError(const QXmlParseException &exc);
+
+ bool resolveEntity(const QString &publicId,
+ const QString &systemId,
+ QXmlInputSource* &ret);
+
+ bool externalEntityDecl(const QString &name,
+ const QString &publicId,
+ const QString &systemId);
+
+ bool internalEntityDecl(const QString &name,
+ const QString &value);
+
+ bool skippedEntity(const QString &name);
+
+ /**
+ * Returns the parser result.
+ */
+ void getData( QString &data ) const;
+
+ /**
+ * Reset
+ */
+ void reset();
+
+ /**
+ * Set Mode:
+ * \param rtf 'true' = Replace DocBook tags with RTF-tags.\n
+ * 'false' = Ignore tags, return text content only.
+ */
+ void setRTF(bool rtf);
+
+
+private:
+ QString m_output;
+ bool m_rtf;
+ TagMapT m_tagmap;
+
+};
+
+#endif
diff --git a/ksayit/src/version.h b/ksayit/src/version.h
new file mode 100644
index 0000000..180c99f
--- /dev/null
+++ b/ksayit/src/version.h
@@ -0,0 +1,23 @@
+/***************************************************************************
+ version.h - description
+ -------------------
+ begin : Son Aug 10 13:26:57 EDT 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef VERSION_H
+#define VERSION_H
+
+const char* KSAYIT_VERSION = " 0.8.4";
+
+#endif // VERSION_H
diff --git a/ksayit/src/voicesetupdlg.cpp b/ksayit/src/voicesetupdlg.cpp
new file mode 100644
index 0000000..bdf6db3
--- /dev/null
+++ b/ksayit/src/voicesetupdlg.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+ voicesetupdlg.cpp - description
+ -------------------
+ begin : Son Nov 2 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// #include <iostream>
+// using namespace std;
+
+// QT includes
+#include <qpixmap.h>
+#include <qstringlist.h>
+#include <qcombobox.h>
+#include <qcolor.h>
+#include <qlayout.h>
+#include <qwidget.h>
+
+// KDE includes
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+// App specific includes
+#include "voicesetupdlg.h"
+#include "fxsetupimpl.h"
+#include "fxpluginhandler.h"
+#include "kttsdlib.h"
+
+VoiceSetupDlg::VoiceSetupDlg(QWidget *parent, const char *name, const QString &caption,
+ bool modal,
+ KConfig *config,
+ FXPluginHandler *fxpluginhandler,
+ KTTSDLib *ttslib)
+ : KDialogBase(IconList, caption, Ok|Cancel, Ok, parent, name, modal, true),
+ m_config(config),
+ m_fxpluginhandler(fxpluginhandler),
+ m_kttslib(ttslib)
+{
+
+ setIconListAllVisible(true);
+ connect (this, SIGNAL(aboutToShowPage(QWidget*)), this, SLOT(slotPageChanged(QWidget*)));
+
+ initVoicePage();
+ initFXPage();
+
+}
+
+
+VoiceSetupDlg::~VoiceSetupDlg()
+{
+}
+
+
+void VoiceSetupDlg::initVoicePage()
+{
+ QPixmap icon = KGlobal::iconLoader()->loadIcon("ksayit", KIcon::Toolbar, KIcon::SizeMedium);
+ QFrame *voicePage = addPage( i18n( "Voice" ), i18n("Voice Settings"), icon );
+ QVBoxLayout *voiceLayout = new QVBoxLayout( voicePage, 0, spacingHint() );
+
+ const QWidget *voiceDialog = m_kttslib->getGUI( voicePage );
+ voiceLayout->addWidget( const_cast<QWidget*>(voiceDialog) );
+}
+
+
+void VoiceSetupDlg::initFXPage()
+{
+ QPixmap icon = KGlobal::iconLoader()->loadIcon("ksysguard", KIcon::Toolbar, KIcon::SizeMedium);
+ m_fxPage = addPage( i18n( "Audio FX" ), i18n("Effect Stack"), icon );
+ QVBoxLayout *fxLayout = new QVBoxLayout( m_fxPage, 0, spacingHint() );
+
+ FX_SetupImpl *fxDialog = new FX_SetupImpl(m_fxPage, "fxsetup", m_config, m_fxpluginhandler);
+ fxLayout->addWidget(fxDialog);
+ connect( this, SIGNAL(signalOKWasClicked()), fxDialog, SLOT(slotSaveWasClicked()) );
+ connect( this, SIGNAL(signalRemoveAllFX()), fxDialog, SLOT(slotRemoveAll()) );
+ connect( this, SIGNAL(signalReloadFX()), fxDialog, SLOT(slotReload()) );
+
+ // Disable/enable FX-Setup depending on TTS-libs capability
+ int status = m_kttslib->getStatus() & TTS::AUDIOFILE;
+ if ( status ){
+ m_fxPage->setEnabled(true);
+ } else {
+ m_fxPage->setEnabled(false);
+ emit signalRemoveAllFX();
+ }
+}
+
+
+void VoiceSetupDlg::slotPageChanged(QWidget *page)
+{
+ kdDebug(100200) << "+++ entering VoiceSetupDlg::slotPageChanged: " << page << endl;
+
+ if ( page != m_fxPage )
+ return;
+
+ int status = m_kttslib->getStatus() & TTS::AUDIOFILE;
+ if ( status ){
+ m_fxPage->setEnabled(true);
+ } else {
+ QString q = i18n("The active TTS system does not make use of aRts effects.");
+ KMessageBox::information( this, q, i18n("Plugin Configuration"), "KSayIt_Audiofile" );
+ m_fxPage->setEnabled(false);
+ }
+}
+
+
+void VoiceSetupDlg::slotOk()
+{
+ kdDebug(100200) << "+++ entering VoiceSetupDlg::slotOK()" << endl;
+
+ int status = m_kttslib->getStatus();
+ if ( (status & TTS::AUDIOFILE) == 0 ){
+ emit signalRemoveAllFX();
+ }
+
+ // Let all objects save their configuration
+ emit signalOKWasClicked();
+
+ // check if configuration was saved O.K.
+ if ( m_kttslib->saveWasClicked() ){
+ kdDebug(100200) << "--- leaving VoiceSetupDlg::slotOk" << endl;
+ QDialog::accept();
+ }
+}
+
+
+void VoiceSetupDlg::slotCancel()
+{
+ kdDebug(100200) << "VoiceSetupDlg::slotCancel()" << endl;
+ QDialog::reject();
+}
+
+#include "voicesetupdlg.moc"
diff --git a/ksayit/src/voicesetupdlg.h b/ksayit/src/voicesetupdlg.h
new file mode 100644
index 0000000..510c591
--- /dev/null
+++ b/ksayit/src/voicesetupdlg.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ voicesetupdlg.h - description
+ -------------------
+ begin : Son Nov 2 2003
+ copyright : (C) 2003 by Robert Vogl
+ email : voglrobe@saphir
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef VOICESETUPDLG_H
+#define VOICESETUPDLG_H
+
+// QT includes
+#include <qframe.h>
+
+// KDE includes
+#include <kdialogbase.h>
+#include <kconfig.h>
+
+// forward declaration
+class FXPluginHandler;
+class KTTSDLib;
+/**
+ *@author Robert Vogl
+ */
+class VoiceSetupDlg : public KDialogBase {
+ Q_OBJECT
+
+public:
+ VoiceSetupDlg(QWidget *parent=0, const char *name=0, const QString &caption=NULL,
+ bool modal=true,
+ KConfig *config=0,
+ FXPluginHandler *fxpluginhandler=0,
+ KTTSDLib *kttslib=0);
+
+ ~VoiceSetupDlg();
+
+signals:
+ /** Emitted when OK was cliecked;
+ */
+ void signalOKWasClicked();
+
+ /** Signals to remove all effects from the active list.
+ */
+ void signalRemoveAllFX();
+
+ /** Signals to relaod the last saved state.
+ */
+ void signalReloadFX();
+
+private: // Methods
+ /** Initializes the configuration page to setup the properties of
+ * of the TTS system.
+ */
+ void initVoicePage();
+
+ /** Initializes the configuration page to setup the effects.
+ */
+ void initFXPage();
+
+private slots:
+ /** Called when the Page changes.
+ */
+ void slotPageChanged(QWidget *page);
+
+ /** Reimplementation from base class.
+ */
+ void slotCancel();
+
+ /** Reimplementation from base class.
+ */
+ void slotOk();
+
+private:
+ KConfig *m_config;
+ FXPluginHandler *m_fxpluginhandler;
+ KTTSDLib *m_kttslib;
+ QFrame *m_fxPage;
+
+};
+
+#endif
diff --git a/kttsd/AUTHORS b/kttsd/AUTHORS
new file mode 100644
index 0000000..33193d5
--- /dev/null
+++ b/kttsd/AUTHORS
@@ -0,0 +1,5 @@
+José Pablo Ezequiel Fernández <pupeno@pupeno.com>
+Gary Cramblitt <garycramblitt@comcast.net>
+Gunnar Schmi Dt <gunnar@schmi-dt.de>
+Olaf Schmidt <ojschmidt@kde.org>
+Paul Giannaros <ceruleanblaze@gmail.com>
diff --git a/kttsd/ChangeLog b/kttsd/ChangeLog
new file mode 100644
index 0000000..549f975
--- /dev/null
+++ b/kttsd/ChangeLog
@@ -0,0 +1,609 @@
+2006-11-02 Gary Cramblitt (PhantomsDad)
+ * Add support for new Vietnamese voices to festivalintvoices file. Get them at http://sourceforge.net/projects/vietnamesevoice.
+
+2006-02-09 Gary Cramblitt (PhantomsDad)
+ * Use KDE_CHECK_{HEADER,LIB} instead of AC_CHECK_{HEADER,LIB} to locate alsalib.
+
+2006-02-07 Stephan Johach
+ * Fix translation of "Speak Text" in kate/ktextedit.
+
+2006-02-06 Gary Cramblitt (PhantomsDad)
+ * Bump version to 0.3.5.2.
+ * Fix BUG:121427 Translations sometimes not working due to incorrect catalog
+ insertion/removal.
+
+2006-01-20 ======== Release v0.3.5.1 with KDE 3.5.1
+
+2006-01-13 Gary Cramblitt (PhantomsDad)
+ * Fix BUG:120083 buffer length problem in Epos and Command plugin.
+ * Fix BUG:115795 Don't try to start the Epos server for every utterance.
+ * Epos server command changed from epos to eposd. Epos client command changed from
+ say to say-epos. These changes appeared around Epos v2.5.35. Enhance to try for these
+ automatically.
+
+2006-01-10 Gary Cramblitt (PhantomsDad)
+ * Bug fix. Pausing when popping up status in systray.
+ * Plug small memory leak.
+ * Allow user to specify custom ALSA device name.
+
+2006-01-09 Gary Cramblitt (PhantomsDad)
+ * Fix BUG:119753 Freezing when removing a speaking text job speaking on AlsaPlayer.
+ AlsaPlayer now uses non-blocking pcm open and polling.
+ * The ALSA device list pickable by user is now restricted to "default" and available
+ "plughw" devices.
+ * The following parameters may be placed in the [ALSAPlayer] section of
+ ~/.kde/share/config/kttsdrc:
+ PcmName=default (Any valid alsa pcm device, but your on your own. Examples:
+ dmix, hw:1,0)
+ DebugLevel=1 (0 = errors only; 1 = messages; 2 = verbose debug)
+ PeriodSize=128 (Number of frames in the ALSA buffer between interrupts.
+ If you have trouble, try adjusting up or down.)
+ Periods=8 (Same)
+ * If the ALSA pcm does not support pausing, simulates by not writing to the
+ pcm anymore, which will cause a slight delay, and underruns,
+ but that's the best we can do, I suppose.
+ * Fix bug. When starting KTTSMgr, it loaded the aRts plugin to determine if aRts is
+ available. But this started the aRts server and if user's machine does not have
+ proper audio sharing enabled, caused "device busy" errors. Now it starts the aRts
+ server only when playback begins the first time.
+ * Bump version from 0.3.5 to 0.3.5.1.
+
+2006-01-06 Gary Cramblitt (PhantomsDad)
+ * Fix BUG:118016 Not loading plugins when desktop language is not ISO-8859-1.
+
+2005-12-03 Jürgen Zdero
+ * Add German chat filter by Jürgen Zdero.
+
+2005-11-13 Gary Cramblitt (PhantomsDad)
+ * BUG:116031 Fix appendText method. Add version method to dcop interface.
+ This change did not make it into the KDE 3.5 release.
+
+2005-11-29 ======== Release v0.3.5 with KDE 3.5
+
+2005-10-16 J. Riddell
+ * Make install error. Install the Hadifix icons.
+
+2005-07-19 Gary Cramblitt (PhantomsDad)
+ * Name kept .wav files in format kttsd-jjjjjjjj-ssssssss.wav where jjjjjjjj is the job
+ number zero-filled to the left and ssssssss is the sentence sequence number zero-filled
+ to the left.
+
+2005-07-01 Gary Cramblitt (PhantomsDad)
+ * Since ALSA plugin seems to work pretty well, enable building --without-arts and build
+ ALSA plugin by default (if headers found).
+
+2005-06-25 Gary Cramblitt (PhantomsDad)
+ * The XML Transformer filter now applies itself when the root element OR doctype and appId match.
+
+2005-06-12 Gary Cramblitt (PhantomsDad)
+ * New aKode audio plugin. Build it with ./configure --enable-kttsd-akode.
+ There are a couple of problems. See README players/akodeplayer/README.
+ * Activate rich speak (XHTML to SSML) in Konqueror plugin. To speak richly,
+ you must configure the xhtml2ssml_simple XML Transformer plugin.
+
+2005-06-03 Gary Cramblitt (PhantomsDad)
+ * New ALSA audio plugin. Build it with ./configure --enable-kttsd-alsa for now.
+ * New Qt Rich Text to Plain Text filter by David Powell.
+
+2005-04-30 Gary Cramblitt (PhantomsDad)
+ * Change Current Sentence widget in Jobs tab to KTextEdit to avoid resizing when text does
+ not fit in box.
+ * HTML to SSML now working pretty well. Note that you must
+ 1. Have Festival 1.95 installed.
+ 2. Have rab_diphone voice installed.
+ 3. Have xsltproc installed.
+ 4. If you have Festival Talker configured, reconfigure it (Edit) so that it will detect
+ if you have rab_diphone voice installed. You must hit the Apply button.
+ 5. Enable XML Transformer filter and point it to xhtml2ssml_simple.xsl stylesheet.
+ 6. Right now, only speaks HTML from Konqi if you paste HTML from clipboard.
+ Speak button in Konqi not yet enabled until I get some confidence it is working well.
+
+2005-04-23 Gary Cramblitt (PhantomsDad)
+ * Break sentences longer than 600 characters into shorter sentences by changing comma to
+ period. This prevents Festival from droning on lower and lower in tone until it is
+ unintelligible or crashes.
+
+2005-04-22 Gary Cramblitt (PhantomsDad)
+ * If resumeText is called on a speaking job, do not restart it.
+
+2005-04-21 Gary Cramblitt (PhantomsDad)
+ * New Hungarian Hadifix (mbrola and txt2pho) voice available at
+ http://tkltrans.sourceforge.net/
+ Since Hungarian requires ISO 8859-2 character encoding, added encoding option to
+ Hadifix plugin. Also, Hadifix plugin auto-selects a voice matching the user's
+ chosen language.
+ * Abbreviate USA and UK country names to save space.
+ * Display male/female icons in Festival Interactive configuration dialog.
+ * Use new Select Talker dialog in Talker Chooser filter.
+
+2005-04-17 Gary Cramblitt (PhantomsDad)
+ * Actions to be taken on notifications may now be specified at three levels
+ Specific event of specific application
+ All other events of specific application
+ All other events
+ * When the last event of an application is deleted, delete the app from
+ Notifications list.
+
+2005-04-12 Gary Cramblitt (PhantomsDad)
+ * Enhanced notification options. Ability to customize each application event.
+ * Enhanced Talker chooser for notifications and Job Manager.
+ * Fix bug in Talker matching algorithm.
+
+2005-03-18 Gary Cramblitt (PhantomsDad)
+ * Added --systray cmdline option to KTTSMgr, which causes it to start minimized in system
+ tray.
+ * Added --autoexit cmdline option to KTTSMgr, which causes it to exit when no longer
+ speaking any text jobs.
+ * Added AutoStartManager and AutoExitManager options to config. These cause kttsd
+ to automatically start KTTSMgr when a text job starts, and automatically exit
+ KTTSMgr when all text jobs have finished speaking.
+
+2005-03-16 Gary Cramblitt (PhantomsDad)
+ * Bug fix. Interruption messages are spoken using the Talker of the interrupting message.
+ So if default Talker is en, and you do sayMessage "Guten Tag" "de", the "Text Interrupted.
+ Message" is spoken using German Talker. Interruption messages should speak using the
+ default Talker.
+
+2005-03-13 Gary Cramblitt (PhantomsDad)
+ * Bug. SBD Filter turned off by default. Not good!
+ * When running kttsd and no Talkers or Filters have been configured, automatically
+ attempt to configure them. Try to configure a Talker in the user's desktop language
+ and if that doesn't work, in English. Automatically configure the Standard
+ Sentence Boundary Detector.
+
+2005-03-12 Gary Cramblitt (PhantomsDad)
+ * Change toolbar buttons on Jobs tab to push buttons so they can be used from keyboard.
+ Clean up screen layout and add WhatsThis help.
+ * Added sayText convenience method to kspeech.h, which combines setText and startText
+ into a single call. Be sure to update kdelibs/interfaces/kspeech before attempting to
+ compile kttsd:
+ cd kdelibs/interfaces/kspeech
+ cvs up
+ make install
+ * When starting or restoring KTTSMgr, defaults to Jobs tab if visible.
+ * When clicking on Jobs tab, warn user if there are config changes not yet saved.
+
+2005-03-09 Gary Cramblitt (PhantomsDad)
+ * Add Hold and Resume items to systray menu.
+
+2005-03-06 Gary Cramblitt (PhantomsDad)
+ * Consolidated all the translation catalogues into single catalog called "kttsd".
+
+2005-03-05 Gary Cramblitt (PhantomsDad)
+ * Add support for Kiswahili, Zulu, and Ibibio Festival languages. Get them at
+ http://www.llsti.org/index.htm. Note that Ibibio does not have an assigned two-letter
+ (iso 639) code, so I gave it Zulu (zu), which is probably as bad as saying that English
+ is French, but it cannot be helped. The Ibibio and Zulu voices will only speak valid
+ Ibibio or Zulu text, so the Test button is non-functional for them until translators
+ provide translations.
+
+2005-03-02 Gary Cramblitt (PhantomsDad)
+ * BUG:100600 Fix for messages and warnings not spoken when text job is paused.
+ * Bug. Talker Chooser claims it can autoconfigure itself, but it cannot really.
+ * Allow to remove any Filter.
+
+2005-02-17 Gary Cramblitt (PhantomsDad)
+ * Remove festival/ and festivalcs/ plugins from source tree. AFAIK, these plugins don't work
+ and nobody is using them. And these are confusing packagers who think we have a build
+ dependency on Festival and Speech Tools libraries. Use festivalint/.
+
+2005-02-15 Gary Cramblitt (PhantomsDad)
+ * Translations now working.
+ * Include a copy of kdelibs/interfaces/kspeech in compat/ dir. This permits distribution
+ and compilation of KTTS for KDE less than 3.4.
+ * Support for Italian voices. Download from
+ http://www.csrf.pd.cnr.it/TTS/It-FESTIVAL-download.htm.
+ or http://mirko.lilik.it/Italian-FESTIVAL.zip
+
+2005-02-05 Gary Cramblitt (PhantomsDad)
+ * Version bumped to 0.3.0.
+ * Russian Festival voice added to voices file. Download voice from
+ http://nshmyrev.narod.ru/festival/festival.html. Must have Festival 1.95 beta or later.
+ Untar to festival/lib/voices/russian/ directory. Encoding must be one of the
+ single-byte cryllics, such as KOI8-R.
+ * Ability to load/save Talker Chooser and XML Transformer configurations.
+ * Some bug fixes related to Filters.
+
+2005-01-24 Gary Cramblitt (PhantomsDad)
+ * Add Talker Chooser Filter.
+ * Add option on Audio tab to preserve generated audio files by copying to user-specified
+ directory.
+
+2005-01-22 Gary Cramblitt (PhantomsDad)
+ * Allow filtering of notifications. (only setText and appendText are currently filtered.)
+ * Fix bug. Synchronous filters not being run.
+
+2005-01-21 Gary Cramblitt (PhantomsDad)
+ * Sentence Boundary Detector plugin now active. This means that SSML is parsed into
+ sentences and therefore can be rewound/advanced by sentence. It also means that
+ KTTS no longer crashes (taking KDE and X11 with it) on large HTML/SSML files.
+ * Filters can be applied based on the DCOP Application ID of app that queued the text
+ job.
+ * Filters can be applied based on language of Talker.
+ * StringReplacer filter can now load and save word lists to/from external file.
+ * Several other bug fixes.
+
+2005-01-13 Gary Cramblitt (PhantomsDad)
+ * FilterMgr class now implemented in kttsd, which means that filters now work. Well
+ almost. See TODO file for some nasty problems. (Hint: avoid large HTML/SSML pages!)
+ * Moved the TalkerCode matching and Talker plugins to TalkerMgr class so both
+ Speaker and SpeechData classes can access them.
+
+2005-01-09 Gary Cramblitt (PhantomsDad)
+ * Epos plugin defaults to ISO 8859-2 encoding. Pass encoded text to Epos client
+ via Stdin rather than command line to avoid encoding problem.
+ * Added encoding parameter to kspeech::setFile method. This allows for speaking a
+ file that is encoded different from global desktop default.
+
+2005-01-07 Gary Cramblitt (PhantomsDad)
+ * Start to Filters capability. StringReplacer Filter implemented in KTTSMgr GUI,
+ but not yet implemented in kttsd.
+
+2004-12-31 Gary Cramblitt (PhantomsDad)
+ * In KTTSD, if user has not yet configured any Talkers, prompt user and if they click
+ Yes, run KTTSMgr. User has option to turn off prompt.
+ * Activate kspeech::showDialog() method.
+ * The khmtlktts plugin automatically senses if KTTSD is installed and if not,
+ hides menu item.
+
+2004-12-30 Gary Cramblitt (PhantomsDad)
+ * Set LANG and LC_CTYPE environment variables before starting subprocess in Epos and
+ and Command plugins. Fix encoding bug in Epos plugin. Move common encoding routines
+ to PluginProc.
+
+2004-12-27 Gary Cramblitt (PhantomsDad)
+ * Add encoding option to Festival Interactive Plugin. When choosing a voice, default the
+ encoding option based on voices file.
+ * Add support for Polish Festival.
+
+2004-12-21 Gary Cramblitt (PhantomsDad)
+ * Require GStreamer 0.8.5 or above in configure.in.in. SuSE 9.2 users have
+ GStreamer 0.8.0, which causes KTTSMgr to immediately crash on startup.
+
+2004-12-20 Gary Cramblitt (PhantomsDad)
+ * kdenonbeta/kttsd moved to kdeaccessibility/kttsd.
+ * kdenonbeta/kttsd/libktts moved to kdelibs/interfaces/kspeech. libktts dropped.
+ * kdenonbeta/app-plugins/khtml-plugin moved to kdebase/konqueror/kttsplugin.
+ * kdenonbeta/app-plugins/kate-plugin moved to kdebase/kate/plugins/ktts.
+ * kdenonbeta/app-plugins/katepart-plugin moved to kdebase/kate/plugin/katepartktts.
+
+2004-12-19 Gary Cramblitt (PhantomsDad)
+ * Change Festival voices from ini to xml format. Permit translators to translate voice names.
+ * Add "--enable-kttsd-gstreamer" option to configure, defaulting to no.
+ Warn packagers not to distribute gstreamer in binary packages of kdeaccessibility as it
+ creates unwanted dependencies.
+
+2004-12-18 Gary Cramblitt (PhantomsDad)
+ * Remove kcmkttsmgr. Use kcmkttsd instead.
+
+2004-12-14 Gary Cramblitt (PhantomsDad)
+ * Under KDE 3.2, FestivalInt plugin automatically finding /usr/share/festival, rather
+ than /usr/bin/festival.
+
+2004-12-12 Release 0.2.0. First public release.
+
+2004-12-09 Gary Cramblitt (PhantomsDad)
+ * Require GStreamer >= 0.8.7.
+ * Bug. Always using default GStreamer sink in KTTSD. Honor user's choice now.
+
+2004-12-07 Gary Cramblitt (PhantomsDad)
+ * Add Festival Czech voice.
+ * Apply some Juk patches to GStreamerPlayer.
+
+2004-12-06 Gary Cramblitt (PhantomsDad)
+ * Initial, but primitive support for SSML with Hadifix.
+
+2004-12-03 Gary Cramblitt (PhantomsDad)
+ * Audio players are now plugins. This permits distribution of binary packages
+ without GStreamer being a mandatory dependency.
+
+2004-12-02 Gary Cramblitt (PhantomsDad)
+ * Bypass stretching (overall Speed setting) when utterance contains SSML. sox
+ mangles SSML pitch settings.
+
+2004-12-01 Gary Cramblitt (PhantomsDad)
+ * Some code reorganization. New TalkerCode object in libkttsd.
+ * Better Talker selection dialog when changing Talker in Jobs tab.
+
+2004-11-29 Gary Cramblitt (PhantomsDad)
+ * When clicking Test button, now honors users output method (arts or gstreamer) and
+ overall Audio Speed setting.
+ * Add option for GStreamer output sink.
+
+2004-11-27 Gary Cramblitt (PhantomsDad)
+ * Extremely rudimentary support for SSML/Sable using FestivalInt plugin. If it works for
+ you, it will be minor miracle.
+ * In FestivalInt configuration dialog, do not enable OK button if EXE Path is invalid.
+ * When Editing existing FestivalInt configuration, do not inadvertently change the selected
+ voice when rescanning.
+ * In FestivalInt configuration dialog, disable voice combo box until scan has been clicked.
+
+2004-11-26 Gary Cramblitt (PhantomsDad)
+ * Slight throughput improvement by eliminating pause at start of each Festival utterance.
+ * Bug fix. Can find synthesizers when HOME env variable is in the path.
+
+2004-11-25 Gary Cramblitt (PhantomsDad)
+ * Add Finnish Male voice (http://www.ling.helsinki.fi/suopuhe/download/)
+ * Improve throughput slightly by emitting Text Started signal after playback has begun.
+
+2004-11-24 Gary Cramblitt (PhantomsDad)
+ * Add overall Speed control to KTTSMgr Audio tab. This permits to speed up speech
+ even if the synth does not support it. Must have sox installed for this to work.
+ * Add Speed and Pitch controls to Epos plugin. Also set language.
+ * Better Speed adjustment for HTS voices.
+
+2004-11-23 Gary Cramblitt (PhantomsDad)
+ * Add support for OGI English and Spanish voices.
+ * Update Handbook.
+ * Better Spanish translations for voice names.
+
+2004-11-22 Gary Cramblitt (PhantomsDad)
+ * Add support for IMS German Festival.
+ * Update Handbook.
+
+2004-11-21 Gary Cramblitt (PhantomsDad)
+ * Add volume control to Festival Interactive.
+ * Accelerators for Festival Interactive configuration dialog.
+ * HTS voices only support Volume (not Speed or Pitch)
+ * Talker Codes reflect volume setting.
+
+2004-11-20 Gary Cramblitt (PhantomsDad)
+ * Add pitch control to Festival Interactive.
+ * GStreamer plugin.
+
+2004-11-17 Gary Cramblitt (PhantomsDad)
+ * Bug fix. Hosed Talker in KTTSMgr after removing a Talker and clicking Cancel.
+ * In KTTSMgr no longer record LastTalkerID in config file; compute at load time instead.
+ * Change Talker tab in KTTSMgr to "standard" layout.
+ * Bug fix. Talker matching. Tended to pick last talker no matter what.
+
+2004-11-13 Gary Cramblitt (PhantomsDad)
+ * Fix. Nothing happens when clicking Configure button for Festival Interactive
+ plugin if your desktop language is not English. Display translated name for
+ Synthesizer in Talkers tab.
+ * Display translated words for "male", "female", "neutral", "fast", "slow", "medium",
+ "loud", "soft" in KTTSMgr Talkers list and from Jobs "Change Talker" button.
+ * getTalkers() not returning country code as part of Talker Code.
+ * The Command plugin configuration dialog should enable OK button if %t or %f
+ appear in command, or "Send data via stdin" is checked. Also uncheck this option
+ by default in order for plugin to sense proper configuration.
+ * Add Jorge Luis Arzola to credits as tester.
+
+2004-11-11 Gary Cramblitt (PhantomsDad)
+ * Support for Festival 2.0. and Festival MultiSyn voices in FestivalInt plugin.
+ * Query Festival for available voices, rather than scanning for directories.
+ * Support for multiple versions of Festival executable. Now asks for EXE path rather
+ than voices path.
+ * Allow preload of Festival voices that take a long time to load.
+ If set, Festival is started when KTTSD starts and the voice is loaded.
+ * When stopText() is called and FestivalInt plugin is synthing (not saying) using
+ a pre-loaded voice, instead of killing Festival, which would cost hugely in
+ re-startup time, Festival is allowed to finish synthing and result is discarded.
+ This improves performance when rewinding/fastforwarding.
+ * Corrected FestivalInt voices file as to voice descriptions and languages.
+ Added MultiSyn voices.
+ * Added accelerators and WhatsThis help to FestivalInt, Command, Epos, Flite, and Hadifix
+ configuration dialogs.
+ * Added modal, cancelable, progress dialog while Testing in FestivalInt, Command, Epos,
+ Flite, FreeTTS, and Hadifix configuration dialogs.
+ This prevents a crash when user clicks OK or Cancel before test has completed.
+ * Command plugin always displays configuration dialog when added, i.e., never
+ autoconfigs.
+ * Speed adjustment disabled when using MultiSyn Festival voices.
+ * Allow KTTSMgr screen to be resized to minimum size. Allow splitter to resize jobs
+ ListView to minimum vertical size.
+ * No longer attempt to build Festival plugin (static linking to Festival/Speech Tools
+ libaries). User must explicitly request via ./configure --enable-kttsd-festival.
+ Code is woefully behind, I cannot get it to work, and probably wouldn't work
+ anymore even if I could get it to link and get past crash on first call to library.
+ FestivalInt seems to work just fine..grc.
+
+2004-11-10 Paul Giannaros (Cerulean)
+ * getTalkerCodes() returning corrupted talker codes.
+
+2004-11-04 Gary Cramblitt (PhantomsDad)
+ * Add English languages to FreeTTS desktop file so they show up in Add Talker dialog.
+ * When starting kttsmgr, if no Talkers are configured, default to Talker page.
+ * In kttsmgr, uncheck and disable Enable TTS checkbox until at least one Talker
+ has been configured. Once at least one Talker is added, enable the checkbox.
+ If all Talkers are removed, uncheck and disable the box and stop KTTSD.
+ * Give kttsmgr window an icon.
+ * Add option to embed KTTSMgr in the system tray.
+
+2004-11-03 Gary Cramblitt (PhantomsDad)
+ * Add ability to configure more than one plugin for a language, but with different
+ voices. Call them "talkers".
+ * Improve language selection and management in the KTTSD's configuration. Languages
+ added shouldn't be shown in the list of languages to add. Default languages should
+ show only the current languages. Languages should be shown as names and not codes.
+ Languages should be erased from the default language combo box. If a plugin does
+ not support a language, it should not be choosable.
+ * Add support for moving a text job to a different talker (language/plugin).
+ * Standarize the .desktop files
+
+2004-10-20 Gary Cramblitt (PhantomsDad)
+ * kcm_kttsmgr and kcm_kttsd are now identical libraries/KCModules.
+ Applications should use kcm_kttsd. When all apps have stopped
+ using kcm_kttsmgr, remove it.
+
+2004-10-19 Gary Cramblitt (PhantomsDad)
+ * The following installed files were renamed
+ on or about 19 Oct 2004:
+ In $KDEDIR/share/services/:
+ festival.desktop -> kttsd_festivalplugin.desktop
+ festivalint.desktop -> kttsd_festivalintplugin.desktop
+ command.desktop -> kttsd_commandplugin.desktop
+ hadifix.desktop -> kttsd_hadifixplugin.desktop
+ flite.desktop -> kttsd_fliteplugin.desktop
+ epos-kttsdplugin.desktop -> kttsd_eposplugin.desktop
+ freetts.desktop -> kttsd_freettsplugin.desktop
+ In $KDEDIR/lib/kde3/:
+ libfestivalplugin -> libkttsd_festivalplugin
+ libfestivalintplugin -> libkttsd_festivalintplugin
+ libcommandplugin -> libkttsd_commandplugin
+ libhadifixplugin -> libkttsd_hadifixplugin
+ libfliteplugin -> libkttsd_fliteplugin
+ libeposkttsdplugin -> libkttsd_eposplugin
+ libfreettsplugin -> libkttsd_freettsplugin
+
+ Rename libkttsjobmgr to libkttsjobmgrpart per kdelibs/NAMING convention.
+
+ There is a new shell script, clean_obsolete.sh that will remove these
+ obsolete files from your system.
+
+2004-10-14 Gary Cramblitt (PhantomsDad)
+ * Fix crash when clicking Cancel to prompt for Other language code, or user
+ enters an invalid language code.
+
+2004-10-13 Gary Cramblitt (PhantomsDad)
+ * libktts is now a versioned shared library. You may need to remove the
+ unversioned library, ie.
+ rm $KDEDIR/lib/libktts.*
+
+2004-10-13 Gary Cramblitt (PhantomsDad)
+ * Revert previous change. Sorry.
+
+2004-10-13 Gary Cramblitt (PhantomsDad)
+ * Remove versioning from libkttsd.
+ NOTE: After rebuilding and installing, you will want to delete
+ the following file:
+ $KDEDIR/lib/libkttsd.so.1.0.0
+
+2004-10-12 Gary Cramblitt (PhantomsDad)
+ * Added Handbook.
+ * Help button and system tray content menu display Handbook.
+
+2004-09-07 Gary Cramblitt (PhantomsDad)
+ * Added 6 new HTS voices for Festival and FestivalInt plugins.
+ Courtesy of "N.Cat" Triskelios.
+ Download the voices from http://hts.ics.nitech.ac.jp/
+
+2004-09-04 Gary Cramblitt (PhantomsDad)
+ * Rename Hadifax to Hadifix.
+ NOTE: After rebuilding and installing, you will want to delete the
+ following files:
+ $KDEDIR/lib/kde3/libhadifaxplugin.la
+ $KDEDIR/lib/kde3/libhadifaxplugin.so
+ $KDEDIR/share/services/hadifax.desktop
+
+2004-09-02 Paul Giannaros
+ * FreeTTS plugin.
+
+2004-08-28 Gary Cramblitt (PhantomsDad)
+ * GStreamer player added. Doesn't work right now because gstreamer 0.6
+ has issues with wav files. Try again when KDE bindings (gst) have been
+ updated to gstreamer 0.8.
+ * If jobNum parameter in dcop calls is 0, default to last job queued by the
+ application, or if no such job, the current job (instead of last job).
+ * After call to stopText, if there more speakable jobs in the queue, they begin
+ speaking.
+ * Emit textPaused and textStopped signals as documented.
+ * Fix bug in festivalint plugin. Hangs sometimes with short utterances caused
+ by writing to Stdin before Stdin buffer is empty.
+ * Better sentence parsing.
+ * Minor fixes to kttsjobmgrpart.
+
+2004-08-09 Gary Cramblitt (PhantomsDad)
+ * Remove requirement to copy pluginconf.h to $KDEDIR/include when running designer
+ against plugin configuration widgets.
+ * Epos plugin not listing codecs.
+ * Some plugins listing codecs multiple times.
+ * Select and ensure default language visible when first displaying kttsmgr.
+ * Auto select and prepare Properties tab when adding a new language in kttsmgr.
+
+2004-08-08 Gary Cramblitt (PhantomsDad)
+ * Add plugin for Epos TTS Synthesis System (czech and slovak).
+
+2004-08-07 Gary Cramblitt (PhantomsDad)
+ * Existing release marked with tag ktts-0-1.
+ * New version of KTTS is 0.2.
+ * Many changes to KTTSD and the KTTSD plugins.
+ * QThreads have been mostly eliminated, which were causing anomalies.
+ * See libkttsd/pluginproc.h for the new plugin API. The new API is backwards
+ compatible to the old API.
+ * Plugins now perform synthesis separate from audibilizing, but they may do
+ both if needed. If a plugin supports separate synthesis, it returns True
+ in supportsSynth() method.
+ * If a plugin supports separate synthesis, KTTSD sends the synthesized audio file
+ to aRts for playback. The playback code has been designed with future
+ alternate playback plugins in mind, example gstreamer. (The code was adapted
+ from Juk with minor changes.)
+ * Plugins may work asynchronously, provide status via state() method and emit
+ signals when an operation has completed. If a plugin supports asynchronous
+ operation, it returns True in supportsAsync() method.
+ * If a plugin does not support asynchronous operation, it is wrapped in a QThread,
+ which is the same as before. See threadedplugin.h/cpp.
+ * Because playback is separate from synthesis and plugins work asynchronously,
+ pauseText or stopText _immediately_ pause or stop playback in mid-sentence.
+ * New plugin, flite, added for direct support of Festival Lite.
+ * The festivalint, command, and hadifax plugins were rewritten to support
+ these new capabilities.
+ * Need someone to rework the freetts plugin. I don't have JVM.
+ * Each plugin (except festival and freetts) now has a "Test" button on the
+ configuration dialog.
+ * The option to play a sound on text interruption now works.
+
+2004-07-10 Gary Cramblitt (PhantomsDad)
+ * Warn user if festival not installed.
+ * Install voices data file for festival interactive plugin even if
+ festival plugin not installed.
+
+2004-06-05 Gary Cramblitt (PhantomsDad)
+ * Draft KDE Text-to-Speech API Draft 3.
+ * Removed concept of paragraphs.
+ * Added concept of text job parts.
+ * Added sayScreenReaderOutput method.
+ * Replaced nextSenText, prevSenText, nextParText, prevParText with moveRelTextSentence.
+ * Added jumpToTextPart.
+ * Removed paragraph settings from configuration dialog.
+
+2004-05-31 Gary Cramblitt (PhantomsDad)
+ * Move speaking of notifications to KTTSD and persist notify settings.
+ * Clean up kcmkttsmgr.desktop and install to correct place.
+
+2004-05-23 Gary Cramblitt (PhantomsDad)
+ * Add option to speak KNotify notifications.
+
+2004-05-22 Gary Cramblitt (PhantomsDad)
+ * Change menu item to "Speak Text" on the Tools menu in app-plugins. Also start KTTSD if it is
+ not running.
+
+2004-05-21 Gary Cramblitt (PhantomsDad)
+ * Bug fix. Upon startup of kttsmgr, Remove button and Properties tab not enabled despite
+ default language selected.
+
+2004-05-19 Gary Cramblitt (PhantomsDad)
+ * Allow kttsmgr screen to be resized as narrow as possible.
+ * Correct some mispellings.
+ * When calling reinit() pauseText only if isSpeakingText().
+
+2004-05-18 Gary Cramblitt (PhantomsDad)
+ * Reinit() without losing existing queued text jobs, messages, or warnings.
+ * When kttsd restarts because of reinit(), job manager part refreshes list.
+
+2004-05-17 Gary Cramblitt (PhantomsDad)
+ * Fix hang when calling reinit() while speaking.
+
+2004-05-15 Gary Cramblitt (PhantomsDad)
+ * Lots of changes:
+ * Defined the KDE Text-to-speech API. See /libktts/kspeech.h.
+ * Moved all the GUI stuff out of KTTSD into kttsmgr. KTTSD is a pure non-GUI deamon now.
+ * Added text job manager as a KPart (kttsjobmgr) for GUI interface.
+ * Replaced existing configuration manager (kcmkttsd) with kcmkttsmgr, which includes kttsjobmgr.
+ * Fixed several typos and minor bugs.
+ * Fixed Kate and KHTML Plugins.
+ * Updated README, TODO and this file.
+ *
+ * IMPORTANT note to developers using KTTSD: The startText, stopText, resumeText DCOP
+ * methods now take a jobNum argument, which you can code as 0 to operate against the last text
+ * job your app queued. See /plugins/kate-plugin/katekttsd.cpp for example, or /libktts/kspeech.h.
+
+2002-11-21 Pupeno <pupeno@pupeno.com>
+ * Full port to the new architecture finished. Some fine tunning still needed.
+
+2002-09-25 Pupeno <pupeno@pupeno.com>
+ * Festival Cliente/Server plug in added. Festival plug in was added initially in the
+ project. FreeTTS never was meant to work yet.
+
+2002-07-28 Pupeno <pupeno@pupeno.com>
+ * ChangeLog created.
diff --git a/kttsd/Makefile.am b/kttsd/Makefile.am
new file mode 100644
index 0000000..5a54368
--- /dev/null
+++ b/kttsd/Makefile.am
@@ -0,0 +1,19 @@
+# The build order must be libktts, then libkttsd, then the rest.
+SUBDIRS = \
+ compat \
+ libkttsd \
+ players \
+ plugins \
+ filters \
+ kttsd \
+ kttsjobmgr \
+ kcmkttsmgr \
+ kttsmgr \
+ app-plugins \
+ icons
+
+messages: rc.cpp
+ $(EXTRACTRC) */*.rc */*/*.rc >> rc.cpp
+ $(EXTRACTRC) */*.ui */*/*.ui >> rc.cpp
+ $(EXTRACTRC) --tag=name --context=FestivalVoiceName plugins/festivalint/voices >> rc.cpp
+ $(XGETTEXT) rc.cpp */*.cpp */*.h */*/*.cpp */*/*.h -o $(podir)/kttsd.pot
diff --git a/kttsd/README b/kttsd/README
new file mode 100644
index 0000000..7906f4f
--- /dev/null
+++ b/kttsd/README
@@ -0,0 +1,166 @@
+KTTS -- KDE Text-to-Speech -- is a subsystem within the KDE desktop
+for conversion of text to audible speech. KTTS is currently under
+development and aims to become the standard subsystem for all KDE
+applications to provide speech output. Currently, KTTS consists of
+the following components:
+
+KTTSD
+ The KDE Text-to-Speech Deamon, a non-gui application that runs in
+the background, providing TTS support to KDE applications. Applications
+initiate TTS by making DCOP calls to kttsd.
+
+KTTSMGR
+ An application for configuring the KTTS System and for managing in-progress
+speech jobs. kttsmgr provides an icon in the system tray for performing
+these functions as needed.
+
+kttsjobmgr
+ A KPart for managing in-progress speech jobs.
+
+kcmkttsd
+ A KControl module for configuring the KTTS System. kcmkttsd runs in the
+KDE Control Center or start it with the command "kcmshell kcmkttsd".
+
+ktexteditor_kttsd
+ A plugin for the KDE Advanced Text Editor that permits you to speak an entire
+text file or any portion of a file.
+
+khmtl-plugin
+ A plugin for Konqueror that permits you to speak all or any portion of an
+HTML web page. (Note: this component is in kdebase/konqueror/kttsplugin)
+
+Original Author: Jos Pablo Ezequiel "Pupeno" Fernndez <pupeno@kde.org>
+Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+Contributors:
+ Olaf Schmidt <ojschmidt@kde.org>
+ Gunnar Schmi Dt <gunnar@schmi-dt.de>
+ Paul Giannaros <ceruleanblaze@gmail.com>
+ Jorge Luis Arzola <arzolacub@hotmail.com>
+ David Powell <achiestdragon@gmail.com>
+
+User features:
+ * Speak contents of a text file.
+ * Speak KDE notification events (KNotify).
+ * Speak all or part of the text of a web page in Konqueror.
+ * Speak all or part of the text in Kate text editor, including
+ instances where Kate is embedded in another KDE application.
+ * Long text is parsed into sentences. User may backup by sentence
+ or paragraph, replay, pause, and stop playing.
+ * Filter plugins for converting chat emoticons to speakable words,
+ fix mispronunciations, and convert xhtml to SSML.
+ * Audio output via aRts, ALSA, GStreamer (version 0.8.7 or later),
+ or aKode.
+
+Programmer features:
+ * Priority system for screen reader outputs, warnings and messages,
+ while still playing regular texts.
+ * Plugin-based architecture for support of a wide variety of speech
+ synthesis engines and drivers.
+ * Permit generation of speech from the command line (or via shell scripts)
+ using the KDE DCOP utilities.
+ * Provide a lightweight and easily usable interface for applications
+ to generate speech output.
+ * Applications need not be concerned about contention over the speech device.
+ * FUTURE: Provide support for speech markup languages, such as VoiceXML, Sable,
+ Java Speech Markup Language (JSML), and Speech Markup Meta-language (SMML).
+ * FUTURE: Provide limited support for embedded speech markers.
+ * Asynchronous to prevent system blocking.
+
+Requirements
+------------
+KDE 3.2 or greater and a speech synthesis engine, such as Festival. Festival
+can be obtained from http://www.cstr.ed.ac.uk/projects/festival/. Festival
+is distributed with most Linux distros. Check your distro CDs. Also works
+with Hadifix, Epos, Festival Lite (flite), FreeTTS, or any command that can
+speak text.
+
+Optional Components
+-------------------
+ * The sox utility is needed for adjusting overall speech rate.
+ * The xsltproc utility is needed for SSML support.
+ * GStreamer 0.8.7 or greater.
+
+See the KTTS Handbook
+
+ (http://accessibility.kde.org/developer/kttsd/handbook/index.html)
+
+for complete instructions on installing, compiling, configuring, and using
+KTTS.
+
+Audio Plugins
+-------------
+KTTS can be built with the following audio plugins. The "Default Configure
+"Option" column shows the default option for the configure command.
+The "Alternate" column gives the opposite configure option:
+
+ System Plugin Default Configure Option Alternate
+ ------ ------------ ------------------------- ------------------------
+ aRts artsplayer --with-arts --without-arts
+ ALSA alsaplayer --with-alsa=check --with-alsa=no
+ GStreamer gstplayer --with-gstreamer=no --with-gstreamer=check
+ aKode akodeplayer --with-akode=no --with-akode=check
+
+You *must* have at least one of these plugins for KTTS to work.
+
+The aKode and GStreamer players are not built by default because they have issues
+with instant stopping and starting.
+
+Packager Notes
+--------------
+The following speech synthesizer plugins are all built by default.
+Some of them are runtime only dependent upon non-free software.
+(Non-free according to Debian Policy). The "Configure Option to
+not build" column shows the configure command to not build the plugin:
+
+ Synth License Configure Option to not build
+ ------------- -------- -----------------------------
+ Festival free --disable-kttsd-festivalint
+ Festival Lite free --disable-kttsd-flite
+ Epos free --disable-kttsd-epos
+ Command free --disable-kttsd-command
+ Hadifix non-free --disable-kttsd-hadifix
+ FreeTTS non-free --disable-kttsd-freetts
+
+IMPORTANT NOTE TO BINARY PACKAGERS:
+Please do not distribute binary packages of kdeaccessibility with the
+gstreamer plugin, as this creates unwanted dependencies. Instead,
+distribute the gstreamer plugin in a separate package, e.g.
+kde-accessibility-extras. The separate package should require
+gstreamer >= 0.8.7. Thank you.
+
+Support
+-------
+The KTTS website is
+
+ http://accessibility.kde.org/developer/kttsd
+
+In addition to the KDE Bugzilla database (bugs.kde.org), discussions for KTTSD
+currently take place in the kde-accessibility mailing list. Subscribe at
+https://mail.kde.org/mailman/listinfo/kde-accessibility. Developers
+also hang out in IRC (irc.kde.org channel #kde-accessibility).
+
+Directories
+-----------
+libktts Library for applications desiring to speak text. This must be built first.
+libkttsd Library for KTTSD. Defines the interface for plugins for KTTSD. Must be built second.
+players Audio plugins for KTTSD.
+ artsplayer aRts audio plugin for KTTSD.
+ gstplayer GStreamer audio plugin for KTTSD.
+ alsaplayer ALSA audio plugin for KTTSD.
+ akodeplayer aKode audio plugin for KTTSD.
+plugins Plugins for KTTSD. You must have at least one plugin to use KTTSD.
+ festivalint Plugin for Festival using Festival Interactive mode (festival --interactive).
+ flite Plugin for Festival Lite.
+ hadifix Plugin for Hadifix.
+ freetts Plugin for FreeTTS.
+ epos Plugin for Epos.
+ command Generic command plugin.
+kttsd KTTSD itself. Non-interactive deamon.
+icons Icon for kttsmgr and KTTSD.
+kttsjobmgr A KPart used by kcmkttsmgr for managing text jobs in KTTSD.
+kcmkttsmgr A KControl module for managing KTTSD. Run using "kcmshell kcmkttsd".
+kttsmgr Application for managing KTTSD. Wrapper for kcmkttsmgr plus a system tray icon.
+app-plugins Plugins for other applications to speak text.
+ kate Embedded Kate plugin.
+compat Copy of kdelibs/interfaces/kspeech. Used when compiling for KDE less than 3.4.
+debian Debian packaging files. (possibly way out of date)
diff --git a/kttsd/README.kttsd b/kttsd/README.kttsd
new file mode 100644
index 0000000..2fe8d51
--- /dev/null
+++ b/kttsd/README.kttsd
@@ -0,0 +1,10 @@
+Where is KTTSD?
+
+KTTSD was moved on 20 Dec 2004.
+Most of it has moved to kdeaccessibility/kttsd.
+The following pieces were also moved.
+
+kttsd/libktts -> kdelibs/interfaces/kspeech
+kttsd/app-plugins/khtml-plugin -> kdebase/konqueror/kttsplugin
+kttsd/app-plugins/kate-plugin -> kdebase/kate/plugins/ktts
+kttsd/app-plugins/katepart-plugin -> kdebase/kate/plugin/katepartktts
diff --git a/kttsd/TODO b/kttsd/TODO
new file mode 100644
index 0000000..27ef1a3
--- /dev/null
+++ b/kttsd/TODO
@@ -0,0 +1,95 @@
+_ Filters:
+ _ XHTMLtoSSML stylesheet needs work to provide better mappings for most web pages.
+ _ Add KNewStuff capability for folks to upload/download filter configs.
+ _ There should be a default set of filters configured when user first runs KTTSMgr.
+ If user presses Default button, it should ask user whether to replace all existing
+ filters with the standard set. The standard set should probably include
+ the Qt to Plain Text and Fix Festival Unspeakable Characters filters, but I'm not
+ sure about the latter when desktop is not ISO 8859-1.
+ _ The SBD Filter configuration dialog can be shrunk smaller than the widgets on it.
+ This apparently due to a bug in the QLabel widget when it contains RichText. If
+ forced to plain text, the problem won't happen (I am told). However, the WARNING
+ in the dialog needs to be bolded. What to do?
+_ Handbook:
+ _ Mention that "Root element is" and "DOCTYPE" are case sensitive. "html" is not
+ the same as "HTML". It should stay this way, BTW. Proper xhtml requires lowercase
+ tags.
+_ Audio Plugins:
+ _ Audio Plugins are loaded for each sentence. Instead, reuse the plugins from a pool
+ of loaded plugins.
+ _ BUG:116542. Apply patch and resolve compile issue.
+ _ At least one user experiences a freeze-up using ALSA plugin. Speak a web page,
+ pause the page, cause a knotify to speak, kttsd freezes. This appears to be an
+ ALSA device contention problem? In this situation, there are two alsaplayer objects;
+ one in pause state, and one attempting to speak notify.
+ _ akodelib does not stop instantly when pause() or stop() is called. See bug:107135.
+ _ Why must Player constructor take a 3rd "args" argument, while PluginProc constructor
+ does not. They are essentially the same. ??
+ _ Add option to automatically turn down music player volume while speaking (via dcop).
+_ Festival Interactive plugin:
+ _ Need someone who can read czech to try integrating this into KTTS:
+ http://www.freebsoft.org/festival-czech
+ _ New Italian voice for Festival. http://www.pd.istc.cnr.it/FESTIVAL/home/default.htm
+_ EPOS plugin:
+_ Command plugin:
+ _ Command plugin encodes text on command line using %t in user's chosen encoding, but
+ if this differs from user's desktop default encoding, doesn't work. KProcess always
+ encodes command line stuff using user's default encoding. There is no point, therefore,
+ in attempting to encode it differently, just mangles the text even more. Short of modifying
+ KProcess, I see no way around this. But perhaps a warning to user advising to use %f instead?
+ _ Command plugin crashes when using command 'flite -t "%t"' and flite can't get write access to /dev/dsp*.
+_ Hadifix plugin:
+ _ BUG:116151 Add options for using the new prepoc capability in Hadifix.
+ _ When stopText() is called, and Hadifix process is killed, the temporary wav file is not deleted,
+ despite QFile::remove call. Possibly still locked by exiting mbrola process? This only seems
+ to happen in the configuration dialog when canceling Tests.
+_ KTTSMgr:
+ _ Give Talkers a Talker Name entered by user. Show this name in Jobs tab, Change Talker screen,
+ and in systray menu.
+ _ Change the Current Sentence panel to show the current sentence of the selected job? If selected
+ job is not the currently speaking job, won't show currently-speaking text anymore. However, would
+ be helpful when using advance/rewind buttons. Perhaps to be effective, if the currently-selected
+ job IS the currently speaking job, and that job finishes, would automatically select the next
+ speaking job? But that could become confusing for users with selection jumping around.
+ _ Add ability to quickly pick default Talker in systray menu.
+ _ KCMultiDialog has a bug that won't allow sizing the screen narrower than 640.
+ _ Overall Audio Speed should be a realtime setting, i.e., not necessary to click Apply.
+ _ Disable Audio Speed control if sox not installed (configure.in.in but runtime check would be better).
+ _ Add drag N drop for the Talkers so it is easier to change the ordering.
+ _ It is possible to configure multiple instances of Talkers with the exact same configuration.
+ _ In kcmkttsmgr, use setHelp() to set help anchor based on current tab.
+ _ Add playback controls to kttsmgr. Volume, pause. Maybe rewind?
+_ KTTSD:
+ _ I am told that when kttsd crashes, it can take knotify down with it. See about
+ "disconnecting" knotify from kttsd (using post to Qt event queue).
+ _ Strange msg being produced by KIO::move, but it works fine. ??
+ kio (KIOJob): stat file:///home/kde-devel/.kde/share/apps/kttsd/audio/kttsd-5-1.wav
+ kio (KIOJob): error 11 /home/kde-devel/.kde/share/apps/kttsd/audio/kttsd-5-1.wav
+ kio (KIOJob): This seems to be a suitable case for trying to rename before stat+[list+]copy+del
+ _ While kttsd currently configures a Talker automatically, would be nice if it could
+ autoconfigure talkers for each requested language, if one has not already been configured.
+ _ Add support for speech markers.
+ _ Implement error signal handling in KTTSD.
+ _ Add support for JSML and other Speech Markup languages.
+ _ Add method for apps to play a sound file, including in the middle of a job.
+ Could be done with SSML or with special Talker Code = "sound".
+_ Other/General:
+ _ As pointed out by NOKUBI Takatsugu on Planet Debian, there exists an
+ open-source synthesis + recognition engine for Japanese.
+ http://aniki.daionet.gr.jp/~knok/blog/blosxom.cgi/2005/11/24
+ http://hil.t.u-tokyo.ac.jp/~galatea/index.html
+ _ Save buttons should confirm if user chooses an existing file. KFileDialog doesn't seem to
+ offer this option, but shouldn't it?
+ _ .desktop files must have a Type keyword, but what to use for kcmkttsd_testmessage.desktop?
+ _ Add option to kill plugin process when no longer needed so that memory can be recovered.
+ Or maybe some sort of "nice" setting so that process will be swapped out when no longer needed.
+ _ Convert to KConfig XT.
+ _ Add a plugin for TuxTalk, http://tuxtalk.sourceforge.net/. Since it only supports
+ English (at the moment) and is alpha, don't think it is worth it now.
+ _ Add a plugin for dhvani, an Indian and Hindi TTS engine, http://dhvani.sourceforge.net/
+ Currently written in c, but it looks like future versions will require Java VM.
+ Main problem at the moment is that dhvani sends audio directly to /dev/dsp with no option
+ to send to a wav file.
+ _ IBM ViaVoice plugin? IBM TTS is a proprietary runtime product with opensource API.
+ http://ibmtts-sdk.sourceforge.net/
+ _ Add KTTS plugin to aKregator.
diff --git a/kttsd/TODO.french b/kttsd/TODO.french
new file mode 100644
index 0000000..32372c3
--- /dev/null
+++ b/kttsd/TODO.french
@@ -0,0 +1,31 @@
+The <a href="http://accessibility.kde.org/developer/kttsd/index.php">KDE Text-to-Speech System</a> currently supports the following languages via non-commercial TTS systems and voices on the Linux platform:
+
+American English
+British
+Spanish
+German
+Finnish
+Czech
+Polish
+Russian
+Italian
+Kiswahili
+Zulu
+Ibibio
+
+Notably absent from this list is French (French Canadian voices can be purchased from <a href="http://www.cepstral.com">Cepstral LLC</a>). This is a damn shame.
+
+If you are French speaking, your mission, should you choose to accept it, is to develop a free and easy-to-install French language package for KTTS on the Linux platform. There are several possible ways this could be done:
+
+1. MBROLA and txt2pho. This solution uses MBROLA to synthesize voice from phonemes. What's needed is a means to convert text into phonemes. There are French voices available for MBROLA at <a href="http://tcts.fpms.ac.be/synthesis/mbrola/mbrcopybin.html">http://tcts.fpms.ac.be/synthesis/mbrola/mbrcopybin.html</a>. There are txt2pho utilities and other TTS systems available at <a href="http://tcts.fpms.ac.be/synthesis/mbrola/mbrtts.html">http://tcts.fpms.ac.be/synthesis/mbrola/mbrtts.html</a>. I tried these without success. In some cases, the txt2pho programs fussed about "little endian", so this might require some perl programming. If you get a solution working this way, it would employ the Hadifix plugin in KTTS.
+
+2. MBROLA and Festival. Like #1, this solution uses MBROLA to synthesize voice from phonemes, but uses Festival to do the text to phoneme conversion. More info at <a href="http://www.cstr.ed.ac.uk/projects/festival/mbrola.html">http://www.cstr.ed.ac.uk/projects/festival/mbrola.html</a>. A solution using this technique was developed for Festival 1.4.3 called FranFest. Google for "FranFest". Also, here's an article that explains how to install it: <a href="http://www.pollock-nageoire.net/festival/festival-english004.html">http://www.pollock-nageoire.net/festival/festival-english004.html</a>. The problem with this is 1) it requires patching and rebuilding Festival, and 2) it needs to be adapted to Festival 2.0 (1.95 beta). I would recommend approaching the Festival programmers about incorporating this patch into Festival permanently.
+
+3. Native Festival. Develop a "native" voice for Festival so that Festival can do the full TTS conversion. This is much harder than #1 or #2, but would be much easier for KTTS users to install. From time to time, I have seen people mention on the festival-talk mailing list that they are working on this, so it may already be done or near done. More info at <a href="http://festvox.org/maillists.html">http://festvox.org/maillists.html</a>. Unfortunately, the festival-talk mailing list archive is not available. I can send you an mbox of what I have if you are interested.
+
+Whatever solution you come up with, you'll need to document how French KTTS users install and configure it. If your solution uses Festival, it must list the voice code for the French voice in response to the following Scheme statement:
+
+ (print (mapcar (lambda (pair) (car pair)) voice-locations))
+
+Contact me in irc.kde.org channel #kde-accessibility for more information.
+
diff --git a/kttsd/app-plugins/Makefile.am b/kttsd/app-plugins/Makefile.am
new file mode 100644
index 0000000..22a2493
--- /dev/null
+++ b/kttsd/app-plugins/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = kate
diff --git a/kttsd/app-plugins/kate/Makefile.am b/kttsd/app-plugins/kate/Makefile.am
new file mode 100644
index 0000000..3508e52
--- /dev/null
+++ b/kttsd/app-plugins/kate/Makefile.am
@@ -0,0 +1,19 @@
+# Allow build from within kdebase or kdeaccessibility.
+INCLUDES = \
+ -I$(top_srcdir)/kate/interfaces \
+ -I$(kde_includes)/kate \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = ktexteditor_kttsd.la
+
+ktexteditor_kttsd_la_SOURCES = katekttsd.cpp
+ktexteditor_kttsd_la_LIBADD = -lktexteditor
+ktexteditor_kttsd_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+kttsddatadir = $(kde_datadir)/ktexteditor_kttsd
+kttsddata_DATA = ktexteditor_kttsdui.rc
+
+kde_services_DATA = ktexteditor_kttsd.desktop
diff --git a/kttsd/app-plugins/kate/katekttsd.cpp b/kttsd/app-plugins/kate/katekttsd.cpp
new file mode 100644
index 0000000..a2e64e6
--- /dev/null
+++ b/kttsd/app-plugins/kate/katekttsd.cpp
@@ -0,0 +1,120 @@
+/***************************************************************************
+ A KTextEditor (Kate Part) plugin for speaking text.
+
+ Copyright:
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+
+ Original Author: Olaf Schmidt <ojschmidt@kde.org>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qmessagebox.h>
+#include <dcopclient.h>
+#include <qtimer.h>
+
+// KDE includes.
+#include <ktexteditor/editinterface.h>
+#include <ktexteditor/selectioninterface.h>
+
+#include <kaction.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+
+// KateKttsdPlugin includes.
+#include "katekttsd.h"
+#include "katekttsd.moc"
+
+K_EXPORT_COMPONENT_FACTORY( ktexteditor_kttsd, KGenericFactory<KateKttsdPlugin>( "ktexteditor_kttsd" ) )
+
+KateKttsdPlugin::KateKttsdPlugin( QObject *parent, const char* name, const QStringList& )
+ : KTextEditor::Plugin ( (KTextEditor::Document*) parent, name )
+{
+}
+
+KateKttsdPlugin::~KateKttsdPlugin()
+{
+}
+
+
+void KateKttsdPlugin::addView(KTextEditor::View *view)
+{
+ KateKttsdPluginView *nview = new KateKttsdPluginView (view, "KTTSD Plugin");
+ m_views.append (nview);
+}
+
+void KateKttsdPlugin::removeView(KTextEditor::View *view)
+{
+ for (uint z=0; z < m_views.count(); ++z)
+ if (m_views.at(z)->parentClient() == view)
+ {
+ KateKttsdPluginView *nview = m_views.at(z);
+ m_views.remove (nview);
+ delete nview;
+ }
+ KGlobal::locale()->removeCatalogue("kttsd");
+}
+
+
+KateKttsdPluginView::KateKttsdPluginView( KTextEditor::View *view, const char *name )
+ : QObject( view, name ),
+ KXMLGUIClient( view )
+{
+ view->insertChildClient( this );
+ setInstance( KGenericFactory<KateKttsdPlugin>::instance() );
+ KGlobal::locale()->insertCatalogue("kttsd");
+ (void) new KAction( i18n("Speak Text"), "kttsd", 0, this, SLOT(slotReadOut()), actionCollection(), "tools_kttsd" );
+ setXMLFile( "ktexteditor_kttsdui.rc" );
+}
+
+void KateKttsdPluginView::slotReadOut()
+{
+ KTextEditor::View *v = (KTextEditor::View*)parent();
+ KTextEditor::SelectionInterface *si = KTextEditor::selectionInterface( v->document() );
+ QString text;
+
+ if ( si->hasSelection() )
+ text = si->selection();
+ else {
+ KTextEditor::EditInterface *ei = KTextEditor::editInterface( v->document() );
+ text = ei->text();
+ }
+
+ DCOPClient *client = kapp->dcopClient();
+ // If KTTSD not running, start it.
+ if (!client->isApplicationRegistered("kttsd"))
+ {
+ QString error;
+ if (kapp->startServiceByDesktopName("kttsd", QStringList(), &error))
+ QMessageBox::warning(0, i18n( "Starting KTTSD Failed"), error );
+ }
+ QByteArray data;
+ QByteArray data2;
+ QCString replyType;
+ QByteArray replyData;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << text << "";
+ if ( !client->call("kttsd", "KSpeech", "setText(QString,QString)",
+ data, replyType, replyData, true) )
+ QMessageBox::warning( 0, i18n( "DCOP Call Failed" ),
+ i18n( "The DCOP call setText failed." ));
+ QDataStream arg2(data2, IO_WriteOnly);
+
+ arg2 << 0;
+ if ( !client->call("kttsd", "KSpeech", "startText(uint)",
+ data2, replyType, replyData, true) )
+ QMessageBox::warning( 0, i18n( "DCOP Call Failed" ),
+ i18n( "The DCOP call startText failed." ));
+}
+
diff --git a/kttsd/app-plugins/kate/katekttsd.h b/kttsd/app-plugins/kate/katekttsd.h
new file mode 100644
index 0000000..cbab720
--- /dev/null
+++ b/kttsd/app-plugins/kate/katekttsd.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ A KTextEditor (Kate Part) plugin for speaking text.
+
+ Copyright:
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+
+ Original Author: Olaf Schmidt <ojschmidt@kde.org>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _KATEKTTSD_H_
+#define _KATEKTTSD_H_
+
+#include <ktexteditor/plugin.h>
+#include <ktexteditor/view.h>
+#include <kxmlguiclient.h>
+#include <qobject.h>
+
+class KateKttsdPlugin : public KTextEditor::Plugin, public KTextEditor::PluginViewInterface
+{
+ Q_OBJECT
+
+ public:
+ KateKttsdPlugin( QObject *parent = 0,
+ const char* name = 0,
+ const QStringList &args = QStringList() );
+ virtual ~KateKttsdPlugin();
+
+ void addView (KTextEditor::View *view);
+ void removeView (KTextEditor::View *view);
+
+ private:
+ QPtrList<class KateKttsdPluginView> m_views;
+};
+
+class KateKttsdPluginView : public QObject, public KXMLGUIClient
+{
+ Q_OBJECT
+
+ public:
+ KateKttsdPluginView( KTextEditor::View *view, const char *name=0 );
+ ~KateKttsdPluginView() {};
+
+ public slots:
+ void slotReadOut();
+};
+
+#endif // _KATEKTTSD_H_
diff --git a/kttsd/app-plugins/kate/ktexteditor_kttsd.desktop b/kttsd/app-plugins/kate/ktexteditor_kttsd.desktop
new file mode 100644
index 0000000..aac7e0c
--- /dev/null
+++ b/kttsd/app-plugins/kate/ktexteditor_kttsd.desktop
@@ -0,0 +1,104 @@
+[Desktop Entry]
+Name=KTextEditor KTTSD Plugin
+Name[bg]=Приставка KTextEditor KTTSD
+Name[br]=Lugent KTTSD KTextEditor
+Name[bs]=KTextEditor KTTSD dodatak
+Name[ca]=Connector pel KTTSD del KTextEditor
+Name[cs]=KTextEditor KTTSD modul
+Name[de]=KTextEditor-Modul für KTTSD
+Name[el]=Πρόσθετο KTextEditor KTTSD
+Name[es]=Complemento KTextEditor KTTSD
+Name[et]=KTextEditor KTTSD plugin
+Name[eu]=KTextEditor-en KTTSD plugina
+Name[fa]=وصلۀ KTextEditor KTTSD
+Name[fi]=KTextEditor KTTSD -liitännäinen
+Name[fr]=Module KTTSD pour KTextEditor
+Name[ga]=Breiseán KTTSD KTextEditor
+Name[gl]=Plugin de KTTSD para KTextEditor
+Name[he]=תוסף KTextEditor עבור KTTSD
+Name[hu]=KTextEditor KTTSD-modul
+Name[is]=KTextEditor KTTSD íforrit
+Name[it]=Plugin di KTTSD per KTextEditor
+Name[ja]=KTextEditor KTTSD プラグイン
+Name[ka]=KTextEditor KTTSD მოდული
+Name[km]= កម្មវិធី​ជំនួយ​ KTextEditor KTTSD
+Name[lt]=KTextEditor KTTSD priedas
+Name[mk]=KTTSD-приклучок за KTextEditor
+Name[ms]=Plugin KTextEditor KTTSD
+Name[nb]=KTextEditor programtillegg for KTTSD
+Name[nds]=KTTSD-Moduul KTextEditor
+Name[ne]=केडीई पाठ सम्पादक KTTSD प्लगइन
+Name[nl]=KTextEditor KTTSD-plugin
+Name[pa]=KTextEditor KTTSD ਪਲੱਗਿੰਨ
+Name[pl]=Wtyczka KTTSD dla edytora tekstu
+Name[pt]='Plugin' KTextEditor do KTTSD
+Name[pt_BR]=Plug-in do KTTSD para o KTextEditor
+Name[ru]=Модуль KTextEditor для KTTSD
+Name[sk]=KTextEditor KTTSD modul
+Name[sl]=Vstavek KTTSD za KTextEditor
+Name[sr]=KTTSD као прикључак за KTextEditor
+Name[sr@Latn]=KTTSD kao priključak za KTextEditor
+Name[sv]=KTTSD-insticksprogram för Ktexteditor
+Name[ta]=KTextEditor KTTSD சொருகுப்பொருள்
+Name[tg]=Модли KTextEditor барои KTTSD
+Name[th]=ปลั๊กอิน KTTSD สำหรับ KTextEditor
+Name[tr]=Ktexteditor KTTSD Eklentisi
+Name[uk]=Втулок KTextEditor KTTSD
+Name[vi]=Trình bổ sung KTTSD cho Trình soạn thảo K
+Name[zh_CN]=KTextEditor KTTSD 插件
+Name[zh_TW]=K-文字編輯器的 kttsd 外掛程式
+Comment=Adds a menu entry for speaking the text
+Comment[bg]=Добавяне на операция в менюто за изговаряне на текст
+Comment[bs]=Dodaje stavku u meniju za čitanje teksta
+Comment[ca]=Afegeix una entrada de menú per pronunciar el text
+Comment[cs]=Vložení nabídky pro předčítání textu
+Comment[da]=Tilføjer et menupunkt for at læse teksten op
+Comment[de]=Fügt einen Menüeintrag zum Vorlesen des Textes hinzu
+Comment[el]=Προσθέτει μία καταχώρηση στο μενού για τη μετατροπή σε φωνή του κειμένου
+Comment[es]=Añadir una entrada al menú para leer el texto
+Comment[et]=Lisab menüükirje teksti kõnelemiseks
+Comment[eu]=Testuak ahoskatzeko menuko sarrera bat gehitzen du
+Comment[fa]=مدخل گزینگان را برای گفتن متن اضافه می‌کند
+Comment[fi]=Lisää valikkovalinnan tekstin puhumiseksi
+Comment[fr]=Ajoute une entrée dans le menu pour prononcer le texte
+Comment[ga]=Cuir iontráil sa roghchlár chun an téacs a rá
+Comment[gl]=Engade unha entrada no menu para falar o texto
+Comment[he]=מוסיף כניסה בתפריט להקראת הטקסט
+Comment[hu]=Menüpont létrehozása szövegfelolvasáshoz
+Comment[is]=Bætir við valmyndarfærslu fyrir tal af textanum
+Comment[it]=Aggiunge una voce del menu per pronunciare il testo
+Comment[ja]=テキスト読み上げをメニューエントリに追加する
+Comment[ka]=ტექსტის წაკითხვას ამატებს მენიუს ჩანაწერს
+Comment[km]=បន្ថែម​ធាតុ​ម៉ឺនុយ​សម្រាប់​ការ​និយាយ​អត្ថបទ
+Comment[lt]=Prideda meniu įrašą teksto įkalbėjimui
+Comment[mk]=Додава елемент во менито за зборување на текстот
+Comment[ms]=Tambah entri menu untuk menjadikan teks bercakap
+Comment[nb]=Legger til en menyoppføring for å si teksten høyt
+Comment[nds]=Föögt en Menüindrag för dat Textvörlesen to
+Comment[ne]=पाठ बोल्नका लागि मेनु प्रविष्टि थप्छ
+Comment[nl]=Voegt een menuoptie toe voor het uitspreken van de tekst
+Comment[pa]=ਪਾਠ ਬੋਲਣ ਲਈ ਇੱਕ ਮੇਨੂ ਇੰਦਰਾਜ਼ ਜੋੜਦਾ ਹੈ
+Comment[pl]=Dodaje wpis w menu do mówienia tekstu
+Comment[pt]=Adiciona uma entrada de menu para ler o texto
+Comment[pt_BR]=Adiciona uma entrada no menu para falar o texto
+Comment[ru]=Добавляет меню синтеза речи
+Comment[sk]=Pridá položku menu pre hovorenie textu
+Comment[sl]=Dodaj menijski vnos za govorjenje besedila
+Comment[sr]=Додаје ставку менија за изговарање текста
+Comment[sr@Latn]=Dodaje stavku menija za izgovaranje teksta
+Comment[sv]=Lägger till ett menyalternativ för att läsa upp texten
+Comment[ta]=உரையை பேசுவதற்கு ஒரு பட்டியல் உள்ளிட்டை சேர்க்கிறது
+Comment[tg]=Илова кардани менюи таҳлили овоз
+Comment[th]=เพิ่มรายการเมนูสำหรับอ่านข้อความเป็นเสียง
+Comment[tr]=Metni okumak için bir menü girdisi oluşturur
+Comment[uk]=Додає елемент меню для декламування тексту
+Comment[vi]=Thêm danh mục thực đơn cho việc đọc văn bản
+Comment[zh_CN]=添加可读出文本的菜单项
+Comment[zh_TW]=新增朗讀文字的目錄
+Type=Service
+ServiceTypes=KTextEditor/Plugin
+X-KDE-Library=ktexteditor_kttsd
+X-Kate-Version=2.2
+MimeType=text/plain
+Icon=kttsd
+author=Olaf Jan Schmidt, ojschmidt@kde.org
diff --git a/kttsd/app-plugins/kate/ktexteditor_kttsdui.rc b/kttsd/app-plugins/kate/ktexteditor_kttsdui.rc
new file mode 100644
index 0000000..9dea629
--- /dev/null
+++ b/kttsd/app-plugins/kate/ktexteditor_kttsdui.rc
@@ -0,0 +1,11 @@
+<!DOCTYPE kpartgui>
+<kpartplugin name="ktexteditor_kttsd" library="ktexteditor_kttsd" version="2">
+ <MenuBar>
+ <Menu name="tools"><Text>&amp;Tools</Text>
+ <Action name="tools_kttsd" />
+ </Menu>
+ </MenuBar>
+ <ToolBar name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="tools_kttsd" />
+ </ToolBar>
+</kpartplugin>
diff --git a/kttsd/clean_obsolete.sh b/kttsd/clean_obsolete.sh
new file mode 100755
index 0000000..17e8c26
--- /dev/null
+++ b/kttsd/clean_obsolete.sh
@@ -0,0 +1,105 @@
+#! /bin/sh
+
+# This script cleans obsolete KTTS files from your system.
+# You should run this if you have been downloading KTTS and installing
+# prior to the indicated dates.
+
+# You would normally run this after running configure and before
+# make install, i.e.,
+# cd kdenonbeta
+# echo kttsd>inst-apps
+# make -f Makefile.cvs
+# ./configure
+# cd kttsd
+# ./clean_obsolete.sh
+# make install
+
+PREFIX=$(kde-config --prefix)
+LIBTOOL="../libtool"
+
+if [ -z "$PREFIX" ]; then
+ echo "KDE prefix not found. Do you have kde-config installed?"
+ exit
+fi
+
+if [ ! -x $LIBTOOL ]; then
+ echo "libtool was not found. Did you run configure?"
+ exit
+fi
+
+set -x
+
+# libktts removed. See kdeaccessibility/kttsd/kcmkttsmgr/Makefile.am
+# for example how to build without it.
+# on or about 20 Dec 2004.
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libktts
+$LIBTOOL --mode=uninstall $PREFIX/lib/libktts
+
+# ServiceType kttsd.desktop renamed to kttsd_synthplugin.desktop,
+# which distinquishes it from kttsd.desktop in the services dir
+# and more accurately reflects its purpose
+# on or about 8 Dec 2004.
+rm -f $PREFIX/share/servicetypes/kttsd.desktop
+
+# kcm_kttsmgr removed. Use kcm_kttsd instead.
+# Change made on or about 18 Dec 2004.
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/kcm_kttsmgr
+rm -f $PREFIX/share/applnk/Settings/Accessibility/kcmkttsmgr.desktop
+rm -f $PREFIX/share/applications/kde/kcmkttsmgr.desktop
+
+# Renamed libkttsjobmgr to libkttsjobmgrpart per kdelibs/NAMING convention
+# on or about 19 Oct 2004:
+
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libkttsjobmgr
+
+# The following installed files were renamed
+# on or about 19 Oct 2004:
+# In $KDEDIR/share/services/:
+# festival.desktop -> kttsd_festivalplugin.desktop
+# festivalint.desktop -> kttsd_festivalintplugin.desktop
+# command.desktop -> kttsd_commandplugin.desktop
+# hadifix.desktop -> kttsd_hadifixplugin.desktop
+# flite.desktop -> kttsd_fliteplugin.desktop
+# epos-kttsdplugin.desktop -> kttsd_eposplugin.desktop
+# freetts.desktop -> kttsd_freettsplugin.desktop
+# In $KDEDIR/lib/kde3/:
+# libfestivalplugin -> libkttsd_festivalplugin
+# libfestivalintplugin -> libkttsd_festivalintplugin
+# libcommandplugin -> libkttsd_commandplugin
+# libhadifixplugin -> libkttsd_hadifixplugin
+# libfliteplugin -> libkttsd_fliteplugin
+# libeposkttsdplugin -> libkttsd_eposplugin
+# libfreettsplugin -> libkttsd_freettsplugin
+
+rm -f $PREFIX/share/services/festival.desktop
+rm -f $PREFIX/share/services/festivalint.desktop
+rm -f $PREFIX/share/services/command.desktop
+rm -f $PREFIX/share/services/hadifix.desktop
+rm -f $PREFIX/share/services/flite.desktop
+rm -f $PREFIX/share/services/epos-kttsdplugin.desktop
+rm -f $PREFIX/share/services/freetts.desktop
+
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libfestivalplugin
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libfestivalintplugin
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libcommandplugin
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libhadifixplugin
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libfliteplugin
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libeposkttsdplugin
+$LIBTOOL --mode=uninstall $PREFIX/lib/kde3/libfreettsplugin
+
+# The following library was changed from unversioned to versioned
+# on or about 13 Oct 2004,
+
+$LIBTOOL --mode=uninstall $PREFIX/lib/libktts
+
+# The hadifax plugin was renamed to hadifix
+# on or about 4 Sep 2004.
+
+rm -f $PREFIX/share/services/hadifax.desktop
+$LIBTOOL --mode=uninstall /lib/kde3/libhadifaxplugin
+
+# Clean up the library cache.
+
+$LIBTOOL --mode=finish -n $PREFIX/lib
+$LIBTOOL --mode=finish -n $PREFIX/lib/kde3/
+
diff --git a/kttsd/compat/Makefile.am b/kttsd/compat/Makefile.am
new file mode 100644
index 0000000..f1e3edd
--- /dev/null
+++ b/kttsd/compat/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+ $(KTTS_ICONS_DIR) \
+ $(KTTS_INTERFACES_DIR)
diff --git a/kttsd/compat/README_COMPAT b/kttsd/compat/README_COMPAT
new file mode 100644
index 0000000..40729d0
--- /dev/null
+++ b/kttsd/compat/README_COMPAT
@@ -0,0 +1,6 @@
+This is a directory to keep compatibility in KTTSD.
+This directory permits distribution and compilation of the following kttsd components:
+ If KDE < 3.4, copy of kdelibs/interfaces/kspeech.
+ If KDE < 3.5, copy of kdelibs/pics (kttsd icons only)
+
+Last Sync: Sat Mar 26 18:00:00 EST 2004 by Gary Cramblitt (PhantomsDad) <garycramblitt@comcast.net>
diff --git a/kttsd/compat/icons/Makefile.am b/kttsd/compat/icons/Makefile.am
new file mode 100644
index 0000000..e5515a8
--- /dev/null
+++ b/kttsd/compat/icons/Makefile.am
@@ -0,0 +1 @@
+KDE_ICON = AUTO
diff --git a/kttsd/compat/icons/cr128-app-kttsd.png b/kttsd/compat/icons/cr128-app-kttsd.png
new file mode 100644
index 0000000..0efd8c9
--- /dev/null
+++ b/kttsd/compat/icons/cr128-app-kttsd.png
Binary files differ
diff --git a/kttsd/compat/icons/cr16-app-kttsd.png b/kttsd/compat/icons/cr16-app-kttsd.png
new file mode 100644
index 0000000..3be5160
--- /dev/null
+++ b/kttsd/compat/icons/cr16-app-kttsd.png
Binary files differ
diff --git a/kttsd/compat/icons/cr22-app-kttsd.png b/kttsd/compat/icons/cr22-app-kttsd.png
new file mode 100644
index 0000000..8372208
--- /dev/null
+++ b/kttsd/compat/icons/cr22-app-kttsd.png
Binary files differ
diff --git a/kttsd/compat/icons/cr32-app-kttsd.png b/kttsd/compat/icons/cr32-app-kttsd.png
new file mode 100644
index 0000000..dde2333
--- /dev/null
+++ b/kttsd/compat/icons/cr32-app-kttsd.png
Binary files differ
diff --git a/kttsd/compat/icons/cr48-app-kttsd.png b/kttsd/compat/icons/cr48-app-kttsd.png
new file mode 100644
index 0000000..9b14757
--- /dev/null
+++ b/kttsd/compat/icons/cr48-app-kttsd.png
Binary files differ
diff --git a/kttsd/compat/icons/cr64-app-kttsd.png b/kttsd/compat/icons/cr64-app-kttsd.png
new file mode 100644
index 0000000..9cbc325
--- /dev/null
+++ b/kttsd/compat/icons/cr64-app-kttsd.png
Binary files differ
diff --git a/kttsd/compat/icons/crsc-app-kttsd.svgz b/kttsd/compat/icons/crsc-app-kttsd.svgz
new file mode 100644
index 0000000..199484f
--- /dev/null
+++ b/kttsd/compat/icons/crsc-app-kttsd.svgz
Binary files differ
diff --git a/kttsd/compat/interfaces/Makefile.am b/kttsd/compat/interfaces/Makefile.am
new file mode 100644
index 0000000..54cb7de
--- /dev/null
+++ b/kttsd/compat/interfaces/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = $(AUTODIRS)
diff --git a/kttsd/compat/interfaces/kspeech/Makefile.am b/kttsd/compat/interfaces/kspeech/Makefile.am
new file mode 100644
index 0000000..d7b5aaa
--- /dev/null
+++ b/kttsd/compat/interfaces/kspeech/Makefile.am
@@ -0,0 +1,8 @@
+# This is necessary for "make bcheck" to work.
+INCLUDES = $(all_includes)
+
+# Header files to be installed.
+include_HEADERS = kspeech.h kspeechsink.h
+
+# Define DCOP/Text-to-Speech Service Type.
+kde_servicetypes_DATA = dcoptexttospeech.desktop
diff --git a/kttsd/compat/interfaces/kspeech/dcoptexttospeech.desktop b/kttsd/compat/interfaces/kspeech/dcoptexttospeech.desktop
new file mode 100644
index 0000000..637cb7e
--- /dev/null
+++ b/kttsd/compat/interfaces/kspeech/dcoptexttospeech.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=DCOP/Text-to-Speech
+Comment=Text-to-Speech Service with a DCOP interface
+Comment[bg]=Модул за синтез на глас с интерфейс DCOP
+Comment[bs]=Servis za čitanje teksta za DCOP interfejsom
+Comment[ca]=Servei de text a veu amb una interfície DCOP
+Comment[cs]=Služba hlasové syntézy s DCOP rozhraním
+Comment[cy]=Gwasanaeth Testun-i-Lafar efo rhyngwyneb DCOP
+Comment[da]=Tekst-til-tale tjeneste med en DCOP grænseflade
+Comment[de]=Sprachausgabedienst mit DCOP-Schnittstelle
+Comment[el]=Υπηρεσία κειμένου-σε-ομιλία με διασύνδεση DCOP
+Comment[es]=Servicio de texto a voz con interfaz DCOP
+Comment[et]=Teksti kõneks muutmise teenus DCOP-liidesega
+Comment[eu]=DCOP interfazedun testutik hizketarako zerbitzua
+Comment[fa]=خدمت متن به گفتار با یک واسط DCOP
+Comment[fi]=Teksti puheeksi -palvelu DCOP -liittymällä
+Comment[fr]=Service de synthèse vocale avec une interface DCOP
+Comment[ga]=Seirbhís Téacs-go-Caint le comhéadan DCOP
+Comment[gl]= Servizo de Texto-para-Fala con interface DCOP
+Comment[he]=שירות טקסט לדיבור עם ממשק DCOP
+Comment[hu]=Szövegfelolvasó szolgáltatás DCOP-felülettel
+Comment[is]=Texti-í-tal þjónusta með DCOP viðmóti
+Comment[it]=Servizio di pronuncia con interfaccia DCOP
+Comment[ja]=DCOP インターフェースによるテキスト読み上げサービス
+Comment[ka]=ტექსტი-სიტყვა სერვისი DCOP ინტერფეისით
+Comment[km]=សេវា​អត្ថបទ​ដែល​ត្រូវ​និយាយ​ជាមួយ​នឹង​ចំណុច​ប្រទាក់ DCOP
+Comment[lt]=Teksto vertimo kalba tarnyba su DCOP sąsaja
+Comment[mk]=Сервис за текст-во-говор со DCOP-интерфејс
+Comment[ms]=Servis Teks-ke-Tutur dengan antara muka DCOP
+Comment[nb]=Tjeneste for tekst-til-tale med DCOP-grensesnitt
+Comment[nds]=Vörleesdeenst mit DCOP-Koppelsteed
+Comment[ne]=DCOP इन्टरफेससँग पाठ वाचक सेवा
+Comment[nl]=Tekst-tot-spraak-dienst met een DCOP-interface
+Comment[pl]=Usługa odczytywania tekstu z interfejsem DCOP
+Comment[pt]=Servidor Texto-para-Voz com interface DCOP
+Comment[pt_BR]=Serviço de Fala de Textos com uma interface DCOP
+Comment[ru]=Сервис синтеза речи через интерфейс DCOP
+Comment[rw]=Serivise Umwandiko-ku-Kuvuga ifite imigaragarire DCOP
+Comment[sk]=Text-na-reč služba pre DCOP
+Comment[sl]=Storitev besedila v govor z vmesnikom DCOP
+Comment[sr]=Услуга изговарања текста са DCOP интерфејсом
+Comment[sr@Latn]=Usluga izgovaranja teksta sa DCOP interfejsom
+Comment[sv]=Text-till-tal tjänst med DCOP-gränssnitt
+Comment[ta]=ஒரு DCOP இடைமுகத்தில் உரையில் இருந்து பேச்சு சேவை
+Comment[tg]=Бартарафсозии таҳлили овоз ба воситаи интерфейси DCOP
+Comment[th]=บริการแปลงข้อความเป็นคำพูดผ่านทาง DCOP
+Comment[tr]=DCOP arayüzü ile Metinden Konuşmaya Servisi
+Comment[uk]=Служба синтезу мовлення з тексту із інтерфейсом DCOP
+Comment[vi]=Dịch vụ chuyển Văn bản thành Tiếng nói cho giao diện DCOP
+Comment[zh_CN]=带 DCOP 接口的文本到语音服务
+Comment[zh_TW]=有 DCOP 介面的文字轉語音服務
diff --git a/kttsd/compat/interfaces/kspeech/kspeech.h b/kttsd/compat/interfaces/kspeech/kspeech.h
new file mode 100644
index 0000000..e4a831c
--- /dev/null
+++ b/kttsd/compat/interfaces/kspeech/kspeech.h
@@ -0,0 +1,1285 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ kspeech.h
+ KTTSD DCOP Interface
+ --------------------
+ Copyright:
+ (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2004-2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _KSPEECH_H_
+#define _KSPEECH_H_
+
+#include <dcopobject.h>
+#include <qstringlist.h>
+
+/**
+ * @interface KSpeech
+ *
+ * kspeech - the KDE Text-to-Speech API.
+ *
+ * @version 1.0 Draft 10
+ *
+ * @since KDE 3.4
+ *
+ * This class defines the DCOP interface for applications desiring to speak text.
+ * Applications may speak text by sending DCOP messages to application "kttsd" object "KSpeech".
+ *
+ * %KTTSD -- the KDE Text-to-Speech Deamon -- is the program that supplies the services
+ * in the KDE Text-to-Speech API.
+ *
+ * @warning The KSpeech interface is still being developed and is likely to change in the future.
+ *
+ * @section Features
+ *
+ * - Priority system for Screen Readers, warnings and messages, while still playing
+ * regular texts.
+ * - Long text is parsed into sentences. User may backup by sentence or part,
+ * replay, pause, and stop playing.
+ * - Handles multiple speaking applications. Text messages are treated like print jobs.
+ * Jobs may be created, started, stopped, paused, resumed, and deleted.
+ * - Speak contents of clipboard.
+ * - Speak KDE notifications.
+ * - Plugin-based text job filtering permits substitution for misspoken words,
+ * abbreviations, etc., transformation of XML or XHTML to SSML, and automatic
+ * choice of appropriate synthesis engine.
+ *
+ * @section Requirements
+ *
+ * You may build any KDE application to use KSpeech, since the interface is in kdelibs, but
+ * the kdeaccessibility package must be installed for KTTS to function.
+ *
+ * You will need a speech synthesis engine, such as Festival. See the KTTS Handbook
+ * for the latest information on installing and configuring speech engines and voices
+ * with KTTS.
+ *
+ * @section goals Design Goals
+ *
+ * The KDE Text-to-Speech API is designed with the following goals:
+ *
+ * - Support the features enumerated above.
+ * - Plugin-based architecture for support of a wide variety of speech synthesis
+ * engines and drivers.
+ * - Permit generation of speech from the command line (or via shell scripts)
+ * using the KDE DCOP utilities.
+ * - Provide a lightweight and easily usable interface for applications to
+ * generate speech output.
+ * - Applications need not be concerned about contention over the speech device.
+ * - Provide limited support for speech markup languages, such as Sable,
+ * Java %Speech Markup Language (JSML), and %Speech Markup Meta-language (SMML).
+ * - Provide limited support for embedded speech markers.
+ * - Asynchronous to prevent system blocking.
+ * - Plugin-based audio architecture. Currently supports aRts but will support
+ * additional audio engines in the future, such as gstreamer.
+ * - Compatible with original %KTTSD API as developed by José Pablo Ezequiel
+ * "Pupeno" Fernández (avoid breaking existing applications).
+ *
+ * Architecturally, applications interface with %KTTSD, which performs queueing,
+ * speech job managment, plugin management and sentence parsing. %KTTSD interfaces with a
+ * %KTTSD speech plugin(s), which then interfaces with the speech engine(s) or driver(s).
+ *
+ @verbatim
+ application
+ ^
+ | via DCOP (the KDE Text-to-Speech API)
+ v
+ kttsd
+ ^
+ | KTTSD plugin API
+ v
+ kttsd plugin
+ ^
+ |
+ v
+ speech engine
+ @endverbatim
+ *
+ * The %KTTSD Plugin API is documented in PluginConf in the kdeaccessibility module.
+ *
+ * There is a separate GUI application, called kttsmgr, for providing %KTTSD
+ * configuration and job management.
+ *
+ * kttsd maintains 4 types of speech output:
+ * - Screen Reader Output
+ * - Warnings
+ * - Messages
+ * - Text Jobs
+ *
+ * Method sayScreenReaderOutput speaks Screen Reader output.
+ * It pre-empts any other speech in progress,
+ * including other Screen Reader outputs, i.e., it is not a queue.
+ * This method is reserved for use by Screen Readers.
+ *
+ * Methods sayWarning and sayMessage place messages into the Warnings and
+ * Messages queues respectively. Warnings take priority over messages, which take priority
+ * over text jobs. Warnings and messages are spoken when the currently-speaking
+ * sentence of a text job is finished.
+ *
+ * setText places text into the text job queue. startText begins speaking jobs.
+ * When one job finishes, the next job begins. Method appendText adds
+ * additional parts to a text job. Within a text job, the application (and user
+ * via the kttsmgr GUI), may back up or advance by sentence or part, or rewind
+ * to the beginning.
+ * See jumpToTextPart and moveRelTextSentence.
+ * Text jobs may be paused, stopped, and resumed or deleted from the queue.
+ * See pauseText, stopText, resumeText, and removeText.
+ *
+ * @section cmdline DCOP Command-line Interface
+ *
+ * To create a text job to be spoken
+ *
+ @verbatim
+ dcop kttsd KSpeech setText <text> <talker>
+ @endverbatim
+ *
+ * where \<text\> is the text to be spoken, and \<talker\> is usually a language code
+ * such as "en", "cy", etc.
+ *
+ * Example.
+ *
+ @verbatim
+ dcop kttsd KSpeech setText "This is a test." "en"
+ @endverbatim
+ *
+ * To start speaking the text.
+ *
+ @verbatim
+ dcop kttsd KSpeech startText 0
+ @endverbatim
+ *
+ * You can combine the setText and startText commands into a single command.
+ *
+ @verbatim
+ dcop kttsd KSpeech sayText <text> <talker>
+ @endverbatim
+ *
+ * @since KDE 3.5
+ *
+ * To stop speaking and rewind to the beginning of the text.
+ *
+ @verbatim
+ dcop kttsd KSpeech stopText 0
+ @endverbatim
+ *
+ * Depending upon the speech plugin used, speaking may not immediately stop.
+ *
+ * To stop and remove a text job.
+ *
+ @verbatim
+ dcop kttsd KSpeech removeText 0
+ @endverbatim
+ *
+ * Note: For more information about talker codes, see talkers below.
+ *
+ * @section programming Calling KTTSD from a Program
+ *
+ * There are two methods of making DCOP calls from your application to %KTTSD.
+ *
+ * - Manually code them using dcopClient object. See kdebase/konqueror/kttsplugin/khtmlkttsd.cpp
+ * for an example. This method is recommended if you want to make a few simple calls to KTTSD.
+ * - Use kspeech_stub as described below. This method generates the marshalling code for you
+ * and is recommended for a more complex speech-enabled applications. kcmkttsmgr in the
+ * kdeaccessibility module is an example that uses this method.
+ *
+ * To make DCOP calls from your program using kspeech_stub, follow these steps:
+ *
+ * 1. Include kspeech_stub.h in your code. Derive an object from the KSpeech_stub interface.
+ * For example, suppose you are developing a KPart and want to call %KTTSD.
+ * Your class declaration might look like this:
+ *
+ @verbatim
+ #include <kspeech_stub.h>
+ class MyPart: public KParts::ReadOnlyPart, public KSpeech_stub {
+ @endverbatim
+ *
+ * 2. In your class constructor, initialize DCOPStub, giving it the sender
+ * "kttsd", object "KSpeech".
+ *
+ @verbatim
+ MyPart::MyPart(QWidget *parent, const char *name) :
+ KParts::ReadOnlyPart(parent, name),
+ DCOPStub("kttsd", "KSpeech") {
+ @endverbatim
+ *
+ * 3. See if KTTSD is running, and if not, start it.
+ *
+ @verbatim
+ DCOPClient *client = dcopClient();
+ client->attach();
+ if (!client->isApplicationRegistered("kttsd")) {
+ QString error;
+ if (KApplication::startServiceByDesktopName("kttsd", QStringList(), &error))
+ cout << "Starting KTTSD failed with message " << error << endl;
+ }
+ @endverbatim
+ *
+ * If you want to detect if KTTSD is installed without starting it, use this code.
+ *
+ @verbatim
+ KTrader::OfferList offers = KTrader::self()->query("DCOP/Text-to-Speech", "Name == 'KTTSD'");
+ if (offers.count() > 0)
+ {
+ // KTTSD is installed.
+ }
+ @endverbatim
+ *
+ * Typically, you would do this to hide a menu item or button if KTTSD is not installed.
+ *
+ * 4. Make calls to KTTSD in your code.
+ *
+ @verbatim
+ uint jobNum = setText("Hello World", "en");
+ startText(jobNum);
+ @endverbatim
+ *
+ * 4. Add kspeech_DIR and kspeech.stub to your Makefile.am. Example:
+ *
+ @verbatim
+ kspeech_DIR = $(kde_includes)
+ libmypart_la_SOURCES = kspeech.stub
+ @endverbatim
+ *
+ * @section signals Signals Emitted by KTTSD
+ *
+ * %KTTSD emits a number of DCOP signals, which provide information about sentences spoken,
+ * text jobs started, stopped, paused, resumed, finished, or deleted and markers seen.
+ * In general, these signals are broadcast to any application that connects to them.
+ * Applications should check the appId argument to determine whether the signal belongs to
+ * them or not.
+ *
+ * To receive %KTTSD DCOP signals, follow these steps:
+ *
+ * 1. Include kspeechsink.h in your code. Derive an object from the KSpeechSink interface
+ * and declare a method for each signal you'd like to receive. For example,
+ * if you were coding a KPart and wanted to receive the KTTSD signal sentenceStarted:
+ *
+ @verbatim
+ #include <kspeechsink.h>
+ class MyPart:
+ public KParts::ReadOnlyPart,
+ virtual public KSpeechSink
+ {
+ protected:
+ ASYNC sentenceStarted(const QCString& appId, const uint jobNum, const uint seq);
+ @endverbatim
+ *
+ * You can combine sending and receiving in one object.
+ *
+ @verbatim
+ #include <kspeechsink.h>
+ class MyPart:
+ public KParts::ReadOnlyPart,
+ public KSpeech_stub,
+ virtual public KSpeechSink
+ {
+ protected:
+ ASYNC sentenceStarted(const QCString& appId, const uint jobNum, const uint seq);
+ @endverbatim
+ *
+ * See below for the signals you can declare.
+ *
+ * 2. In your class constructor, initialize DCOPObject with the name of your DCOP
+ * receiving object.
+ *
+ @verbatim
+ MyPart::MyPart(QWidget *parent, const char *name) :
+ KParts::ReadOnlyPart(parent, name),
+ DCOPObject("mypart_kspeechsink") {
+ @endverbatim
+ *
+ * Use any name you like.
+ *
+ * 3. Where appropriate (usually in your constructor), make sure your DCOPClient
+ * is registered and connect the %KTTSD DCOP signals to your declared receiving
+ * methods.
+ *
+ @verbatim
+ // Register DCOP client.
+ DCOPClient *client = kapp->dcopClient();
+ if (!client->isRegistered())
+ {
+ client->attach();
+ client->registerAs(kapp->name());
+ }
+ // Connect KTTSD DCOP signals to our slots.
+ connectDCOPSignal("kttsd", "KSpeech",
+ "sentenceStarted(QCString,uint,uint)",
+ "sentenceStarted(QCString,uint,uint)",
+ false);
+ @endverbatim
+ *
+ * Notice that the argument signatures differ slightly from the actual declarations. For
+ * example
+ *
+ @verbatim
+ ASYNC sentenceStarted(const QCString& appId, const uint jobNum, const uint seq);
+ @endverbatim
+ *
+ * becomes
+ *
+ @verbatim
+ "sentenceStarted(QCString,uint,uint)",
+ @endverbatim
+ *
+ * in the connectDCOPSignal call.
+ *
+ * 4. Write the definition for the received signal. Be sure to check whether the signal
+ * is intended for your application.
+ *
+ @verbatim
+ ASYNC MyPart::sentenceStarted(const QCString& appId, const uint jobNum, const uint seq)
+ {
+ // Check appId to determine if this is our signal.
+ if (appId != dcopClient()->appId()) return;
+ // Do something here.
+ }
+ @endverbatim
+ *
+ * 5. Add kspeechsink_DIR and kspeechsink.skel to your Makefile.am. Example for an app
+ * both sending and receiving.
+ *
+ @verbatim
+ kspeech_DIR = $(kde_includes)
+ kspeechsink_DIR = $(kde_includes)
+ libmypart_la_SOURCES = kspeech.stub kspeechsink.skel
+ @endverbatim
+ *
+ * @section talkers Talkers, Talker Codes, and Plugins
+ *
+ * Many of the methods permit you to specify a desired "talker". This
+ * may be a simple language code, such as "en" for English, "es" for Spanish, etc.
+ * Code as NULL to use the default configured talker.
+ *
+ * Within KTTSMGR, the user has the ability to configure more than one talker for each language,
+ * with different voices, genders, volumes, and talking speeds.
+ *
+ * Talker codes serve two functions:
+ * - They identify configured plugins, and
+ * - They provide a way for applications to specify the desired speaking attributes
+ * that influence the choice of plugin to speak text.
+ *
+ * A Talker Code consists of a series of XML tags and attributes.
+ * An example of a full Talker Code with all attributes specified is
+ *
+ * <voice lang="en" name="kal" gender="male"/>
+ * <prosody volume="soft" rate="fast"/>
+ * <kttsd synthesizer="Festival" />
+ *
+ * (The @e voice and @e prosody tags are adapted from the W3C Speech Synthesis
+ * Markup Language (SSML) and Java Speech Markup Language (JSML).
+ * The @e kttsd tag is an extension to the SMML and JSML languages to support
+ * named synthesizers and text encodings.)
+ * %KTTS doesn't really care about the @e voice, @e prosody, and @e kttsd tags. In fact,
+ * they may be omitted and just the attributes specified. The example above then
+ * becomes
+ *
+ * lang="en" name="kal" gender="male" volume="soft" rate="fast"
+ * synthesizer="Festival"
+ *
+ * The attributes may be specified in any order.
+ *
+ * For clarity, the rest of the discussion
+ * will omit the @e voice, @e prosody, and @e kttsd tags.
+ *
+ * The attributes that make up a talker code are:
+ *
+ * - @e lang. Language code and optional country code.
+ * Examples: en, es, en_US, en_GB. Codes
+ * are case in-sensitive and hyphen (-) or underscore (_) may be
+ * used to separate the country code from the language code.
+ * - @e synthesizer. The name of the synthesizer (plugin) used to produce the speech.
+ * - @e gender. May be either "male", "female", or "neutral".
+ * - @e name. The name of the voice code.
+ * The choice of voice codes is synthesizer-specific.
+ * - @e volume. May be "loud", "medium", or "quiet". A synonym for "quiet" is
+ * "soft".
+ * - @e rate. May be "fast", "medium", or "slow".
+ *
+ * Each plugin, once it has been configured by a user in kttsmgr, returns a
+ * fully-specified talker code to identify itself. If the plugin supports it,
+ * the user may configure another instance of the plugin with a different set
+ * of attributes. This is the difference between a "plugin" and a "talker".
+ * A talker is a configured instance of a plugin. Each plugin (if it supports it)
+ * may be configured as multiple talkers.
+ *
+ * When the user configures %KTTSD, she configures one or more talkers and then
+ * places them in preferred order, top to bottom in kttsmgr. In effect,
+ * she specifies her preferences for each of the talkers.
+ *
+ * When applications specify a talker code, they need not (and typically do not)
+ * give a full specification. An example of a talker code with only some of the
+ * attributes specified might be
+ *
+ * lang="en" gender="female"
+ *
+ * If the talker code is not in XML attribute format, it assumed to be a @e lang
+ * attribute. So the talker code
+ *
+ * en
+ *
+ * is interpreted as
+ *
+ * lang="en"
+ *
+ * When a program requests a talker code in calls to setText, appendText,
+ * sayMessage, sayWarning, and sayScreenReaderOutput,
+ * %KTTSD tries to match the requested talker code to the closest matching
+ * configured talker.
+ *
+ * The @e lang attribute has highest priority (attempting to speak English with
+ * a Spanish synthesizer would likely be unintelligible). So the language
+ * attribute is said to have "priority".
+ * If an application does not specify a language attribute, a default one will be assumed.
+ * The rest of the attributes are said to be "preferred". If %KTTSD cannot find
+ * a talker with the exact preferred attributes requested, the closest matching
+ * talker will likely still be understandable.
+ *
+ * An application may specify that one or more of the attributes it gives in a talker
+ * code have priority by preceeding each priority attribute with an asterisk.
+ * For example, the following talker code
+ *
+ * lang="en" gender="*female" volume="soft"
+ *
+ * means that the application wants to use a talker that supports American English language
+ * and Female gender. If there is more than one such talker, one that supports
+ * Soft volume would be preferred. Notice that a talker configured as English, Male,
+ * and Soft volume would not be picked as long as an English Female talker is
+ * available.
+ *
+ * The algorithm used by %KTTSD to find a matching talker is as follows:
+ *
+ * - If language code is not specified by the application, assume default configured
+ * by user. The primary language code automatically has priority.
+ * - (Note: This is not yet implemented.)
+ * If there are no talkers configured in the language, %KTTSD will attempt
+ * to automatically configure one (see automatic configuraton discussion below)
+ * - The talker that matches on the most priority attributes wins.
+ * - If a tie, the one that matches on the most preferred attributes wins.
+ * - If there is still a tie, the one nearest the top of the kttsmgr display
+ * (first configured) will be chosen.
+ *
+ * Language codes actually consist of two parts, a language code and an optional
+ * country code. For example, en_GB is English (United Kingdom). The language code is
+ * treated as a priority attribute, but the country code (if specified) is treated
+ * as preferred. So for example, if an application requests the following
+ * talker code
+ *
+ * lang="en_GB" gender="male" volume="medium"
+ *
+ * then a talker configured as lang="en" gender="male" volume="medium" would be
+ * picked over one configured as lang="en_GB" gender="female" volume="soft",
+ * since the former matches on two preferred attributes and the latter only on the
+ * preferred attribute GB. An application can override this and make the country
+ * code priority with an asterisk. For example,
+ *
+ * lang="*en_GB" gender="male" volume="medium"
+ *
+ * To specify that American English is priority, put an asterisk in front of
+ * en_US, like this.
+ *
+ * lang="*en_US" gender="male" volume="medium"
+ *
+ * Here the application is indicating that a talker that speaks American English
+ * has priorty over one that speaks a different form of English.
+ *
+ * (Note: Not yet implemented).
+ * If a language code is specified, and no plugin is currently configured
+ * with a matching language code, %KTTSD will attempt to automatically
+ * load and configure a plugin to support the requested language. If
+ * there is no such plugin, or there is a plugin but it cannot automatically
+ * configure itself, %KTTSD will pick one of the configured plugins using the
+ * algorithm given above.
+ *
+ * Notice that %KTTSD will always pick a talker, even if it is a terrible match.
+ * (The principle is that something heard is better than nothing at all. If
+ * it sounds terrible, user will change his configuration.)
+ * If an attribute is absolutely mandatory -- in other words the application
+ * must speak with the attribute or not at all -- the application can determine if
+ * there are any talkers configured with the attribute by calling getTalkers,
+ * and if there are none, display an error message to the user.
+ *
+ * Applications can implement their own talker-matching algorithm by
+ * calling getTalkers, then finding the desired talker from the returned
+ * list. When the full talker code is passed in, %KKTSD will find an exact
+ * match and use the specified talker.
+ *
+ * If an application requires a configuration that user has not created,
+ * it should display a message to user instructing them to run kttsmgr and
+ * configure the desired talker. (This must be done interactively because
+ * plugins often need user assistance locating voice files, etc.)
+ *
+ * The above scheme is designed to balance the needs
+ * of applications against user preferences. Applications are given the control
+ * they @e might need, without unnecessarily burdening the application author.
+ * If you are an application author, the above discussion might seem overly
+ * complicated. It isn't really all that complicated. Here are rules of thumb:
+ *
+ * - It is legitimate to give a NULL (0) talker code, in which case, the user's default
+ * talker will be used.
+ * - If you know the language code, give that in the talker code, otherwise
+ * leave it out.
+ * - If there is an attribute your application @e requires for proper functioning,
+ * specify that with an asterisk in front of it. For example, your app might
+ * speak in two different voices, Male and Female. (Since your
+ * app requires both genders, call getTalkers to determine if both genders
+ * are available, and if not, advise user to configure them. Better yet,
+ * give the user a choice of available distinquishing attributes
+ * (loud/soft, fast/slow, etc.)
+ * - If there are other attributes you would prefer, specify those without an
+ * asterisk, but leave them out if it doesn't really make any difference
+ * to proper functioning of your application. Let the user decide them
+ * when they configure %KTTS.
+ *
+ * One final note about talkers. %KTTSD does talker matching for each sentence
+ * spoken, just before the sentence is sent to a plugin for synthesis. Therefore,
+ * the user can change the effective talker in mid processing of a text job by
+ * changing his preferences, or even deleting or adding new talkers to the configuration.
+ *
+ * @section markup Speech Markup
+ *
+ * Note: %Speech Markup is not yet fully implemented in %KTTSD.
+ *
+ * Each of the five methods for queueing text to be spoken -- sayScreenReaderOutput,
+ * setText, appendText, sayMessage, and sayWarning -- may contain speech markup,
+ * provided that the plugin the user has configured supports that markup. The markup
+ * languages and plugins currently supported are:
+ *
+ * - %Speech Synthesis Markup language (SSML): Festival and Hadifix.
+ *
+ * This may change in the future as synthesizers improve.
+ *
+ * Before including markup in the text sent to kttsd, the application should
+ * query whether the currently-configured plugin
+ * supports the markup language by calling supportsMarkup.
+ *
+ * It it does not support the markup, it will be stripped out of the text.
+ *
+ * @section markers Support for Markers
+ *
+ * Note: Markers are not yet implemented in %KTTSD.
+ *
+ * When using a speech markup language, such as Sable, JSML, or SSML, the application may embed
+ * named markers into the text. If the user's chosen speech plugin supports markers, %KTTSD
+ * will emit DCOP signal markerSeen when the speech engine encounters the marker.
+ * Depending upon the speech engine and plugin, this may occur either when the speech engine
+ * encounters the marker during synthesis from text to speech, or when the speech is actually
+ * spoken on the audio device. The calling application can call the supportsMarkers
+ * method to determine if the currently configured plugin supports markers or not.
+ *
+ * @section sentenceparsing Sentence Parsing
+ *
+ * Not all speech engines provide robust capabilities for stopping synthesis that is in progress.
+ * To compensate for this, %KTTSD parses text jobs given to it by the setText and
+ * appendText methods into sentences and sends the sentences to the speech
+ * plugin one at a time. In this way, should the user wish to stop the speech
+ * output, they can do so, and the worst that will happen is that the last sentence
+ * will be completed. This is called Sentence Boundary Detection (SBD).
+ *
+ * Sentence Boundary Detection also permits the user to rewind by sentences.
+ *
+ * The default sentence delimiter used for plain text is as follows:
+ *
+ * - A period (.), question mark (?), exclamation mark (!), colon (:), or
+ * semi-colon (;) followed by whitespace (including newline), or
+ * - Two newlines in a row separated by optional whitespace, or
+ * - The end of the text.
+ *
+ * When given text containing speech markup, %KTTSD automatically determines the markup type
+ * and parses based on the sentence semantics of the markup language.
+ *
+ * An application may change the sentence delimiter by calling setSentenceDelimiter
+ * prior to calling setText. Changing the delimiter does not affect other
+ * applications.
+ *
+ * Text given to %KTTSD via the sayWarning, sayMessage, and sayScreenReaderOutput
+ * methods is @e not parsed into sentences. For this reason, applications
+ * should @e not send long messages with these methods.
+ *
+ * Sentence Boundary Detection is implemented as a plugin SBD filter. See
+ * filters for more information.
+ *
+ * @section filters Filters
+ *
+ * Users may specify filters in the kttsmgr GUI. Filters are plugins that modify the text
+ * to be spoken or change other characteristics of jobs. Currently, the following filter plugins
+ * are available:
+ *
+ * - String Replacer. Permits users to substitute for mispoken words, or vocalize chat
+ * emoticons.
+ * - XML Transformer. Given a particular XML or XHTML format, permits conversion of the
+ * XML to SSML (Speech Synthesis Markup Language) using XSLT (XML Style Language - Transforms)
+ * stylesheets.
+ * - Talker Chooser. Permits users to redirect jobs from one configured Talker to another
+ * based on the contents of the job or application that sent it.
+ *
+ * Additional plugins may be available in the future.
+ *
+ * In additional to these regular filters, KTTS also implements Sentence Boundary Detection (SBD)
+ * as a plugin filter. See sentenceparsing for more information.
+ *
+ * Regular filters are applied to Warnings, Messages, and Text jobs. SBD filters are
+ * only applied to regular Text jobs; they are not applied to Warnings and Messages. Screen
+ * Reader Outputs are never filtered.
+ *
+ * @section authors Authors
+ *
+ * @author José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ * @author Gary Cramblitt <garycramblitt@comcast.net>
+ * @author Olaf Schmidt <ojschmidt@kde.org>
+ * @author Gunnar Schmi Dt <gunnar@schmi-dt.de>
+ */
+
+// NOTE: kspeech class is now obsolete. Please use KSpeech instead.
+
+class KSpeech : virtual public DCOPObject {
+ K_DCOP
+
+ public:
+ /**
+ * @enum kttsdJobState
+ * Job states returned by method getTextJobState.
+ */
+ enum kttsdJobState
+ {
+ jsQueued = 0, /**< Job has been queued but is not yet speakable. */
+ jsSpeakable = 1, /**< Job is speakable, but is not speaking. */
+ jsSpeaking = 2, /**< Job is currently speaking. */
+ jsPaused = 3, /**< Job has been paused. */
+ jsFinished = 4 /**< Job is finished and is deleteable. */
+ };
+
+ /**
+ * @enum kttsdMarkupType
+ * %Speech markup language types.
+ */
+ enum kttsdMarkupType
+ {
+ mtPlain = 0, /**< Plain text */
+ mtJsml = 1, /**< Java %Speech Markup Language */
+ mtSsml = 2, /**< %Speech Synthesis Markup Language */
+ mtSable = 3, /**< Sable 2.0 */
+ mtHtml = 4 /**< HTML @since 3.5 */
+ };
+
+ k_dcop:
+ /** @name DCOP Methods */
+ //@{
+
+ /**
+ * Determine whether the currently-configured speech plugin supports a speech markup language.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * @param markupType The kttsd code for the desired speech markup language.
+ * @return True if the plugin currently configured for the indicated
+ * talker supports the indicated speech markup language.
+ * @see kttsdMarkupType
+ */
+ virtual bool supportsMarkup(const QString &talker, uint markupType = 0) const = 0;
+
+ /**
+ * Determine whether the currently-configured speech plugin supports markers in speech markup.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * @return True if the plugin currently configured for the indicated
+ * talker supports markers.
+ */
+ virtual bool supportsMarkers(const QString &talker) const = 0;
+
+ /**
+ * Say a message as soon as possible, interrupting any other speech in progress.
+ * IMPORTANT: This method is reserved for use by Screen Readers and should not be used
+ * by any other applications.
+ * @param msg The message to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ *
+ * If an existing Screen Reader output is in progress, it is stopped and discarded and
+ * replaced with this new message.
+ */
+ virtual ASYNC sayScreenReaderOutput(const QString &msg, const QString &talker) = 0;
+
+ /**
+ * Say a warning. The warning will be spoken when the current sentence
+ * stops speaking and takes precedence over Messages and regular text. Warnings should only
+ * be used for high-priority messages requiring immediate user attention, such as
+ * "WARNING. CPU is overheating."
+ * @param warning The warning to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ */
+ virtual ASYNC sayWarning(const QString &warning, const QString &talker) = 0;
+
+ /**
+ * Say a message. The message will be spoken when the current sentence stops speaking
+ * but after any warnings have been spoken.
+ * Messages should be used for one-shot messages that can't wait for
+ * normal text messages to stop speaking, such as "You have mail.".
+ * @param message The message to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no talker has been configured for the specified talker code,
+ * defaults to the closest matching talker.
+ */
+ virtual ASYNC sayMessage(const QString &message, const QString &talker) = 0;
+
+ /**
+ * Sets the GREP pattern that will be used as the sentence delimiter.
+ * @param delimiter A valid GREP pattern.
+ *
+ * The default sentence delimiter is
+ @verbatim
+ ([\\.\\?\\!\\:\\;])(\\s|$|(\\n *\\n))
+ @endverbatim
+ *
+ * Note that backward slashes must be escaped.
+ * When %KTTSD parses the text, it replaces all tabs, spaces, and formfeeds
+ * with a single space, and then replaces the sentence delimiters using
+ * the following statement:
+ @verbatim
+ QString::replace(sentenceDelimiter, "\\1\t");
+ @endverbatim
+ *
+ * which replaces all sentence delimiters with a tab, but
+ * preserving the first capture text (first parenthesis). In other
+ * words, the sentence punctuation is preserved.
+ * The tab is later used to separate the text into sentences.
+ *
+ * Changing the sentence delimiter does not affect other applications.
+ *
+ * @see sentenceparsing
+ */
+ virtual ASYNC setSentenceDelimiter(const QString &delimiter) = 0;
+
+ /**
+ * Queue a text job. Does not start speaking the text.
+ * @param text The message to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default plugin.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ * @return Job number.
+ *
+ * Plain text is parsed into individual sentences using the current sentence delimiter.
+ * Call setSentenceDelimiter to change the sentence delimiter prior to
+ * calling setText.
+ * Call getTextCount to retrieve the sentence count after calling setText.
+ *
+ * The text may contain speech mark language, such as Sable, JSML, or SSML,
+ * provided that the speech plugin/engine support it. In this case,
+ * sentence parsing follows the semantics of the markup language.
+ *
+ * Call startText to mark the job as speakable and if the
+ * job is the first speakable job in the queue, speaking will begin.
+ *
+ * @see getTextCount
+ * @see startText
+ */
+ virtual uint setText(const QString &text, const QString &talker) = 0;
+
+ /**
+ * Say a plain text job. This is a convenience method that
+ * combines setText and startText into a single call.
+ * @param text The message to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default plugin.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ * @return Job number.
+ *
+ * Plain text is parsed into individual sentences using the current sentence delimiter.
+ * Call setSentenceDelimiter to change the sentence delimiter prior to
+ * calling setText.
+ * Call getTextCount to retrieve the sentence count after calling setText.
+ *
+ * The text may contain speech mark language, such as Sable, JSML, or SSML,
+ * provided that the speech plugin/engine support it. In this case,
+ * sentence parsing follows the semantics of the markup language.
+ *
+ * The job is marked speakable.
+ * If there are other speakable jobs preceeding this one in the queue,
+ * those jobs continue speaking and when finished, this job will begin speaking.
+ * If there are no other speakable jobs preceeding this one, it begins speaking.
+ *
+ * @see getTextCount
+ *
+ * @since KDE 3.5
+ */
+ virtual uint sayText(const QString &text, const QString &talker) = 0;
+
+ /**
+ * Adds another part to a text job. Does not start speaking the text.
+ * @param text The message to be spoken.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return Part number for the added part. Parts are numbered starting at 1.
+ *
+ * The text is parsed into individual sentences. Call getTextCount to retrieve
+ * the sentence count. Call startText to mark the job as speakable and if the
+ * job is the first speakable job in the queue, speaking will begin.
+ *
+ * @see setText.
+ * @see startText.
+ */
+ virtual int appendText(const QString &text, uint jobNum=0) = 0;
+
+ /**
+ * Queue a text job from the contents of a file. Does not start speaking the text.
+ * @param filename Full path to the file to be spoken. May be a URL.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ * @param encoding Name of the encoding to use when reading the file. If
+ * NULL or Empty, uses default stream encoding.
+ * @return Job number. 0 if an error occurs.
+ *
+ * Plain text is parsed into individual sentences using the current sentence delimiter.
+ * Call setSentenceDelimiter to change the sentence delimiter prior to calling setText.
+ * Call getTextCount to retrieve the sentence count after calling setText.
+ *
+ * The text may contain speech mark language, such as Sable, JSML, or SSML,
+ * provided that the speech plugin/engine support it. In this case,
+ * sentence parsing follows the semantics of the markup language.
+ *
+ * Call startText to mark the job as speakable and if the
+ * job is the first speakable job in the queue, speaking will begin.
+ *
+ * @see getTextCount
+ * @see startText
+ */
+ virtual uint setFile(const QString &filename, const QString &talker,
+ const QString& encoding) = 0;
+
+ /**
+ * Get the number of sentences in a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return The number of sentences in the job. -1 if no such job.
+ *
+ * The sentences of a job are given sequence numbers from 1 to the number returned by this
+ * method. The sequence numbers are emitted in the sentenceStarted and
+ * sentenceFinished signals.
+ */
+ virtual int getTextCount(uint jobNum=0) = 0;
+
+ /**
+ * Get the job number of the current text job.
+ * @return Job number of the current text job. 0 if no jobs.
+ *
+ * Note that the current job may not be speaking. See isSpeakingText.
+ *
+ * @see getTextJobState.
+ * @see isSpeakingText
+ */
+ virtual uint getCurrentTextJob() = 0;
+
+ /**
+ * Get the number of jobs in the text job queue.
+ * @return Number of text jobs in the queue. 0 if none.
+ */
+ virtual uint getTextJobCount() = 0;
+
+ /**
+ * Get a comma-separated list of text job numbers in the queue.
+ * @return Comma-separated list of text job numbers in the queue.
+ */
+ virtual QString getTextJobNumbers() = 0;
+
+ /**
+ * Get the state of a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return State of the job. -1 if invalid job number.
+ *
+ * @see kttsdJobState
+ */
+ virtual int getTextJobState(uint jobNum=0) = 0;
+
+ /**
+ * Get information about a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return A QDataStream containing information about the job.
+ * Blank if no such job.
+ *
+ * The stream contains the following elements:
+ * - int state - Job state.
+ * - QCString appId - DCOP senderId of the application that requested the speech job.
+ * - QString talker - Talker Code requested by application.
+ * - int seq - Current sentence being spoken. Sentences are numbered starting at 1.
+ * - int sentenceCount - Total number of sentences in the job.
+ * - int partNum - Current part of the job begin spoken. Parts are numbered starting at 1.
+ * - int partCount - Total number of parts in the job.
+ *
+ * Note that sequence numbers apply to the entire job. They do not start from 1 at the beginning of
+ * each part.
+ *
+ * The following sample code will decode the stream:
+ @code
+ QByteArray jobInfo = getTextJobInfo(jobNum);
+ QDataStream stream(jobInfo, IO_ReadOnly);
+ int state;
+ QCString appId;
+ QString talker;
+ int seq;
+ int sentenceCount;
+ int partNum;
+ int partCount;
+ stream >> state;
+ stream >> appId;
+ stream >> talker;
+ stream >> seq;
+ stream >> sentenceCount;
+ stream >> partNum;
+ stream >> partCount;
+ @endcode
+ */
+ virtual QByteArray getTextJobInfo(uint jobNum=0) = 0;
+
+ /**
+ * Given a Talker Code, returns the Talker ID of the talker that would speak
+ * a text job with that Talker Code.
+ * @param talkerCode Talker Code.
+ * @return Talker ID of the talker that would speak the text job.
+ */
+ virtual QString talkerCodeToTalkerId(const QString& talkerCode) = 0;
+
+ /**
+ * Return a sentence of a job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @param seq Sequence number of the sentence.
+ * @return The specified sentence in the specified job. If no such
+ * job or sentence, returns "".
+ */
+ virtual QString getTextJobSentence(uint jobNum=0, uint seq=0) = 0;
+
+ /**
+ * Determine if kttsd is currently speaking any text jobs.
+ * @return True if currently speaking any text jobs.
+ */
+ virtual bool isSpeakingText() const = 0;
+
+ /**
+ * Remove a text job from the queue.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * The job is deleted from the queue and the textRemoved signal is emitted.
+ *
+ * If there is another job in the text queue, and it is marked speakable,
+ * that job begins speaking.
+ */
+ virtual ASYNC removeText(uint jobNum=0) = 0;
+
+ /**
+ * Start a text job at the beginning.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * Rewinds the job to the beginning.
+ *
+ * The job is marked speakable.
+ * If there are other speakable jobs preceeding this one in the queue,
+ * those jobs continue speaking and when finished, this job will begin speaking.
+ * If there are no other speakable jobs preceeding this one, it begins speaking.
+ *
+ * The textStarted signal is emitted when the text job begins speaking.
+ * When all the sentences of the job have been spoken, the job is marked for deletion from
+ * the text queue and the textFinished signal is emitted.
+ */
+ virtual ASYNC startText(uint jobNum=0) = 0;
+
+ /**
+ * Stop a text job and rewind to the beginning.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * The job is marked not speakable and will not be speakable until startText
+ * or resumeText is called.
+ *
+ * If there are speaking jobs preceeding this one in the queue, they continue speaking.
+ *
+ * If the job is currently speaking, the textStopped signal is emitted,
+ * the job stops speaking, and if the next job in the queue is speakable, it
+ * begins speaking.
+ *
+ * Depending upon the speech engine and plugin used, speech may not stop immediately
+ * (it might finish the current sentence).
+ */
+ virtual ASYNC stopText(uint jobNum=0) = 0;
+
+ /**
+ * Pause a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * The job is marked as paused and will not be speakable until resumeText or
+ * startText is called.
+ *
+ * If there are speaking jobs preceeding this one in the queue, they continue speaking.
+ *
+ * If the job is currently speaking, the textPaused signal is emitted and the job
+ * stops speaking. Note that if the next job in the queue is speakable, it does
+ * not start speaking as long as this job is paused.
+ *
+ * Depending upon the speech engine and plugin used, speech may not stop immediately
+ * (it might finish the current sentence).
+ *
+ * @see resumeText
+ */
+ virtual ASYNC pauseText(uint jobNum=0) = 0;
+
+ /**
+ * Start or resume a text job where it was paused.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * The job is marked speakable.
+ *
+ * If the job is currently speaking, or is waiting to be spoken (speakable
+ * state), the resumeText() call is ignored.
+ *
+ * If the job is currently queued, or is finished, it is the same as calling
+ * @see startText .
+ *
+ * If there are speaking jobs preceeding this one in the queue,
+ * those jobs continue speaking and when finished this job will begin
+ * speaking where it left off.
+ *
+ * The textResumed signal is emitted when the job resumes.
+ *
+ * @see pauseText
+ */
+ virtual ASYNC resumeText(uint jobNum=0) = 0;
+
+ /**
+ * Get a list of the talkers configured in KTTS.
+ * @return A QStringList of fully-specified talker codes, one
+ * for each talker user has configured.
+ *
+ * @see talkers
+ */
+ virtual QStringList getTalkers() = 0;
+
+ /**
+ * Change the talker for a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @param talker New code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ */
+ virtual ASYNC changeTextTalker(const QString &talker, uint jobNum=0 ) = 0;
+
+ /**
+ * Get the user's default talker.
+ * @return A fully-specified talker code.
+ *
+ * @see talkers
+ * @see getTalkers
+ */
+ virtual QString userDefaultTalker() = 0;
+
+ /**
+ * Move a text job down in the queue so that it is spoken later.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * If the job is currently speaking, it is paused.
+ * If the next job in the queue is speakable, it begins speaking.
+ */
+ virtual ASYNC moveTextLater(uint jobNum=0) = 0;
+
+ /**
+ * Jump to the first sentence of a specified part of a text job.
+ * @param partNum Part number of the part to jump to. Parts are numbered starting at 1.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return Part number of the part actually jumped to.
+ *
+ * If partNum is greater than the number of parts in the job, jumps to last part.
+ * If partNum is 0, does nothing and returns the current part number.
+ * If no such job, does nothing and returns 0.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+ virtual int jumpToTextPart(int partNum, uint jobNum=0) = 0;
+
+ /**
+ * Advance or rewind N sentences in a text job.
+ * @param n Number of sentences to advance (positive) or rewind (negative) in the job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return Sequence number of the sentence actually moved to. Sequence numbers
+ * are numbered starting at 1.
+ *
+ * If no such job, does nothing and returns 0.
+ * If n is zero, returns the current sequence number of the job.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+ virtual uint moveRelTextSentence(int n, uint jobNum=0) = 0;
+
+ /**
+ * Add the clipboard contents to the text queue and begin speaking it.
+ */
+ virtual ASYNC speakClipboard() = 0;
+
+ /**
+ * Displays the %KTTS Manager dialog. In this dialog, the user may backup or skip forward in
+ * any text job by sentence or part, rewind jobs, pause or resume jobs, or
+ * delete jobs.
+ */
+ virtual void showDialog() = 0;
+
+ /**
+ * Stop the service.
+ */
+ virtual void kttsdExit() = 0;
+
+ /**
+ * Re-start %KTTSD.
+ */
+ virtual void reinit() = 0;
+
+ /**
+ * Return the KTTSD deamon version number.
+ * @since KDE 3.5
+ */
+ virtual QString version() = 0;
+ //@}
+
+ k_dcop_signals:
+ void ignoreThis();
+
+ /** @name DCOP Signals */
+ //@{
+
+ /**
+ * This signal is emitted when KTTSD starts or restarts after a call to reinit.
+ */
+ void kttsdStarted();
+ /**
+ * This signal is emitted just before KTTSD exits.
+ */
+ void kttsdExiting();
+ /**
+ * This signal is emitted when the speech engine/plugin encounters a marker in the text.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param markerName The name of the marker seen.
+ *
+ * @see markers
+ */
+ void markerSeen(const QCString& appId, const QString& markerName);
+ /**
+ * This signal is emitted whenever a sentence begins speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ *
+ * @see getTextCount
+ */
+ void sentenceStarted(const QCString& appId, uint jobNum, uint seq);
+ /**
+ * This signal is emitted when a sentence has finished speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ *
+ * @see getTextCount
+ */
+ void sentenceFinished(const QCString& appId, uint jobNum, uint seq);
+
+ /**
+ * This signal is emitted whenever a new text job is added to the queue.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textSet(const QCString& appId, uint jobNum);
+
+ /**
+ * This signal is emitted whenever a new part is appended to a text job.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ * @param partNum Part number of the new part. Parts are numbered starting
+ * at 1.
+ */
+ void textAppended(const QCString& appId, uint jobNum, int partNum);
+
+ /**
+ * This signal is emitted whenever speaking of a text job begins.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textStarted(const QCString& appId, uint jobNum);
+ /**
+ * This signal is emitted whenever a text job is finished. The job has
+ * been marked for deletion from the queue and will be deleted when another
+ * job reaches the Finished state. (Only one job in the text queue may be
+ * in state Finished at one time.) If startText or resumeText is
+ * called before the job is deleted, it will remain in the queue for speaking.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textFinished(const QCString& appId, uint jobNum);
+ /**
+ * This signal is emitted whenever a speaking text job stops speaking.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ *
+ * The signal is only emitted if stopText() is called and the job is currently
+ * speaking.
+ */
+ void textStopped(const QCString& appId, uint jobNum);
+ /**
+ * This signal is emitted whenever a speaking text job is paused.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textPaused(const QCString& appId, uint jobNum);
+ /**
+ * This signal is emitted when a text job, that was previously paused, resumes speaking.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textResumed(const QCString& appId, uint jobNum);
+ /**
+ * This signal is emitted whenever a text job is deleted from the queue.
+ * The job is no longer in the queue when this signal is emitted.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textRemoved(const QCString& appId, uint jobNum);
+ //@}
+};
+
+#endif // _KSPEECH_H_
diff --git a/kttsd/compat/interfaces/kspeech/kspeechsink.h b/kttsd/compat/interfaces/kspeech/kspeechsink.h
new file mode 100644
index 0000000..e90a005
--- /dev/null
+++ b/kttsd/compat/interfaces/kspeech/kspeechsink.h
@@ -0,0 +1,164 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ kspeechsink.h
+ KTTSD DCOP Signal Sink Interface
+ --------------------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+/**
+ * @interface KSpeechSink
+ *
+ * KTTSD DCOP Signal Sink
+ *
+ * @since KDE 3.4
+ *
+ * This defines the interface to sink signals emitted by KTTSD, the KDE Text-to-speech Deamon.
+ * The DCOP IDL Compiler generates a skeleton file from this interface definition that will
+ * marshal the arguments for you.
+ *
+ * @section Usage
+ *
+ * See the Signals section of kspeech.h for instructions.
+ *
+ * @warning The KSpeechSink interface is still being developed and is likely to change in the future.
+*/
+
+#ifndef _KSPEECHSINK_H_
+#define _KSPEECHSINK_H_
+
+#include <dcopobject.h>
+
+class KSpeechSink : virtual public DCOPObject {
+ K_DCOP
+
+ public:
+ /**
+ * @enum kttsdJobState
+ * Job states returned by method getTextJobState.
+ */
+ enum kttsdJobState
+ {
+ jsQueued = 0, /**< Job has been queued but is not yet speakable. */
+ jsSpeakable = 1, /**< Job is speakable, but is not speaking. */
+ jsSpeaking = 2, /**< Job is currently speaking. */
+ jsPaused = 3, /**< Job has been paused. */
+ jsFinished = 4 /**< Job is finished and is deleteable. */
+ };
+
+ /**
+ * @enum kttsdMarkupType
+ * %Speech markup language types.
+ */
+ enum kttsdMarkupType
+ {
+ mtPlain = 0, /**< Plain text */
+ mtJsml = 1, /**< Java %Speech Markup Language */
+ mtSmml = 2, /**< %Speech Markup Meta-language */
+ mtSable = 3 /**< Sable 2.0 */
+ };
+
+ k_dcop:
+ /**
+ * This signal is emitted when KTTSD starts or restarts after a call to reinit.
+ */
+ virtual ASYNC kttsdStarted() { };
+ /**
+ * This signal is emitted just before KTTSD exits.
+ */
+ virtual ASYNC kttsdExiting() { };
+
+ /**
+ * This signal is emitted when the speech engine/plugin encounters a marker in the text.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param markerName The name of the marker seen.
+ * @see markers
+ */
+ virtual ASYNC markerSeen(const QCString& appId, const QString& markerName) { Q_UNUSED(appId); Q_UNUSED(markerName); };
+ /**
+ * This signal is emitted whenever a sentence begins speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ * @see getTextCount
+ */
+ virtual ASYNC sentenceStarted(const QCString& appId, uint jobNum, uint seq) { Q_UNUSED(appId); Q_UNUSED(jobNum); Q_UNUSED(seq); };
+ /**
+ * This signal is emitted when a sentence has finished speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ * @see getTextCount
+ */
+ virtual ASYNC sentenceFinished(const QCString& appId, uint jobNum, uint seq) { Q_UNUSED(appId); Q_UNUSED(jobNum); Q_UNUSED(seq); };
+
+ /**
+ * This signal is emitted whenever a new text job is added to the queue.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ virtual ASYNC textSet(const QCString& appId, uint jobNum) { Q_UNUSED(appId); Q_UNUSED(jobNum); };
+
+ /**
+ * This signal is emitted whenever a new part is appended to a text job.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ * @param partNum Part number of the new part. Parts are numbered starting
+ * at 1.
+ */
+ virtual ASYNC textAppended(const QCString& appId, uint jobNum, int partNum) { Q_UNUSED(appId); Q_UNUSED(jobNum); Q_UNUSED(partNum); };
+
+ /**
+ * This signal is emitted whenever speaking of a text job begins.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ virtual ASYNC textStarted(const QCString& appId, uint jobNum) { Q_UNUSED(appId); Q_UNUSED(jobNum); };
+ /**
+ * This signal is emitted whenever a text job is finished. The job has
+ * been marked for deletion from the queue and will be deleted when another
+ * job reaches the Finished state. (Only one job in the text queue may be
+ * in state Finished at one time.) If startText or resumeText is
+ * called before the job is deleted, it will remain in the queue for speaking.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ virtual ASYNC textFinished(const QCString& appId, uint jobNum) { Q_UNUSED(appId); Q_UNUSED(jobNum); };
+ /**
+ * This signal is emitted whenever a speaking text job stops speaking.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ virtual ASYNC textStopped(const QCString& appId, uint jobNum) { Q_UNUSED(appId); Q_UNUSED(jobNum); };
+ /**
+ * This signal is emitted whenever a speaking text job is paused.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ virtual ASYNC textPaused(const QCString& appId, uint jobNum) { Q_UNUSED(appId); Q_UNUSED(jobNum); };
+ /**
+ * This signal is emitted when a text job, that was previously paused, resumes speaking.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ virtual ASYNC textResumed(const QCString& appId, uint jobNum) { Q_UNUSED(appId); Q_UNUSED(jobNum); };
+ /**
+ * This signal is emitted whenever a text job is deleted from the queue.
+ * The job is no longer in the queue when this signal is emitted.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ virtual ASYNC textRemoved(const QCString& appId, uint jobNum) { Q_UNUSED(appId); Q_UNUSED(jobNum); };
+};
+
+#endif // _KSPEECHSINK_H_
diff --git a/kttsd/configure.in.bot b/kttsd/configure.in.bot
new file mode 100644
index 0000000..b24a085
--- /dev/null
+++ b/kttsd/configure.in.bot
@@ -0,0 +1,65 @@
+if test "x$have_gst" = xno && test "x$with_gstreamer" != xno; then
+ echo "********************************************************"
+ echo "*"
+ echo "* You do not seem to have GStreamer >= 0.8.7 installed."
+ echo "*"
+ echo "* KTTSD supports GStreamer output but will also"
+ echo "* work with aRts, ALSA, and aKode"
+ echo "*"
+ echo "* PACKAGERS: Please do not include the gstreamer plugin"
+ echo "* in binary distributions of kdeaccessibility as it"
+ echo "* creates unwanted dependencies. Instead, include in a"
+ echo "* separate package, e.g., kdeaccessibility-extras."
+ echo "* The separate package should require gstreamer >= 0.8.7"
+ echo "*"
+ echo "********************************************************"
+fi
+if test "x$have_gst" = xyes && test "x$with_gstreamer" = xno; then
+ echo "********************************************************"
+ echo "*"
+ echo "* You seem to have GStreamer >= 0.8.7 installed."
+ echo "* but you did not choose to build the gstreamer plugin."
+ echo "* To enable GStreamer plugin, configure with"
+ echo "*"
+ echo "* --with-gstreamer"
+ echo "*"
+ echo "* KTTSD supports GStreamer output but will also"
+ echo "* work with aRts, ALSA, and aKode"
+ echo "*"
+ echo "* PACKAGERS: Please do not include the gstreamer plugin"
+ echo "* in binary distributions of kdeaccessibility as it"
+ echo "* creates unwanted dependencies. Instead, include in a"
+ echo "* separate package, e.g., kdeaccessibility-extras."
+ echo "* The separate package should require gstreamer >= 0.8.7"
+ echo "*"
+ echo "********************************************************"
+fi
+if test "x$have_gst" = xyes && test "x$with_gstreamer" != xno; then
+ echo "********************************************************"
+ echo "* The build of the GStreamer audio plugin has been enabled."
+ echo "*"
+ echo "* PACKAGERS: Please do not include the gstreamer plugin"
+ echo "* in binary distributions of kdeaccessibility as it"
+ echo "* creates unwanted dependencies. Instead, include in a"
+ echo "* separate package, e.g., kdeaccessibility-extras."
+ echo "* The separate package should require gstreamer >= 0.8.7"
+ echo "*"
+ echo "********************************************************"
+fi
+if test "x$have_alsa" = xno && test "x$with_alsa" = xcheck; then
+ echo "********************************************************"
+ echo "* The build of the KTTS ALSA audio plugin has been"
+ echo "* disabled because the ALSA sound library headers"
+ echo "* (alsa/asoundlib.h) were not found."
+ echo "*"
+ echo "********************************************************"
+fi
+if test "x$have_akode" = xno && test "x$with_akode" = xcheck; then
+ echo "********************************************************"
+ echo "* The build of the KTTS aKode audio plugin has been"
+ echo "* disabled because the aKode library configuration"
+ echo "* script (akode-config) was not found. The aKode libary"
+ echo "* is part of the kdesupport module."
+ echo "*"
+ echo "********************************************************"
+fi
diff --git a/kttsd/configure.in.in b/kttsd/configure.in.in
new file mode 100644
index 0000000..4adcfb1
--- /dev/null
+++ b/kttsd/configure.in.in
@@ -0,0 +1,304 @@
+#MIN_CONFIG(3.2)
+
+### AM_INIT_AUTOMAKE(kttsd,0.2.0)
+
+dnl ================================================================================
+
+dnl Check for GStreamer >= 0.8.7
+
+AC_ARG_WITH(gstreamer,
+ [AC_HELP_STRING(--with-gstreamer,
+ [enable support for GStreamer @<:@default=no@:>@])],
+ [], with_gstreamer=no)
+
+have_gst=no
+if test "x$with_gstreamer" != xno; then
+ # pkg-config seems to have a bug where it masks needed -L entries when it
+ # shouldn't, so disable that.
+
+ PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
+ export PKG_CONFIG_ALLOW_SYSTEM_LIBS
+
+ dnl start with 0.8
+ GST_MAJORMINOR=0.8
+ dnl Actually need 0.8.7, but plugins were version 0.8.5. argh!
+ GST_REQ=0.8.5
+
+ PKG_CHECK_MODULES(GST, \
+ gstreamer-$GST_MAJORMINOR >= $GST_REQ \
+ gstreamer-control-$GST_MAJORMINOR >= $GST_REQ \
+ gstreamer-libs-$GST_MAJORMINOR >= $GST_REQ,
+ have_gst=yes, have_gst=no)
+
+ if test "x$with_gstreamer" != xcheck && test "x$have_gst" != xyes; then
+ AC_MSG_ERROR([--with-gstreamer was given, but test for GStreamer >= 0.8.5 failed])
+ fi
+fi
+
+if test "x$have_gst" = "xno"; then
+ GST_CFLAGS=""
+ LDADD_GST=""
+ LDFLAGS_GST=""
+ AC_DEFINE(HAVE_GSTREAMER, 0, [have GStreamer])
+else
+ LDADD_GST=`$PKG_CONFIG --libs-only-l gstreamer-$GST_MAJORMINOR`
+ LDFLAGS_GST=`$PKG_CONFIG --libs-only-other gstreamer-$GST_MAJORMINOR`
+
+ # Append -L entries, since they are masked by --libs-only-l and
+ # --libs-only-other
+ LIBDIRS_GST=`$PKG_CONFIG --libs-only-L gstreamer-$GST_MAJORMINOR`
+ LDADD_GST="$LDADD_GST $LIBDIRS_GST"
+
+ AC_MSG_NOTICE([GStreamer version >= $GST_REQ found.])
+ AC_DEFINE(HAVE_GSTREAMER, 1, [have GStreamer])
+
+ if test "x$with_gstreamer" != xcheck && test "x$have_gst" != xyes; then
+ AC_MSG_ERROR([--with-gstreamer was given, but test for GStreamer >= 0.8.7 failed])
+ fi
+fi
+
+AC_SUBST(GST_CFLAGS)
+AC_SUBST(LDADD_GST)
+AC_SUBST(LDFLAGS_GST)
+
+AM_CONDITIONAL(include_kttsd_gstplayer, [test "x$have_gst" = "xyes"])
+
+dnl ================================================================================
+
+dnl Do not compile artsplayer plugin if user specifies --without-arts
+
+AM_CONDITIONAL(include_kttsd_artsplayer, [test "x$build_arts" = "xyes"])
+
+dnl ================================================================================
+
+dnl Check for ALSA.
+dnl TODO: Don't know if 0.5 works or not.
+
+AC_DEFUN([KDE_CHECK_ALSA],
+[
+ have_alsa=no
+
+ KDE_CHECK_HEADERS([sys/asoundlib.h alsa/asoundlib.h],
+ [have_alsa=yes])
+
+ KDE_CHECK_LIB(asound, snd_seq_create_simple_port,
+ [:], [have_alsa=no])
+
+ AC_LANG_SAVE
+ AC_LANG_C
+ if test "x$have_alsa" = xyes; then
+ AC_TRY_COMPILE([
+ #include "confdefs.h"
+ #ifdef HAVE_SYS_ASOUNDLIB_H
+ #include <sys/asoundlib.h>
+ #endif
+ #ifdef HAVE_ALSA_ASOUNDLIB_H
+ #include <alsa/asoundlib.h>
+ #endif
+ ],[
+ #if (SND_LIB_MAJOR == 0) && (SND_LIB_MINOR == 5)
+ /* we have ALSA 0.5.x */
+ #else
+ #error not ALSA 0.5.x
+ #endif
+ ],
+ have_alsa_0_5=yes)
+
+ AC_TRY_COMPILE([
+ #include "confdefs.h"
+ #ifdef HAVE_SYS_ASOUNDLIB_H
+ #include <sys/asoundlib.h>
+ #endif
+ #ifdef HAVE_ALSA_ASOUNDLIB_H
+ #include <alsa/asoundlib.h>
+ #endif
+ ],[
+ #if (SND_LIB_MAJOR == 0) && (SND_LIB_MINOR == 9)
+ /* we have ALSA 0.9.x */
+ #else
+ #error not ALSA 0.9.x
+ #endif
+ ],
+ have_alsa_0_9=yes)
+
+ AC_TRY_COMPILE([
+ #include "confdefs.h"
+ #ifdef HAVE_SYS_ASOUNDLIB_H
+ #include <sys/asoundlib.h>
+ #endif
+ #ifdef HAVE_ALSA_ASOUNDLIB_H
+ #include <alsa/asoundlib.h>
+ #endif
+ ],[
+ #if (SND_LIB_MAJOR == 1)
+ /* we have ALSA 1.x */
+ #else
+ #error not ALSA 1.x
+ #endif
+ ],
+ have_alsa_1=yes)
+ fi
+ AC_LANG_RESTORE
+
+ if test "x$have_alsa_0_9" = xyes || test "x$have_alsa_1" = xyes; then
+ # for kmix/ and akode/
+ LIBASOUND="-lasound"
+ AC_DEFINE(HAVE_LIBASOUND2, 1, [Define if you have libasound.so.2 (required for ALSA 0.9.x/1.x support)])
+
+ # for arts/
+ ARTS_LIBASOUND="-lasound"
+ AC_DEFINE(HAVE_ARTS_LIBASOUND2, 1, [Define if you have libasound.so.2 (required for ALSA 0.9.x/1.x support)])
+ fi
+
+ if test "x$have_alsa_0_5" = xyes; then
+ # for arts/
+ ARTS_LIBASOUND="-lasound"
+ AC_DEFINE(HAVE_ARTS_LIBASOUND, 1, [Define if you have libasound.so.1 (required for ALSA 0.5.x support)])
+ fi
+
+ AC_SUBST(LIBASOUND)
+ AC_SUBST(ARTS_LIBASOUND)
+])
+
+AC_ARG_WITH(alsa,
+ [AC_HELP_STRING(--with-alsa,
+ [enable support for ALSA @<:@default=check@:>@])],
+ [], with_alsa=check)
+
+have_alsa=no
+if test "x$with_alsa" != xno; then
+ KDE_CHECK_ALSA
+
+ if test "x$with_alsa" != xcheck && test "x$have_alsa" != xyes; then
+ AC_MSG_ERROR([--with-alsa was given, but test for ALSA failed])
+ fi
+fi
+
+AM_CONDITIONAL(include_kttsd_alsaplayer, [test "x$have_alsa" = "xyes"])
+
+dnl ================================================================================
+
+dnl Check for aKode library. Note: As of about 16 Jul 2005, it got moved
+dnl from kdemultimedia to kdesupport.
+
+AC_DEFUN([KDE_CHECK_AKODE],
+[
+ AC_PATH_PROG(AKODE_CONFIG, akode-config, [no], [$PATH:$prefix/bin])
+
+ if test "x$AKODE_CONFIG" != xno; then
+ AC_DEFINE(HAVE_AKODE, 1, [define if you have aKodelib installed])
+ akode_includes=`$AKODE_CONFIG --cflags`
+ akode_libs=`$AKODE_CONFIG --libs`
+ have_akode=yes
+ else
+ akode_includes=""
+ akode_libs=""
+ have_akode=no
+ fi
+
+ AC_SUBST(akode_includes)
+ AC_SUBST(akode_libs)
+])
+
+AC_ARG_WITH(akode,
+ [AC_HELP_STRING([--with-akode],
+ [enable the aKode decoder @<:@default=no@:>@])],
+ [], with_akode=no)
+
+have_akode=no
+if test "x$with_akode" != xno; then
+ KDE_CHECK_AKODE
+
+ if test "x$with_akode" != xcheck && test "x$have_akode" != xyes; then
+ AC_MSG_ERROR([--with-akode was given, but test for aKode failed])
+ fi
+fi
+
+AM_CONDITIONAL(include_kttsd_akodeplayer, [test "x$have_akode" = "xyes"])
+
+dnl ================================================================================
+
+dnl Check whether to include sys/time.h and time.h, or just sys/time.h.
+dnl Defines TIME_WITH_SYS_TIME and HAVE_SYS_TIME_H, which are used in
+dnl alsaplayer.cpp.
+
+AC_HEADER_TIME
+AC_CHECK_HEADERS(sys/time.h)
+
+dnl ================================================================================
+
+dnl See if the latest kspeech.h is installed and if not, compile against
+dnl kttsd/compat directory.
+
+if test "$KTTS_KSPEECH_DIR" = ""; then
+ KDE_CHECK_HEADER(kspeech.h, ktts_have_kspeech_h=yes, ktts_have_kspeech_h=no)
+ have_latest_kspeech=no
+ if test "x$ktts_have_kspeech_h" = xyes; then
+ AC_MSG_CHECKING([whether installed kspeech.h is latest version])
+ ktts_save_cppflags=$CPPFLAGS
+ AC_LANG_SAVE
+ CPPFLAGS="$all_includes $CPPFLAGS"
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE(
+ [#include <kspeech.h>],
+ [
+ if (4 == KSpeech::mtHtml);
+ ],
+ have_latest_kspeech=yes,
+ have_latest_kspeech=no)
+ AC_MSG_RESULT($have_latest_kspeech)
+ CPPFLAGS=$ktts_save_cppflags
+ AC_LANG_RESTORE
+ fi
+ if test "x$have_latest_kspeech" = xyes; then
+ KTTS_KSPEECH_DIR='$(kde_includes)'
+ KTTS_KSPEECH_INCLUDE=""
+ KTTS_INTERFACES_DIR=""
+ else
+ KTTS_KSPEECH_DIR='$(top_srcdir)/kttsd/compat/interfaces/kspeech'
+ KTTS_KSPEECH_INCLUDE='-I$(top_srcdir)/kttsd/compat/interfaces/kspeech'
+ KTTS_INTERFACES_DIR="interfaces"
+ AC_MSG_WARN([Latest kspeech.h not installed. Compiling using kttsd/compat directory.])
+ fi
+
+ AC_SUBST(KTTS_KSPEECH_DIR)
+ AC_SUBST(KTTS_KSPEECH_INCLUDE)
+ AC_SUBST(KTTS_INTERFACES_DIR)
+fi
+
+dnl ================================================================================
+
+# --- Check for KDE < 3.5 ---
+# If so, install icons.
+
+AC_MSG_CHECKING([for KDE version])
+
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+kdeversion_save_CXXFLAGS="$CXXFLAGS"
+kdeversion_save_LIBS="$LIBS"
+LIBS="$LIBS $X_EXTRA_LIBS"
+CXXFLAGS="$CXXFLAGS $all_includes"
+
+AC_COMPILE_IFELSE([
+#include <kdeversion.h>
+#if ! ( KDE_IS_VERSION( 3, 4, 90 ) )
+#error KDE 3.4
+#endif
+],
+ KTTS_ICONS_DIR=""
+,
+ KTTS_ICONS_DIR="icons"
+)
+
+CXXFLAGS="$kdeversion_save_CXXFLAGS"
+LIBS="$kdeversion_save_LIBS"
+AC_LANG_RESTORE
+
+if test "$KTTS_ICONS_DIR" = ""; then
+ AC_MSG_RESULT([KDE 3.4.x or less])
+else
+ AC_MSG_RESULT([KDE 3.5 or later])
+fi
+
+AC_SUBST(KTTS_ICONS_DIR)
diff --git a/kttsd/cvs2dist b/kttsd/cvs2dist
new file mode 100755
index 0000000..da2c08d
--- /dev/null
+++ b/kttsd/cvs2dist
@@ -0,0 +1,634 @@
+#! /bin/bash
+
+# This is cvs2dist
+# Webpage: http://www.katzbrown.com/shiritsu/programming/cvs2dist/
+# Newest version is always available there!
+# Please report bugs to <jason@katzbrown.com>.
+
+# Original author (of cvs2pack.sh) was Sebastian Stein <seb.stein@hpfsc.de>
+# Heavy, heavy modifications by Jason Katz-Brown <jason@katzbrown.com>
+# Some modifications for i18n inclusion by Dominique Devriese <devriese@kde.org>
+# Added --no-i18n-lang and --replace-files by Michael Buesch <mbuesch@freenet.de>
+# License: GPL (http://www.gnu.org/)
+# Last modification: 2004/10/13
+
+cmdline="$@"
+
+returndir=`pwd`
+override="README ChangeLog INSTALL AUTHORS AUTHOR COPYING COPYING.LIB TODO"
+remove="config.cache config.log config.status Makefile configure inst-apps CVS acinclude.m4 aclocal.m4 config.h config.h.bot config.h.in configure.files libtool stamp-h stamp-h.in stamp-h1 subdirs *.moc *.la .libs .deps .cvsignore autom4te.cache {arch} .arch-ids"
+toplevelremove="configure.in.bot"
+# whitespace seperated list of languages to never include.
+always_skip_languages="xx"
+
+pofilenames="kttsd kttsd_commandplugin kttsd_eposplugin kttsd_festivalintplugin
+kttsd_fliteplugin kttsd_freettsplugin kttsd_hadifixplugin kttsd_sbdplugin
+kttsd_stringreplacerplugin kttsd_talkerchooserplugin kttsd_xmltransformerplugin
+kttsjobmgr kttsmgr kcmkttsd khtmlkttsd ktexteditor_kttsd"
+
+exit_cleanup()
+{
+ echo -n "Cleaning up... "
+ if [ -d $temp_dir ]; then
+ test -z "$debug" && rm -Rf $temp_dir
+ fi
+ echo "done."
+}
+
+trap "exit_cleanup; exit 1" SIGINT SIGTERM
+
+test -e ~/.cvs2distrc && extraoptions=`cat ~/.cvs2distrc`
+
+# getopt usage from the getopt bash example
+# --log has optional argument
+TEMP=`getopt \
+-o v:n:r:e:a:B:dhmbgol \
+--long log::,version:,name:,required-header:,required-header-error-message:,make-unpackaged,help,no-bz2,no-bzip2,no-gzip,only-directory,remove-hidden,admin-dir:,branch:,no-i18n,no-i18n-lang:,cvs-root:,debug,replace-files: \
+-n cvs2dist -- $extraoptions "$@"`
+
+if [ $? != 0 ]; then
+ echo "Aborted." >&2
+ exit 1
+fi
+
+eval set -- "$TEMP"
+
+log="/dev/null"
+calclog=0
+doi18n="yes"
+noi18nlang=""
+replace_files=""
+cvsroot=""
+debug=""
+
+while true; do
+ case "$1" in
+ -v|--version) version=$2; shift 2 ;;
+ -n|--name) name=$2; shift 2 ;;
+ -a|--admin-dir) admindir=$2;
+ if [ `echo $admindir | sed -e 's#^/##'` = $admindir ]; then
+ admindir="`pwd`/$admindir"
+ fi
+ shift 2 ;;
+ -B|--branch) branch="-r$2"; shift 2;;
+ --debug) debug="non-empty"; shift 1 ;;
+ --cvs-root) cvsroot="$2"; shift 2 ;;
+ -r|--required-header) requiredheader=$2; shift 2 ;;
+ --no-i18n) doi18n="no"; shift 1 ;;
+ --no-i18n-lang) noi18nlang="$2"; shift 2 ;;
+ -e|--required-header-error-message) requiredmsg=$2; shift 2 ;;
+ -m|--make-unpackaged) leavedir="non-empty"; shift 1 ;;
+ -h|--help) showhelp="non-empty"; shift 1 ;;
+ -b|--no-bz2|--no-bzip2) nobzip2="non-empty"; shift 1 ;;
+ -o|--only-directory)
+ nogzip="non-empty"
+ nobzip2="non-empty"
+ leavedir="non-empty"
+ shift 1 ;;
+ -g|--no-gzip) nogzip="non-empty"; shift 1 ;;
+ -d|--remove-hidden) removehidden="non-empty"; shift 1 ;;
+ -l) calclog=1; shift 1 ;;
+ --log)
+ case "$2" in
+ # no-argument case
+ "") calclog=1; shift 2 ;;
+ # something, should be a file
+ *) log=$2
+ origlog=$log
+ if [ `echo $log | sed -e 's#^/##'` = $log ]; then
+ log="`pwd`/$log"
+ fi
+
+ shift 2 ;;
+ esac ;;
+ --replace-files) replace_files="$2"; shift 2 ;;
+ --) shift
+ break ;;
+ *) echo "Aborted."
+ exit 1 ;;
+ esac
+done
+
+count=0
+for arg do
+ test $count = 0 && module=$arg
+ test $count = 1 && directory=$arg
+
+ if [ $count -ge 2 ]; then
+ modarg=$arg
+ if [ `echo $modarg | sed -e 's#^/##'` = $modarg ]; then
+ modarg="`pwd`/$modarg"
+ fi
+ addfiles="$addfiles $modarg"
+ fi
+
+ let count count++
+done
+
+# test if a module and directory name was given
+if [ ! -z $showhelp ] || [ -z $module ] || [ -z $directory ]; then
+ echo "Usage: cvs2dist module directory [options] [addfile1] [addfile2] ..."
+ echo ""
+ echo " -n --name <name>"
+ echo " -v --version <version>"
+ echo " --cvs-root <root> the value to use as cvs root"
+ echo " variable. It is not necessary if you use --no-i18n."
+ echo " if this is not given, it is taken from the CVSROOT "
+ echo " environment variable."
+ echo " --admin-dir <dir> admin/ location (default is module/admin)"
+ echo " (symbolic links are OK.)"
+ echo " -B --branch <branch> use branch for i18n checkouts."
+ echo " --no-i18n don't try to automatically checkout the translations from cvs."
+ echo " --no-i18n-lang <languages> exclude all languages in the given comma"
+ echo " seperated list. example:"
+ echo " --no-i18n-lang uk,de,en_GB"
+ echo " --log=<logfile> If logfile unspecified, default file is used."
+ echo " (The '=' is essential and may not be ommited"
+ echo " when specifying the logfile.)"
+ echo " -l Log to default logfile."
+ echo " -m --make-unpackaged Also makes an unpacked distribution"
+ echo " in the current directory."
+ echo " -g --no-gzip Do not create gzip package."
+ echo " -b --no-bz2 Do not create bzip2 package."
+ echo " --no-bzip2 Alias for the above."
+ echo " -o --only-directory Alias for -mbg (no packages, only a directory.)"
+ echo " -r --required-header <header> Errors if header is not installed."
+ echo " -e --required-header-error-message <message>"
+ echo " Error message for above."
+ echo " -d --remove-hidden Remove hidden files/directories from packages"
+ echo " --replace-files <file-pair-list>"
+ echo " <file-pair-list> is a comma separated list of file pairs"
+ echo " which should be replaced in the final distribution package."
+ echo " Each element of a pair is separated by an @"
+ echo -n " Example: --replace-files take_this_file@and_move_it_here,"
+ echo "configure.in.bot.dist@configure.in.bot"
+ echo " The filenames are all relative to your package root."
+ echo " Please be careful! Try to avoid the usage of .. in the path. It"
+ echo " may break stuff! There can not be blank characters in the paths."
+ echo " -h --help Show this help"
+ echo ""
+ echo " Name defaults to the last part of the directory."
+ echo "By default, creates name[-version].tar.gz if gzip is installed"
+ echo "and/or name[-version].tar.bz2 if bzip2 is installed in the current"
+ echo "directory. Removes all temporary files it creates. Produces"
+ echo "tarballs that are standard distribution tarballs with a"
+ echo "configure script."
+ echo " Unless --no-i18n is given, it automatically tries to check out "
+ echo "strings and documentation translation from cvs."
+ echo " Arguments after the second are added to the toplevel directory"
+ echo "in the package. Short options can be combined, eg -dm to create"
+ echo "a directory and remove hidden files. ~/.cvs2distrc is added to"
+ echo "the beginning of command line arguments if it exists."
+ echo " '--' signifies the end of options."
+ echo ""
+ echo "Example: cvs2dist /sources/kdegames kolf/objects/picture \\"
+ echo " -n kolf-picture -v 0.9 -r \"kolf/game.h\" \\"
+ echo " --log ~/tmp/extra-file"
+ echo ""
+ echo " Creates packages of the kolf picture plugin, naming the"
+ echo " packages kolf-picture-0.9 and logging the process. For configure"
+ echo " to succeed, kolf/game.h must be installed or an error will occur."
+ echo " ~/tmp/extra-file is added to the packages."
+ echo ""
+ echo "Webpage: http://www.katzbrown.com/shiritsu/programming/cvs2dist/"
+ echo "Authors: Jason Katz-Brown <jason@katzbrown.com>,"
+ echo " Sebastian Stein <seb.stein@hpfsc.de>,"
+ echo " Dominique Devriese <devriese@kde.org>"
+ exit 1
+fi
+
+# expand module
+module=`echo $module | sed -e 's#/$##'`
+if [ `echo $module | sed -e 's#^/##'` = $module ]; then
+ module="`pwd`/$module"
+fi
+
+# test if the given module is a directory
+test -d $module
+if [ $? -ne 0 ]; then
+ echo "$module is not a directory."
+ echo "Aborted."
+ exit 1
+fi
+
+# go to our module
+cd $module
+
+directory=`echo $directory | sed -e 's#^/##'`
+
+if [ -z $name ]; then
+ name=$directory
+ # get rid of trailing slash
+ name=`echo $name | sed -e 's#/$##'`
+ # leading slash
+ name=`echo $name | sed -e 's#^/##'`
+
+ if [ `echo $name | sed -e 's#/##'` != $name ]; then
+ name=`echo $name | sed -e 's#^.*/##'`
+ fi
+fi
+
+test $calclog = 1 && log="$returndir/cvs2dist-$name.log" && origlog="cvs2dist-$name.log"
+
+# test if the given name is a sub-directory
+if [ ! -d "$directory" ]; then
+ echo "$directory is not a sub-directory of $module."
+ echo "Aborted."
+ exit 1
+fi
+
+test $log != "/dev/null" && echo "Logging to $log."
+
+echo "cvs2dist log on "`date` > $log
+echo "http://katzbrown.com/shiritsu/programming/cvs2dist/" >> $log
+echo -n "Module: $module; Directory: $directory; Name: $name; " >> $log
+if [ -z $version ]; then
+ echo "Version unspecified." >> $log
+else
+ echo "Version $version." >> $log
+fi
+echo $cmdline >> $log
+echo "--------" >> $log
+
+if [ -z $version ]; then
+ filename=$name
+else
+ filename="$name-$version"
+fi
+
+if [ -z $cvsroot ]; then
+ cvsroot="$CVSROOT";
+fi
+if [ $doi18n = "yes" ]; then
+ # a little warning...
+ echo "Will try to fetch i18n files from KDE's CVS."
+ echo "If this doesn't work, use --no-i18n."
+
+ if [ -z "$cvsroot" ]; then
+ echo "No cvs root specified, CVSROOT env var is empty, " >> $log
+ echo "and --no-i18n option is not given.." >> $log
+ echo "Using anonymous cvs.." >> $log
+ cvsroot=":pserver:anonymous@anoncvs.kde.org:/home/kde"
+ # append an entry to ~/.cvspass so the user will not be asked
+ # for a pwd. Thanks to coolo for the idea..
+ if ! grep "anoncvs.kde.org" ~/.cvspass >/dev/null 2>&1; then
+ echo "/1 :pserver:anonymous@anoncvs.kde.org:2401/home/kde A" >> ~/.cvspass
+ fi
+ fi
+fi
+
+# the temporary directory
+temp_dir="$module/cvs2dist-tmp"
+temp_dist="$temp_dir/$filename"
+
+echo "Temporary directory is $temp_dir." >> $log
+
+# make a temporary directory
+test -d $temp_dir && rm -Rf $temp_dir
+
+mkdir -p $temp_dist
+
+# check if we were able to create temp_dir
+test -d $temp_dist
+if [ $? -ne 0 ]; then
+ echo "Could not create temporary directory $temp_dist."
+ echo "$temp_dist could not be created." >> $log
+ echo "Aborted."
+ exit 1
+fi
+
+test -z "$requiredmsg" && requiredmsg="Install development package needed first! $requiredheader, for one, is missing."
+
+### configure.in.in
+if [ ! -z $requiredheader ]; then
+ naiyou="KDE_CHECK_HEADER(
+$requiredheader,
+[],
+[AC_MSG_ERROR(\"$requiredmsg\")]
+)"
+ echo $naiyou > $temp_dir/configure.in.in
+ echo "configure.in.in contents: " >> $log
+ echo "--------" >> $log
+ echo $naiyou >> $log
+ appaddfiles="$appaddfiles $temp_dir/configure.in.in"
+fi
+
+# copy all files of the module to temp_dir/name
+cp -RL $module/$directory $temp_dist/$name
+
+echo "cp -R $module/$directory $temp_dist/$name" >> $log
+
+modulename="$module"
+# get rid of trailing slash
+modulename=`echo $modulename | sed -e 's#/$##'`
+# get the last part
+modulename=`echo $modulename | sed -e 's#^.*/##'`
+
+remove="$remove $modulename.lsm"
+
+# we check out kde-i18n/subdirs in temp_dir/kde-i18n..
+if [ $doi18n = "yes" ]; then
+ pushd $temp_dir
+ echo "cvs co kde-i18n/subdirs" >> $log
+ cvs -z4 -q -d "$cvsroot" co $branch -P kde-i18n/subdirs > /dev/null 2>&1
+ i18nlangs_tmp="$(cat kde-i18n/subdirs)"
+ skiplist="`echo $noi18nlang | sed -e 's/,/ /g'`"
+ skiplist="$skiplist $always_skip_languages"
+ for lang in $i18nlangs_tmp; do
+ must_skip="no"
+ for skip in $skiplist; do
+ if [ "$lang" = "$skip" ]; then
+ must_skip="yes"
+ fi
+ done
+ if [ "$must_skip" = "no" ]; then
+ i18nlangs="$i18nlangs $lang"
+ fi
+ done
+ echo "available languages: $i18nlangs" >> $log
+ popd
+fi
+
+# if a handbook exists, we also copy it to the directory
+if [ -d $module/doc/$name ]; then
+ mkdir -p $temp_dist/doc/$name
+ cp -Rf $module/doc/$name $temp_dist/doc
+ find $module/doc/ ! -xtype d -maxdepth 1 | xargs --replace={} cp {} $temp_dist/doc
+
+ if [ $doi18n = "yes" ]; then
+ pushd $temp_dir
+ for lang in $i18nlangs; do
+ test -d $temp_dist/doc/$lang && rm -Rf $temp_dist/doc/$lang
+ docdirname="kde-i18n/$lang/docs/$modulename/$name"
+ echo "cvs co $docdirname" >> $log
+ cvs -z4 -q -d "$cvsroot" co $branch -P "$docdirname" > /dev/null 2>&1
+ if [ ! -d "$docdirname" ]; then
+ echo "$lang's $name documentation does not exist." >> $log
+ continue
+ fi
+ echo -n "Copying $lang's $name documentation over... "
+ cp -R $docdirname $temp_dist/doc/$lang
+ # we don't want KDE_DOCS = AUTO, cause that makes the
+ # build system assume that the name of the app is the
+ # same as the name of the dir the Makefile.am is in.
+ # Instead, we explicitly pass the name..
+ cat $temp_dist/doc/$lang/Makefile.am | sed -e "s/AUTO/$name/" > $temp_dist/doc/$lang/Makefile.am.nw
+ mv $temp_dist/doc/$lang/Makefile.am.nw $temp_dist/doc/$lang/Makefile.am
+ echo "done."
+ echo "$lang documentation included." >> $log
+ done
+ popd
+ fi
+fi
+
+# clean up doc directory
+if [ -d $temp_dist/doc/$name ]; then
+ pushd $temp_dist/doc/$name
+ echo -n "make clean in $temp_dist/doc/$name/... "
+ echo >> $log
+ echo "make clean in $temp_dist/doc/$name/" >> $log
+ make clean >> $log
+ echo "--------" >> $log
+ echo "done."
+ popd
+fi
+
+if [ $doi18n = "yes" ]; then
+ test -d $temp_dist/po && rm -Rf $temp_dist/po
+ mkdir $temp_dist/po
+
+ pushd $temp_dir/
+ for lang in $i18nlangs; do
+ dest=$temp_dist/po/$lang
+ for poname in $pofilenames; do
+ pofilename="kde-i18n/$lang/messages/$modulename/$poname.po";
+ echo "cvs co $pofilename" >> $log
+ cvs -z4 -q -d "$cvsroot" co $branch -P "$pofilename" > /dev/null 2>&1
+ if [ ! -f "$pofilename" ]; then
+ echo "$lang's $poname.po does not exist." >> $log
+ continue
+ fi
+
+ if [ ! -d $dest ]; then
+ mkdir $dest
+ fi
+ echo -n "Copying $lang's $poname.po over... "
+ echo "$lang's $poname.po file included." >> $log
+ cp $pofilename $dest
+ done
+ echo "done."
+
+ echo "KDE_LANG = $lang
+SUBDIRS = \$(AUTODIRS)
+POFILES = AUTO" > $dest/Makefile.am
+
+ subdirs="non_empty"
+ done
+
+ if [ -z "$subdirs" ]; then
+ rm -Rf $temp_dist/po
+ else
+ echo "SUBDIRS = \$(AUTODIRS)" > $temp_dist/po/Makefile.am
+ fi
+fi
+
+# copy the admin directory
+if [ -z $admindir ]; then
+ cp -pRL $module/admin $temp_dist
+ echo "cp -pRL $module/admin $temp_dist" >> $log
+else
+ cp -pRL $admindir $temp_dist
+ echo "cp -pRL $admindir $temp_dist" >> $log
+fi
+
+# and all files from the base dir, except directories
+echo "Copying over files from the module directory:" >> $log
+find $module ! -xtype d -maxdepth 1 | xargs --verbose --replace={} cp {} $temp_dist 2>> $log
+echo "--------" >> $log
+
+# we now enter the temp_dist and delete all unwanted files
+# and add wanted files
+cd $temp_dist
+
+# override top-level files
+echo "Override files: " >> $log
+for file in $override; do
+ test -e $temp_dist/$name/$file && mv $temp_dist/$name/$file . && echo "mv $temp_dist/$name/$file ." >> $log
+done
+
+test ! -z "$addfiles" && echo "Addfiles: " >> $log
+for file in $addfiles; do
+ test -e $file && cp -R $file $temp_dist && echo "cp -R $file $temp_dist" >> $log
+done
+
+test ! -z "$appaddfiles" && echo "Application addfiles: " >> $log
+for file in $appaddfiles; do
+ test -e $file && cp -R $file $temp_dist/$name/ && echo "cp -R $file $temp_dist/$name/" >> $log
+done
+
+echo "--------" >> $log
+
+# replace all user requested files
+if [ -n "$replace_files" ]; then
+ echo "Replace user requested files" >> $log
+ pair_list="`echo $replace_files | sed -e 's/,/ /g'`"
+ for pair in $pair_list; do
+ pair_tmp="`echo $pair | sed -e 's/@/ /g'`"
+ from="`echo $pair_tmp | awk '//{print $1}'`"
+ to="`echo $pair_tmp | awk '//{print $2}'`"
+ if [ -z "$from" ] || [ -z "$to" ]; then
+ echo "bogus pair \"$from@$to\"" >> $log
+ continue
+ fi
+ echo "Replacing \"$to\" by \"$from\"" >> $log
+ from_path="$temp_dist/$name/$from"
+ to_path="$temp_dist/$name/$to"
+ if [ ! -f "$from_path" ]; then
+ echo "$from_path does not exist!" >> $log
+ echo ""
+ echo "Warning: \"$from\" does not exist!"
+ echo -n "Please enter the path in --replace-files relative "
+ echo "to the package root of your project."
+ echo "Your package root is: \"$module/$directory\""
+ echo ""
+ continue
+ fi
+ rm -f "$to_path" && \
+ mv "$from_path" "$to_path"
+ if [ $? -ne 0 ]; then
+ echo -n "Moving \"$from_path\" failed! " >> $log
+ echo -n "This should not happen." >> $log
+ if [ -f "$to_path" ]; then
+ echo ""
+ else
+ echo " No \"$to\" will exist in the archive!" >> $log
+ fi
+ fi
+ done
+ echo "--------" >> $log
+fi
+
+# version file, if it doesn't exist
+test ! -z $version && test ! -e VERSION && echo "$name version $version" > VERSION
+
+cd $temp_dist/$name
+echo "make clean in $temp_dist/$name/:" >> $log
+echo "" >> $log
+echo -n "make clean in $temp_dist/$name/... "
+make clean >> $log
+echo "--------" >> $log
+echo "done."
+
+cd $temp_dist
+
+# remove files
+echo "Remove files: " >> $log
+for file in $remove; do
+ find . -name $file | xargs rm -Rf
+ echo "find . -name $file | xargs rm -Rf" >> $log
+done
+
+# remove more files
+echo "Remove toplevel files: " >> $log
+for file in $toplevelremove; do
+ test -e $file && rm -Rf $file && echo "rm -Rf $file" >> $log
+done
+unset file
+
+# remove hidden files
+test ! -z $removehidden && echo "Remove hidden files: " >> $log && find $temp_dist -name ".*" -and ! -name "." | xargs --verbose rm -Rf 2>> $log
+
+echo "--------" >> $log
+
+cd $temp_dist
+
+# create the configure script
+# working directory is $temp_dist
+echo "make -f Makefile.cvs in $temp_dist/:" >> $log
+echo "" >> $log
+echo -n "make -f Makefile.cvs in $temp_dist/... "
+make -f Makefile.cvs >> $log 2>> $log
+echo "rm Makefile.cvs" >> $log
+rm -f Makefile.cvs
+echo "rm autom4te.cache" >> $log
+rm -Rf autom4te.cache
+echo "--------" >> $log
+echo "done."
+
+echo "Directory will be $filename."
+
+# play around with our tar file in temp_dir
+cd $temp_dir
+
+if [ ! -z $leavedir ]; then
+ test -e $returndir/$filename && rm -Rf $returndir/$filename
+ cp -R $filename $returndir
+fi
+
+# make a tar of temp_dist
+if [ -z $nogzip ] || [ -z $nobzip2 ]; then
+ echo -n "Tarring... "
+ echo "tar cf $filename.tar $filename" >> $log
+ tar cf $filename.tar $filename >> $log
+ echo "done."
+fi
+
+if [ -z $nogzip ] && [ ! -z `which gzip 2> /dev/null` ]; then
+ cp $filename.tar $filename.tar.tmp
+ echo -n "running gzip... "
+ echo "gzip $filename.tar" >> $log
+ gzip $filename.tar
+ echo "done."
+ mv $filename.tar.tmp $filename.tar
+ mv $filename.tar.gz $returndir
+ echo "mv $filename.tar.gz $returndir" >> $log
+fi
+if [ -z $nobzip2 ] && [ ! -z `which bzip2 2> /dev/null` ]; then
+ echo -n "running bzip2... "
+ echo "bzip2 $filename.tar" >> $log
+ bzip2 $filename.tar
+ echo "done."
+ mv $filename.tar.bz2 $returndir
+ echo "mv $filename.tar.bz2 $returndir" >> $log
+fi
+
+test -e $filename.tar && rm -f $filename.tar
+
+# cleanup all tempoaries
+exit_cleanup
+
+cd $returndir
+
+test -z $leavedir && test ! -z $nobzip2 && test ! -z $nogzip && echo "Finished - no created files." && exit 1
+
+# cool, everything went ok!
+if [ -z $leavedir ]; then
+ echo "Finished. Created packages:"
+else
+ if [ -z $nogzip ] || [ -z $nobzip2 ]; then
+ echo "Finished. Created packages/directories:"
+ else
+ echo "Finished. Created directory:"
+ fi
+fi
+
+echo "--------" >> $log
+echo "Done: " >> $log
+echo "Files are in `pwd`." >> $log
+
+if [ ! -z $leavedir ] && [ -d $filename ]; then
+ ls -ld $filename
+ ls -ld $filename >> $log
+fi
+if [ -z $nogzip ] && [ -e $filename.tar.gz ]; then
+ ls -l $filename.tar.gz
+ ls -l $filename.tar.gz >> $log
+fi
+if [ -z $nobzip2 ] && [ -e $filename.tar.bz2 ]; then
+ ls -l $filename.tar.bz2
+ ls -l $filename.tar.bz2 >> $log
+fi
+if [ $log != "/dev/null" ]; then
+ echo "Created log:"
+ ls -l $origlog
+fi
diff --git a/kttsd/debian/TODO b/kttsd/debian/TODO
new file mode 100644
index 0000000..12b05e3
--- /dev/null
+++ b/kttsd/debian/TODO
@@ -0,0 +1,36 @@
+* FWIW, I have the following packages installed (among many others, of course):
+ libqt3-headers 3.3.3-4.1 Qt3 header files
+ libqt3-mt-dev 3.3.3-4.1 Qt development files (Threaded)
+ libqt3c102-mt 3.3.3-4.1 Qt GUI Library (Threaded runtime version), V
+ libqthreads-12 1.6.4-4 QuickThreads library for Guile
+ qt3-designer 3.3.3-4.1 Qt3 Designer
+ qt3-dev-tools 3.3.3-4.1 Qt3 development tools
+ qt3-doc 3.3.3-4.1 Qt3 API documentation
+ kde 3.1.2 The K Desktop Environment
+ kdelibs4 3.2.3-2 KDE core libraries
+ kdelibs4-dev 3.2.3-2 KDE core libraries (development files)
+ kdelibs4-doc 3.2.3-2 KDE core library documentation
+ kde-devel 3.1.2 The K Desktop Environment (development files
+ kde-devel-extr 3.1.2-0.2 The K Desktop Environment (extra development
+ exuberant-ctag 5.5.4-1 build tag file indexes of source code defini
+ cdbs 0.4.26-1.1 common build system for Debian packages
+
+* Here's my build procedure (note that I'm using CDBS):
+ - cd kdeaccessibility/doc/kttsd && make distclean && cd kdeaccessibility/kttsd && make distclean
+ - cvs2dist kdeaccessibility kttsd --version 0.3.0
+ - Copy resulting kttsd-0.3.0.tar.gz to a work folder and rename to kttsd_0.3.0.orig.tar.gz
+ (Note underscore)
+ - Unpack tarball
+ - cd kttsd-0.3.0
+ - rm -fR autom4te.cache
+ - cp -R kttsd/debian debian
+ - debuild -uc -us
+
+* dpkg-shlibdeps is reporting:
+ dpkg-shlibdeps: warning: could not find path for libkttsd.so.1
+ Should I have libkttsd.so in the .install file?
+
+* Should rc files be installed to etc/ tree?
+
+* For unknown reason, several of the doc translations aren't being built (da, pt for example),
+ but en and de are being built. ??
diff --git a/kttsd/debian/changelog b/kttsd/debian/changelog
new file mode 100644
index 0000000..81f503a
--- /dev/null
+++ b/kttsd/debian/changelog
@@ -0,0 +1,5 @@
+kttsd (0.3.0-1) unstable; urgency=low
+
+ * Second Release
+
+ -- Gary Cramblitt (PhantomsDad) <garycramblitt@comcast.net> Wed, 9 Feb 2005 23:05:18 -0500
diff --git a/kttsd/debian/compat b/kttsd/debian/compat
new file mode 100644
index 0000000..b8626c4
--- /dev/null
+++ b/kttsd/debian/compat
@@ -0,0 +1 @@
+4
diff --git a/kttsd/debian/control b/kttsd/debian/control
new file mode 100644
index 0000000..61c10b7
--- /dev/null
+++ b/kttsd/debian/control
@@ -0,0 +1,40 @@
+Source: kttsd
+Section: kde
+Priority: extra
+Maintainer: Gary Cramblitt (PhantomsDad) <garycramblitt@comcast.net>
+Build-Depends: debhelper (>= 4.0.0), kdelibs4-dev (>= 4:3.2), qt3-doc (>=3.3.3)
+Standards-Version: 3.6.1.1
+
+Package: kttsd
+Architecture: any
+Depends: ${shlibs:Depends}
+Suggests: festival, festival-doc, festvox-kallpc, flite, epos,
+ xsltproc, sox, kttsd-gstreamer
+Description: KDE Text-to-Speech system
+ KTTS, the KDE Text-to-Speech (TTS) system, is a plug-in based dcop service
+ that allows any KDE (or non-KDE) application to speak using the DCOP
+ interface.
+ .
+ KTTS intends to be the implementation for the KDE Text-to-Speech API.
+ .
+ Features
+ --------
+ * Priority system for warnings and messages, while still playing
+ regular text.
+ * Long text is parsed into sentences. User may backup by sentence or
+ paragraph, replay, pause, and stop playing.
+ * Speak contents of clipboard.
+ * Speak KDE notification events (KNotify).
+ .
+ You must also install a speech synthesis engine, such as festival, flite,
+ epos, freetts, or hadifix (MBROLA and txt2pho). khelpcenter help:/kttsd/
+ for links and suggestions for obtaining and installing synthesizers.
+
+Package: kttsd-gstreamer
+Architecture: any
+Depends: kttsd, libgstreamer0.8-0 (>= 0.8.7)
+Description: KTTSD GStreamer plugin
+ A plugin for the KDE Text-to-Speech system for producing
+ audio output via GStreamer. You will also need the
+ GStreamer wav file plugin and at least one GStreamer
+ output plugin (aRts, oss, or nas).
diff --git a/kttsd/debian/copyright b/kttsd/debian/copyright
new file mode 100644
index 0000000..c4848dc
--- /dev/null
+++ b/kttsd/debian/copyright
@@ -0,0 +1,33 @@
+This package was debianized by Gary Cramblitt (PhantomsDad)
+<garycramblitt@comcast.net> on
+Wed, 9 FEb 2005 17:06:00 +0500.
+
+It was downloaded from the KDE CVS repository.
+
+Upstream Authors:
+ José Pablo Ezequiel Fernández <pupeno@pupeno.com>
+ Gary Cramblitt <garycramblitt@comcast.net>
+ Gunnar Schmi Dt <gunnar@schmi-dt.de>
+ Olaf Schmidt <ojschmidt@kde.org>
+ Paul Giannaros <ceruleanblaze@gmail.com>
+
+Copyright:
+(c) 2002, José Pablo Ezequiel Fernández
+
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 dated June, 1991.
+
+ This package 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in /usr/share/common-licenses/GPL file.
diff --git a/kttsd/debian/dirs b/kttsd/debian/dirs
new file mode 100644
index 0000000..e772481
--- /dev/null
+++ b/kttsd/debian/dirs
@@ -0,0 +1 @@
+usr/bin
diff --git a/kttsd/debian/docs b/kttsd/debian/docs
new file mode 100644
index 0000000..724e084
--- /dev/null
+++ b/kttsd/debian/docs
@@ -0,0 +1,2 @@
+README
+TODO
diff --git a/kttsd/debian/kttsd-gstreamer.install b/kttsd/debian/kttsd-gstreamer.install
new file mode 100644
index 0000000..dbe0185
--- /dev/null
+++ b/kttsd/debian/kttsd-gstreamer.install
@@ -0,0 +1,3 @@
+debian/tmp/usr/lib/kde3/libkttsd_gstplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_gstplugin.la
+debian/tmp/usr/share/services/kttsd_gstplugin.desktop
diff --git a/kttsd/debian/kttsd.install b/kttsd/debian/kttsd.install
new file mode 100644
index 0000000..1ed977e
--- /dev/null
+++ b/kttsd/debian/kttsd.install
@@ -0,0 +1,107 @@
+debian/tmp/usr/bin/kttsd
+debian/tmp/usr/bin/kttsmgr
+debian/tmp/usr/lib/libkttsd.so.1.0.0
+debian/tmp/usr/lib/libkttsd.so.1
+debian/tmp/usr/lib/libkttsd.la
+debian/tmp/usr/lib/kde3/libkttsd_festivalintplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_festivalintplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_commandplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_commandplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_hadifixplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_hadifixplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_fliteplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_fliteplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_eposplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_eposplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_freettsplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_freettsplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_artsplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_artsplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_stringreplacerplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_stringreplacerplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_sbdplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_sbdplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_talkerchooserplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_talkerchooserplugin.la
+debian/tmp/usr/lib/kde3/libkttsd_xmltransformerplugin.so
+debian/tmp/usr/lib/kde3/libkttsd_xmltransformerplugin.la
+debian/tmp/usr/lib/kde3/libkttsjobmgrpart.so
+debian/tmp/usr/lib/kde3/libkttsjobmgrpart.la
+debian/tmp/usr/lib/kde3/kcm_kttsd.so
+debian/tmp/usr/lib/kde3/kcm_kttsd.la
+debian/tmp/usr/lib/kde3/ktexteditor_kttsd.la
+debian/tmp/usr/lib/kde3/ktexteditor_kttsd.so
+
+debian/tmp/usr/lib/kde3/libkhtmlkttsdplugin.la
+debian/tmp/usr/lib/kde3/libkhtmlkttsdplugin.so
+
+debian/tmp/usr/share/servicetypes/kttsd_synthplugin.desktop
+debian/tmp/usr/share/servicetypes/kttsd_audioplugin.desktop
+debian/tmp/usr/share/servicetypes/kttsd_filterplugin.desktop
+debian/tmp/usr/share/servicetypes/dcoptexttospeech.desktop
+
+debian/tmp/usr/share/apps/kttsd/xslt/SSMLtoPlainText.xsl
+debian/tmp/usr/share/apps/kttsd/festivalint/voices
+debian/tmp/usr/share/apps/kttsd/festivalint/sabletowave.scm
+debian/tmp/usr/share/apps/kttsd/festivalint/xslt/SSMLtoSable.xsl
+debian/tmp/usr/share/apps/kttsd/hadifix/xslt/SSMLtoTxt2pho.xsl
+debian/tmp/usr/share/apps/kttsd/talkerchooser/female_notifications_rc
+debian/tmp/usr/share/apps/kttsd/sbd/polish_festival_sbdrc
+debian/tmp/usr/share/apps/kttsd/sbd/standard_sbdrc
+debian/tmp/usr/share/apps/kttsd/stringreplacer/abbreviations.xml
+debian/tmp/usr/share/apps/kttsd/stringreplacer/emoticons.xml
+debian/tmp/usr/share/apps/kttsd/stringreplacer/polish_festival_fixes.xml
+debian/tmp/usr/share/apps/kttsd/stringreplacer/chat.xml
+debian/tmp/usr/share/apps/kttsd/stringreplacer/kmail.xml
+debian/tmp/usr/share/apps/kttsd/stringreplacer/polish_festival_unspeakables.xml
+debian/tmp/usr/share/apps/kttsd/xmltransformer/xhtml2ssml.xsl
+debian/tmp/usr/share/apps/ktexteditor_kttsd/ktexteditor_kttsdui.rc
+
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/common
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/general.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/index.cache.bz2
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/index.docbook
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/addtalker.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/audio.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/festivalintconf.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/general.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/interruption.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/jobs.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/talkers.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/filters.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/stringreplacer.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/xmltransformer.png
+debian/tmp/usr/share/doc/kde/HTML/*/kttsd/talkerchooser.png
+
+debian/tmp/usr/share/services/kttsd_festivalintplugin.desktop
+debian/tmp/usr/share/services/kttsd_commandplugin.desktop
+debian/tmp/usr/share/services/kttsd_hadifixplugin.desktop
+debian/tmp/usr/share/services/kttsd_fliteplugin.desktop
+debian/tmp/usr/share/services/kttsd_eposplugin.desktop
+debian/tmp/usr/share/services/kttsd_freettsplugin.desktop
+debian/tmp/usr/share/services/kttsd_stringreplacerplugin.desktop
+debian/tmp/usr/share/services/kttsd_sbdplugin.desktop
+debian/tmp/usr/share/services/kttsd_xmltransformerplugin.desktop
+debian/tmp/usr/share/services/kttsd_talkerchooserplugin.desktop
+debian/tmp/usr/share/services/kttsd.desktop
+debian/tmp/usr/share/services/kttsjobmgr.desktop
+debian/tmp/usr/share/services/kttsd_artsplugin.desktop
+debian/tmp/usr/share/services/ktexteditor_kttsd.desktop
+
+debian/tmp/usr/share/apps/khtml/kpartplugins/khtmlkttsd.desktop
+debian/tmp/usr/share/apps/khtml/kpartplugins/khtmlkttsd.rc
+
+debian/tmp/usr/share/icons/hicolor/16x16/actions/male.png
+debian/tmp/usr/share/icons/hicolor/16x16/actions/female.png
+debian/tmp/usr/share/icons/crystalsvg/16x16/apps/kttsd.png
+debian/tmp/usr/share/icons/crystalsvg/22x22/apps/kttsd.png
+debian/tmp/usr/share/icons/crystalsvg/32x32/apps/kttsd.png
+debian/tmp/usr/share/icons/crystalsvg/48x48/apps/kttsd.png
+debian/tmp/usr/share/icons/crystalsvg/64x64/apps/kttsd.png
+debian/tmp/usr/share/icons/crystalsvg/128x128/apps/kttsd.png
+debian/tmp/usr/share/icons/crystalsvg/scalable/apps/kttsd.svgz
+
+debian/tmp/usr/share/applications/kde/kcmkttsd.desktop
+debian/tmp/usr/share/applications/kde/kttsmgr.desktop
+
+debian/tmp/usr/share/locale/*/LC_MESSAGES/
diff --git a/kttsd/debian/kttsd.manpages b/kttsd/debian/kttsd.manpages
new file mode 100644
index 0000000..8051bd1
--- /dev/null
+++ b/kttsd/debian/kttsd.manpages
@@ -0,0 +1,2 @@
+debian/man/kttsmgr.1
+debian/man/kttsd.1
diff --git a/kttsd/debian/kttsmgr.menu b/kttsd/debian/kttsmgr.menu
new file mode 100644
index 0000000..f39b56b
--- /dev/null
+++ b/kttsd/debian/kttsmgr.menu
@@ -0,0 +1,6 @@
+?package(kttsd):\
+ needs="x11"\
+ section="Apps/Tools"\
+ hints="KDE"\
+ title="KTTSMgr"\
+ command="/usr/bin/kttsmgr"
diff --git a/kttsd/debian/man/kttsd.1 b/kttsd/debian/man/kttsd.1
new file mode 100644
index 0000000..379d7f0
--- /dev/null
+++ b/kttsd/debian/man/kttsd.1
@@ -0,0 +1,159 @@
+.\" This file was generated by kdemangen.pl and hand edited
+.TH KTTSD 1 "Oct 2004" "K Desktop Environment" "Text-to-speech synthesis deamon"
+.SH NAME
+kttsd
+- Text-to-speech synthesis deamon
+.SH SYNOPSIS
+kttsd [Qt-options] [KDE-options]
+.SH DESCRIPTION
+kttsd is part of the KDE Text-to-Speech system. kttsd is the
+non-GUI deamon that provides TTS services to applications
+via the DCOP interface. kttsd is configured via kttsmgr.
+.SH OPTIONS
+.SS Generic options:
+.TP
+.B --help
+Show help about options
+.TP
+.B --help-qt
+Show Qt specific options
+.TP
+.B --help-kde
+Show KDE specific options
+.TP
+.B --help-all
+Show all options
+.TP
+.B --author
+Show author information
+.TP
+.B -v, --version
+Show version information
+.TP
+.B --license
+Show license information
+.TP
+.B --
+End of options
+.SS
+.SS KDE options:
+.TP
+.B --caption <caption>
+Use 'caption' as name in the titlebar
+.TP
+.B --icon <icon>
+Use 'icon' as the application icon
+.TP
+.B --miniicon <icon>
+Use 'icon' as the icon in the titlebar
+.TP
+.B --config <filename>
+Use alternative configuration file
+.TP
+.B --dcopserver <server>
+Use the DCOP Server specified by 'server'
+.TP
+.B --nocrashhandler
+Disable crash handler, to get core dumps
+.TP
+.B --waitforwm
+Waits for a WM_NET compatible windowmanager
+.TP
+.B --style <style>
+sets the application GUI style
+.TP
+.B --geometry <geometry>
+sets the client geometry of the main widget
+.TP
+.B --nofork
+Don't run in the background.
+.SS Qt options:
+.TP
+.B --display <displayname>
+Use the X-server display 'displayname'
+.TP
+.B --session <sessionId>
+Restore the application for the given 'sessionId'
+.TP
+.B --cmap
+Causes the application to install a private color
+map on an 8-bit display
+.TP
+.B --ncols <count>
+Limits the number of colors allocated in the color
+cube on an 8-bit display, if the application is
+using the QApplication::ManyColor color
+specification
+.TP
+.B --nograb
+tells Qt to never grab the mouse or the keyboard
+.TP
+.B --dograb
+running under a debugger can cause an implicit
+-nograb, use -dograb to override
+.TP
+.B --sync
+switches to synchronous mode for debugging
+.TP
+.B --fn, --font <fontname>
+defines the application font
+.TP
+.B --bg, --background <color>
+sets the default background color and an
+application palette (light and dark shades are
+calculated)
+.TP
+.B --fg, --foreground <color>
+sets the default foreground color
+.TP
+.B --btn, --button <color>
+sets the default button color
+.TP
+.B --name <name>
+sets the application name
+.TP
+.B --title <title>
+sets the application title (caption)
+.TP
+.B --visual TrueColor
+forces the application to use a TrueColor visual on
+an 8-bit display
+.TP
+.B --inputstyle <inputstyle>
+sets XIM (X Input Method) input style. Possible
+values are onthespot, overthespot, offthespot and
+root
+.TP
+.B --im <XIM server>
+set XIM server
+.TP
+.B --noxim
+disable XIM
+.TP
+.B --reverse
+mirrors the whole layout of widgets
+.SS
+
+.SH SEE ALSO
+Full user documentation is available through the KDE Help Center. You can also enter the URL
+.BR help:/kttsd/
+directly into konqueror or you can run
+.BR "`khelpcenter help:/kttsd/'"
+from the command-line.
+.br
+
+kttsmgr(1)
+.br
+.SH AUTHORS
+.nf
+Jos Pablo Ezequiel Fernndez <pupeno@pupeno.com>
+.br
+Gary Cramblitt <garycramblitt@comcast.net>
+.br
+Gunnar Schmi Dt <gunnar@schmi-dt.de>
+.br
+Olaf Schmidt <ojschmidt@kde.org>
+.br
+Paul Giannaros <ceruleanblaze@gmail.com>
+.br
+
diff --git a/kttsd/debian/man/kttsmgr.1 b/kttsd/debian/man/kttsmgr.1
new file mode 100644
index 0000000..547ff14
--- /dev/null
+++ b/kttsd/debian/man/kttsmgr.1
@@ -0,0 +1,157 @@
+.\" This file was generated by kdemangen.pl and hand edited.
+.TH KTTSMGR 1 "Oct 2004" "K Desktop Environment" "Text-to-Speech Manager"
+.SH NAME
+kttsmgr
+- Text-to-Speech Manager
+.SH SYNOPSIS
+kttsmgr [Qt-options] [KDE-options]
+.SH DESCRIPTION
+kttsmgr is an application for starting and configuring the
+KDE Text-to-Speech system.
+.SH OPTIONS
+.SS Generic options:
+.TP
+.B --help
+Show help about options
+.TP
+.B --help-qt
+Show Qt specific options
+.TP
+.B --help-kde
+Show KDE specific options
+.TP
+.B --help-all
+Show all options
+.TP
+.B --author
+Show author information
+.TP
+.B -v, --version
+Show version information
+.TP
+.B --license
+Show license information
+.TP
+.B --
+End of options
+.SS
+.SS KDE options:
+.TP
+.B --caption <caption>
+Use 'caption' as name in the titlebar
+.TP
+.B --icon <icon>
+Use 'icon' as the application icon
+.TP
+.B --miniicon <icon>
+Use 'icon' as the icon in the titlebar
+.TP
+.B --config <filename>
+Use alternative configuration file
+.TP
+.B --dcopserver <server>
+Use the DCOP Server specified by 'server'
+.TP
+.B --nocrashhandler
+Disable crash handler, to get core dumps
+.TP
+.B --waitforwm
+Waits for a WM_NET compatible windowmanager
+.TP
+.B --style <style>
+sets the application GUI style
+.TP
+.B --geometry <geometry>
+sets the client geometry of the main widget
+.TP
+.B --nofork
+Don't run in the background.
+.SS Qt options:
+.TP
+.B --display <displayname>
+Use the X-server display 'displayname'
+.TP
+.B --session <sessionId>
+Restore the application for the given 'sessionId'
+.TP
+.B --cmap
+Causes the application to install a private color
+map on an 8-bit display
+.TP
+.B --ncols <count>
+Limits the number of colors allocated in the color
+cube on an 8-bit display, if the application is
+using the QApplication::ManyColor color
+specification
+.TP
+.B --nograb
+tells Qt to never grab the mouse or the keyboard
+.TP
+.B --dograb
+running under a debugger can cause an implicit
+-nograb, use -dograb to override
+.TP
+.B --sync
+switches to synchronous mode for debugging
+.TP
+.B --fn, --font <fontname>
+defines the application font
+.TP
+.B --bg, --background <color>
+sets the default background color and an
+application palette (light and dark shades are
+calculated)
+.TP
+.B --fg, --foreground <color>
+sets the default foreground color
+.TP
+.B --btn, --button <color>
+sets the default button color
+.TP
+.B --name <name>
+sets the application name
+.TP
+.B --title <title>
+sets the application title (caption)
+.TP
+.B --visual TrueColor
+forces the application to use a TrueColor visual on
+an 8-bit display
+.TP
+.B --inputstyle <inputstyle>
+sets XIM (X Input Method) input style. Possible
+values are onthespot, overthespot, offthespot and
+root
+.TP
+.B --im <XIM server>
+set XIM server
+.TP
+.B --noxim
+disable XIM
+.TP
+.B --reverse
+mirrors the whole layout of widgets
+.SS
+
+.SH SEE ALSO
+Full user documentation is available through the KDE Help Center. You can also enter the URL
+.BR help:/kttsd/
+directly into konqueror or you can run
+.BR "`khelpcenter help:/kttsd/'"
+from the command-line.
+.br
+
+kttsd(1)
+.SH AUTHORS
+.nf
+Jos Pablo Ezequiel Fernndez <pupeno@pupeno.com>
+.br
+Gary Cramblitt <garycramblitt@comcast.net>
+.br
+Gunnar Schmi Dt <gunnar@schmi-dt.de>
+.br
+Olaf Schmidt <ojschmidt@kde.org>
+.br
+Paul Giannaros <ceruleanblaze@gmail.com>
+.br
+
diff --git a/kttsd/debian/man/manpages.in b/kttsd/debian/man/manpages.in
new file mode 100644
index 0000000..f0a5d64
--- /dev/null
+++ b/kttsd/debian/man/manpages.in
@@ -0,0 +1,2 @@
+kttsd kttsd
+kttsd kttsmgr
diff --git a/kttsd/debian/rules b/kttsd/debian/rules
new file mode 100755
index 0000000..eaed76d
--- /dev/null
+++ b/kttsd/debian/rules
@@ -0,0 +1,5 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/kde.mk
+DEB_CONFIGURE_EXTRA_FLAGS := --enable-kttsd-gstreamer
diff --git a/kttsd/debian/shlibs.kttsd b/kttsd/debian/shlibs.kttsd
new file mode 100644
index 0000000..6746322
--- /dev/null
+++ b/kttsd/debian/shlibs.kttsd
@@ -0,0 +1,2 @@
+libkttsd 1 (>= 1:1.0.0)
+
diff --git a/kttsd/filters/Makefile.am b/kttsd/filters/Makefile.am
new file mode 100644
index 0000000..8c068f0
--- /dev/null
+++ b/kttsd/filters/Makefile.am
@@ -0,0 +1,26 @@
+# Include paths. INCLUDES is maintained by KDevelop, AM_CPPFLAGS is the preferred variable,
+# so keep them synchronized.
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd \
+ -I$(kde_includes)/arts \
+ $(CFLAGS_GST) \
+ $(all_includes)
+
+SUBDIRS = stringreplacer xmltransformer sbd talkerchooser
+
+#########################################################################
+# APPLICATION SECTION
+#########################################################################
+# This is the program that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+check_PROGRAMS = testfilter
+
+testfilter_SOURCES = main.cpp
+
+testfilter_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+testfilter_LDADD = \
+ $(top_builddir)/kttsd/libkttsd/libkttsd.la \
+ $(LIB_KDECORE)
+
+kde_servicetypes_DATA = kttsd_filterplugin.desktop
+
diff --git a/kttsd/filters/kttsd_filterplugin.desktop b/kttsd/filters/kttsd_filterplugin.desktop
new file mode 100644
index 0000000..afede99
--- /dev/null
+++ b/kttsd/filters/kttsd_filterplugin.desktop
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KTTSD/FilterPlugin
+
+[PropertyDef::X-KDE-Languages]
+Type=QStringList
diff --git a/kttsd/filters/main.cpp b/kttsd/filters/main.cpp
new file mode 100644
index 0000000..d358da8
--- /dev/null
+++ b/kttsd/filters/main.cpp
@@ -0,0 +1,140 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KTTSD Filter Test Program
+ -------------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <qstring.h>
+#include <iostream>
+using namespace std;
+
+#include <qtextstream.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kconfig.h>
+#include <ktrader.h>
+#include <kparts/componentfactory.h>
+
+#include "filterproc.h"
+#include "talkercode.h"
+
+static const KCmdLineOptions options[] =
+{
+ { "+pluginName", I18N_NOOP("Name of a KTTSD filter plugin (required)"), 0 },
+ { "t", 0, 0 },
+ { "talker <talker>", I18N_NOOP("Talker code passed to filter"), "en" },
+ { "a", 0, 0 },
+ { "appid <appID>", I18N_NOOP("DCOP application ID passed to filter"), "testfilter" },
+ { "g", 0, 0 },
+ { "group <filterID>",
+ I18N_NOOP2("A string that appears in a single config file, not a group of config files",
+ "Config file group name passed to filter"), "testfilter" },
+ { "list", I18N_NOOP("Display list of available Filter PlugIns and exit"), 0 },
+ { "b", 0, 0 },
+ { "break", I18N_NOOP("Display tabs as \\t, otherwise they are removed"), 0 },
+ { "list", I18N_NOOP("Display list of available filter plugins and exit"), 0 },
+ KCmdLineLastOption
+};
+
+int main(int argc, char *argv[])
+{
+ KAboutData aboutdata(
+ "testfilter", I18N_NOOP("testfilter"),
+ "0.1.0", I18N_NOOP("A utility for testing KTTSD filter plugins."),
+ KAboutData::License_GPL, "(C) 2005, Gary Cramblitt <garycramblitt@comcast.net>");
+ aboutdata.addAuthor("Gary Cramblitt", I18N_NOOP("Maintainer"),"garycramblitt@comcast.net");
+
+ KCmdLineArgs::init( argc, argv, &aboutdata );
+ // Tell which options are supported
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app( false, false );
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin");
+
+ if (args->isSet("list"))
+ {
+ // Iterate thru the offers to list the plugins.
+ const int offersCount = offers.count();
+ for(int ndx=0; ndx < offersCount ; ++ndx)
+ {
+ QString name = offers[ndx]->name();
+ cout << name.latin1() << endl;
+ }
+ return 0;
+ }
+
+ QString filterName;
+ if (args->count() > 0) filterName = args->arg(0);
+ QString talker = args->getOption("talker");
+ QCString appId = args->getOption("appid");
+ QString groupName = args->getOption("group");
+
+ if (filterName.isEmpty()) kdError(1) << "No filter name given." << endl;
+
+ const int offersCount = offers.count();
+ for(int ndx=0; ndx < offersCount ; ++ndx)
+ {
+ if(offers[ndx]->name() == filterName)
+ {
+ // When the entry is found, load the plug in
+ // First create a factory for the library
+ KLibFactory *factory = KLibLoader::self()->factory(offers[ndx]->library().latin1());
+ if(factory)
+ {
+ // If the factory is created successfully, instantiate the KttsFilterConf class for the
+ // specific plug in to get the plug in configuration object.
+ int errorNo;
+ KttsFilterProc *plugIn =
+ KParts::ComponentFactory::createInstanceFromLibrary<KttsFilterProc>(
+ offers[ndx]->library().latin1(), NULL, offers[ndx]->library().latin1(),
+ QStringList(), &errorNo);
+ if(plugIn)
+ {
+ KConfig* config = new KConfig("kttsdrc");
+ config->setGroup( "General" );
+ plugIn->init( config, groupName );
+ QTextStream inp ( stdin, IO_ReadOnly );
+ QString text;
+ text = inp.read();
+ TalkerCode* talkerCode = new TalkerCode( talker );
+ text = plugIn->convert( text, talkerCode, appId );
+ if ( args->isSet("break") )
+ text.replace( "\t", "\\t" );
+ else
+ text.replace( "\t", "" );
+ cout << text.latin1() << endl;
+ delete config;
+ delete plugIn;
+ return 0;
+ } else
+ kdError(2) << "Unable to create instance from library." << endl;
+ } else
+ kdError(3) << "Unable to create factory." << endl;
+ }
+ }
+ kdError(4) << "Unable to find a plugin named " << filterName << endl;
+}
diff --git a/kttsd/filters/sbd/Makefile.am b/kttsd/filters/sbd/Makefile.am
new file mode 100644
index 0000000..4faa8a9
--- /dev/null
+++ b/kttsd/filters/sbd/Makefile.am
@@ -0,0 +1,27 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_sbdplugin.la
+
+libkttsd_sbdplugin_la_SOURCES = \
+ sbdproc.cpp \
+ sbdconf.cpp \
+ sbdconfwidget.ui \
+ sbdplugin.cpp
+
+libkttsd_sbdplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_sbdplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_sbdplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+# Install data files.
+sbddatadir = $(kde_datadir)/kttsd/sbd/
+sbddata_DATA = \
+ standard_sbdrc \
+ polish_festival_sbdrc
+
+noinst_HEADERS = sbdproc.h
diff --git a/kttsd/filters/sbd/kttsd_sbdplugin.desktop b/kttsd/filters/sbd/kttsd_sbdplugin.desktop
new file mode 100644
index 0000000..0e8a483
--- /dev/null
+++ b/kttsd/filters/sbd/kttsd_sbdplugin.desktop
@@ -0,0 +1,91 @@
+[Desktop Entry]
+Name=Sentence Boundary Detector
+Name[bg]=Детектор на изречения
+Name[ca]=Detector de límit de frase
+Name[cs]=Zjištění vět
+Name[da]=Grænsedetektor for sætninger
+Name[de]=Satzgrenzenerkennung
+Name[el]=Ανιχνευτής ορίων πρότασης
+Name[es]=Detector de final de frase
+Name[et]=Lausepiiri tuvastaja
+Name[eu]=Esaldien mugen detektorea
+Name[fa]=آشکارساز کرانۀ جمله
+Name[fi]=Lauserajojen tunnistin
+Name[fr]=Détecteur de fins de phrases
+Name[ga]=Brathadóir Teorainneacha Abairtí
+Name[gl]=Detector de Límite de Frases
+Name[hu]=Mondathatár-detektáló
+Name[is]=Setningamarka greinir
+Name[it]=Rilevatore del limite delle frasi
+Name[ja]=センテンスの境界検出
+Name[ka]=წინადადების საზღვრის დამდგენი
+Name[km]= ឧបករណ៍​ចាប់​ព្រំដែន​ប្រយោគ
+Name[lt]=Sakinio ribų aptikiklis
+Name[mk]=Детектор на граница на реченица
+Name[ms]=Pengesan Sempadan Ayat
+Name[nb]=Finner setningsgrenser
+Name[nds]=Satzgrenz-Faststellen
+Name[ne]=वाक्य सीमा संसूचक
+Name[nl]=Zingrensdetectie
+Name[pl]=Wykrywanie granicy zdania
+Name[pt]=Detector de Limite de Frase
+Name[pt_BR]=Detector de Fim de Sentenças
+Name[ru]=Определитель границ предложения
+Name[sk]=Detekcia okraja vety
+Name[sl]=Detektor meje stavkov
+Name[sr]=Детектор граница реченице
+Name[sr@Latn]=Detektor granica rečenice
+Name[sv]=Meningsgränsdetektering
+Name[ta]=வாக்கிய பவுண்டரி கண்டுபிடிப்பான்
+Name[tg]=Муайянсозии ҳудуди ҷумлаҳо
+Name[tr]=Cümle Sınırlama Algılayıcı
+Name[uk]=Виявлення меж речень
+Name[vi]=Trình nhận dạng Ranh giới Câu văn
+Name[zh_CN]=语句分界检测器
+Name[zh_TW]=句子界限偵測器
+Comment=Sentence Boundary Detection Filter Plugin for KTTS
+Comment[bg]=Приставка филтър за определяне границите на изречението
+Comment[ca]=Connector del filtre detector de límit de frase pel KTTS
+Comment[cs]=Modul filtru zjišťování vět KTTS
+Comment[da]=Grænsedetektor for sætninger, filter-plugin for KTTS
+Comment[de]=Generisches KTTS-Modul zur Erkennung von Satzgrenzen
+Comment[el]=Φίλτρο πρόσθετο ανίχνευσης ορίων πρότασης για το KTTS
+Comment[es]=Complemento de filtrado que detecta el final de las frases para KTTS
+Comment[et]=KTTS-i lausepiiri tuvastamise filtri plugin
+Comment[eu]=KTTS-ren esaldien mugen detektorearen iragazkien plugina
+Comment[fa]=وصلۀ پالایۀ آشکارسازی کرانۀ جمله برای KTTS
+Comment[fi]=Lauserajojen tunnistussuodatin liitännäinen KTTS-ohjelmalle
+Comment[fr]=Module de filtrage de fins de phrases pour KTTS
+Comment[gl]=Plugin de Filtro Detector de Límite de Frases para KTTS
+Comment[hu]=Mondatvég-detektáló szűrőmodul a KTTS-hez
+Comment[is]=Setningamarka greinasía fyrir KTTS
+Comment[it]=Plugin per il filtro di rilevazione del limite delle frasi per KTTS
+Comment[ja]=KTTS 用センテンスの境界検出フィルタプラグイン
+Comment[ka]=წინადადების საზღვრის დამდგენის ფილტრის მოდული KTTS-სთვის
+Comment[km]=កម្មវិធី​ជំនួយ​តម្រង​ឧបករណ៍​ចាប់​ព្រំដែន​ប្រយោគ​សម្រាប់ KTTS
+Comment[lt]=Sakinio ribų aptikiklio filtro priedas, skirtas KTTS
+Comment[mk]=Филтер за KTTS за детекција на границата на реченица
+Comment[ms]=Plugin Penapis Pengesan Sempadan Ayat bagi KTTS
+Comment[nb]=Programtillegg for KTTS som finner setningsgrenser
+Comment[nds]=KTTS-Filtermoduul för dat Faststellen vun Satzgrenzen
+Comment[ne]=KTTS का लागि वाक्य सीमा पत्ता लगाउने फिल्टर
+Comment[nl]=Zingrensdetectieplugin voor KTTS
+Comment[pl]=Wtyczka filtra wykrywania granicy zdania dla KTTS
+Comment[pt]='Plugin' de Filtro de Detecção de Limite de Frase para o KTTS
+Comment[pt_BR]=Plug-in de Detector de Fim de Sentenças para o KTTSD
+Comment[ru]=Фильтр границ предложения для KTTS
+Comment[sk]=Modul filtra na detekciu okraja vety v KTTS
+Comment[sl]=Filtrni vstavek KTTS za zanavanje mej stavka
+Comment[sr]=Филтерски прикључак KTTS-а за откривање граница реченице
+Comment[sr@Latn]=Filterski priključak KTTS-a za otkrivanje granica rečenice
+Comment[sv]=Insticksprogram för KTTS med filter för meningsgränsdetektering
+Comment[ta]=KTTSக்கான வாக்கிய கண்டறி அலங்கார சொருகுப்பொருள்
+Comment[tg]=Филтри ҳудуди ҷумлаҳо барои KTTS
+Comment[tr]=KTTS için Cümle Sınırlama Algılayıcı Süzgeci Eklentisi
+Comment[uk]=Втулок фільтра виявлення меж для KTTS
+Comment[vi]=Trình bổ sung Lọc Nhận dạng Ranh giới Câu văn cho KTTS
+Comment[zh_TW]=KTTS 使用的偵測句子是否已結束的外掛程式
+Type=Service
+ServiceTypes=KTTSD/FilterPlugin
+X-KDE-Library=libkttsd_sbdplugin
+X-KDE-Languages=en,en_US,en_GB,en_CA,es,es_mx,cy,de,fi,cs,pl
diff --git a/kttsd/filters/sbd/polish_festival_sbdrc b/kttsd/filters/sbd/polish_festival_sbdrc
new file mode 100644
index 0000000..ad64153
--- /dev/null
+++ b/kttsd/filters/sbd/polish_festival_sbdrc
@@ -0,0 +1,6 @@
+[Filter]
+AppID=
+LanguageCodes=pl
+SentenceBoundary=\\t
+SentenceDelimiterRegExp=([\\.\\?\\!\\:\\;])(\\s|$|(\\n *\\n))
+UserFilterName=Polish Sentence Boundary Detector
diff --git a/kttsd/filters/sbd/sbdconf.cpp b/kttsd/filters/sbd/sbdconf.cpp
new file mode 100644
index 0000000..2d4cf5d
--- /dev/null
+++ b/kttsd/filters/sbd/sbdconf.cpp
@@ -0,0 +1,341 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Sentence Boundary Detection Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qstring.h>
+#include <qhbox.h>
+#include <qlayout.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qradiobutton.h>
+
+// KDE includes.
+#include <kglobal.h>
+#include <klocale.h>
+#include <klistview.h>
+#include <klineedit.h>
+#include <kdialog.h>
+#include <kdialogbase.h>
+#include <kpushbutton.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kregexpeditorinterface.h>
+#include <ktrader.h>
+#include <kparts/componentfactory.h>
+#include <kfiledialog.h>
+
+// KTTS includes.
+#include "filterconf.h"
+
+// SBD includes.
+#include "sbdconf.h"
+#include "sbdconf.moc"
+
+/**
+* Constructor
+*/
+SbdConf::SbdConf( QWidget *parent, const char *name, const QStringList& /*args*/) :
+ KttsFilterConf(parent, name)
+{
+ // kdDebug() << "SbdConf::SbdConf: Running" << endl;
+
+ // Create configuration widget.
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "SbdConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new SbdConfWidget(this, "SbdConfigWidget");
+ layout->addWidget(m_widget);
+
+ // Determine if kdeutils Regular Expression Editor is installed.
+ m_reEditorInstalled = !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty();
+
+ m_widget->reButton->setEnabled( m_reEditorInstalled );
+ if ( m_reEditorInstalled )
+ connect( m_widget->reButton, SIGNAL(clicked()), this, SLOT(slotReButton_clicked()) );
+
+ connect( m_widget->reLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+ connect( m_widget->sbLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+ connect( m_widget->nameLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+ connect( m_widget->appIdLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+ connect(m_widget->languageBrowseButton, SIGNAL(clicked()),
+ this, SLOT(slotLanguageBrowseButton_clicked()));
+ connect(m_widget->loadButton, SIGNAL(clicked()),
+ this, SLOT(slotLoadButton_clicked()));
+ connect(m_widget->saveButton, SIGNAL(clicked()),
+ this, SLOT(slotSaveButton_clicked()));
+ connect(m_widget->clearButton, SIGNAL(clicked()),
+ this, SLOT(slotClearButton_clicked()));
+
+ // Set up defaults.
+ defaults();
+}
+
+/**
+* Destructor.
+*/
+SbdConf::~SbdConf(){
+ // kdDebug() << "SbdConf::~SbdConf: Running" << endl;
+}
+
+/**
+* This method is invoked whenever the module should read its
+* configuration (most of the times from a config file) and update the
+* user interface. This happens when the user clicks the "Reset" button in
+* the control center, to undo all of his changes and restore the currently
+* valid settings. Note that kttsmgr calls this when the plugin is
+* loaded, so it not necessary to call it in your constructor.
+* The plugin should read its configuration from the specified group
+* in the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* loading your configuration.
+*/
+void SbdConf::load(KConfig* config, const QString& configGroup){
+ // kdDebug() << "SbdConf::load: Running" << endl;
+ config->setGroup( configGroup );
+ m_widget->nameLineEdit->setText(
+ config->readEntry("UserFilterName", m_widget->nameLineEdit->text()) );
+ m_widget->reLineEdit->setText(
+ config->readEntry("SentenceDelimiterRegExp", m_widget->reLineEdit->text()) );
+ m_widget->sbLineEdit->setText(
+ config->readEntry("SentenceBoundary", m_widget->sbLineEdit->text()) );
+ QStringList langCodeList = config->readListEntry("LanguageCodes");
+ if (!langCodeList.isEmpty())
+ m_languageCodeList = langCodeList;
+ QString language = "";
+ for ( uint ndx=0; ndx < m_languageCodeList.count(); ++ndx)
+ {
+ if (!language.isEmpty()) language += ",";
+ language += KGlobal::locale()->twoAlphaToLanguageName(m_languageCodeList[ndx]);
+ }
+ m_widget->languageLineEdit->setText(language);
+ m_widget->appIdLineEdit->setText(
+ config->readEntry("AppID", m_widget->appIdLineEdit->text()) );
+}
+
+/**
+* This function gets called when the user wants to save the settings in
+* the user interface, updating the config files or wherever the
+* configuration is stored. The method is called when the user clicks "Apply"
+* or "Ok". The plugin should save its configuration in the specified
+* group of the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* saving your configuration.
+*/
+void SbdConf::save(KConfig* config, const QString& configGroup){
+ // kdDebug() << "SbdConf::save: Running" << endl;
+ config->setGroup( configGroup );
+ config->writeEntry("UserFilterName", m_widget->nameLineEdit->text() );
+ config->writeEntry("SentenceDelimiterRegExp", m_widget->reLineEdit->text() );
+ config->writeEntry("SentenceBoundary", m_widget->sbLineEdit->text() );
+ config->writeEntry("LanguageCodes", m_languageCodeList );
+ config->writeEntry("AppID", m_widget->appIdLineEdit->text().replace(" ", "") );
+}
+
+/**
+* This function is called to set the settings in the module to sensible
+* default values. It gets called when hitting the "Default" button. The
+* default values should probably be the same as the ones the application
+* uses when started without a config file. Note that defaults should
+* be applied to the on-screen widgets; not to the config file.
+*/
+void SbdConf::defaults(){
+ // kdDebug() << "SbdConf::defaults: Running" << endl;
+ m_widget->nameLineEdit->setText( i18n("Standard Sentence Boundary Detector") );
+ m_widget->reLineEdit->setText( "([\\.\\?\\!\\:\\;])(\\s|$|(\\n *\\n))" );
+ m_widget->sbLineEdit->setText( "\\1\\t" );
+ m_languageCodeList.clear();
+ m_widget->languageLineEdit->setText( "" );
+ m_widget->appIdLineEdit->setText( "" );
+ // kdDebug() << "SbdConf::defaults: Exiting" << endl;
+}
+
+/**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+bool SbdConf::supportsMultiInstance() { return true; }
+
+/**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+QString SbdConf::userPlugInName()
+{
+ if ( m_widget->reLineEdit->text().isEmpty() )
+ return QString::null;
+ else
+ return m_widget->nameLineEdit->text();
+}
+
+/**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * @return True if this filter is a SBD.
+ */
+bool SbdConf::isSBD() { return true; }
+
+void SbdConf::slotReButton_clicked()
+{
+ // Show Regular Expression Editor dialog if it is installed.
+ if ( !m_reEditorInstalled ) return;
+ QDialog *editorDialog =
+ KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor" );
+ if ( editorDialog )
+ {
+ // kdeutils was installed, so the dialog was found. Fetch the editor interface.
+ KRegExpEditorInterface *reEditor =
+ static_cast<KRegExpEditorInterface *>(editorDialog->qt_cast( "KRegExpEditorInterface" ) );
+ Q_ASSERT( reEditor ); // This should not fail!// now use the editor.
+ reEditor->setRegExp( m_widget->reLineEdit->text() );
+ int dlgResult = editorDialog->exec();
+ if ( dlgResult == QDialog::Accepted )
+ {
+ QString re = reEditor->regExp();
+ m_widget->reLineEdit->setText( re );
+ configChanged();
+ }
+ delete editorDialog;
+ } else return;
+}
+
+void SbdConf::slotLanguageBrowseButton_clicked()
+{
+ // Create a QHBox to host KListView.
+ QHBox* hBox = new QHBox(m_widget, "SelectLanguage_hbox");
+ // Create a KListView and fill with all known languages.
+ KListView* langLView = new KListView(hBox, "SelectLanguage_lview");
+ langLView->addColumn(i18n("Language"));
+ langLView->addColumn(i18n("Code"));
+ langLView->setSelectionMode(QListView::Extended);
+ QStringList allLocales = KGlobal::locale()->allLanguagesTwoAlpha();
+ QString locale;
+ QString languageCode;
+ QString countryCode;
+ QString charSet;
+ QString language;
+ // Blank line so user can select no language.
+ QListViewItem* item = new KListViewItem(langLView, "", "");
+ if (m_languageCodeList.isEmpty()) item->setSelected(true);
+ const int allLocalesCount = allLocales.count();
+ for (int ndx=0; ndx < allLocalesCount; ++ndx)
+ {
+ locale = allLocales[ndx];
+ KGlobal::locale()->splitLocale(locale, languageCode, countryCode, charSet);
+ language = KGlobal::locale()->twoAlphaToLanguageName(languageCode);
+ if (!countryCode.isEmpty()) language +=
+ " (" + KGlobal::locale()->twoAlphaToCountryName(countryCode)+")";
+ QListViewItem* item = new KListViewItem(langLView, language, locale);
+ if (m_languageCodeList.contains(locale)) item->setSelected(true);
+ }
+ // Sort by language.
+ langLView->setSorting(0);
+ langLView->sort();
+ // Display the box in a dialog.
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Select Languages"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_widget,
+ "SelectLanguage_dlg",
+ true,
+ true);
+ dlg->setMainWidget(hBox);
+ dlg->setHelp("", "kttsd");
+ dlg->setInitialSize(QSize(300, 500), false);
+ int dlgResult = dlg->exec();
+ languageCode = QString::null;
+ if (dlgResult == QDialog::Accepted)
+ {
+ m_languageCodeList.clear();
+ QListViewItem* item = langLView->firstChild();
+ while (item)
+ {
+ if (item->isSelected()) m_languageCodeList += item->text(1);
+ item = item->nextSibling();
+ }
+ }
+ delete dlg;
+ // TODO: Also delete KListView and QHBox?
+ if (dlgResult != QDialog::Accepted) return;
+ language = "";
+ for ( uint ndx=0; ndx < m_languageCodeList.count(); ++ndx)
+ {
+ if (!language.isEmpty()) language += ",";
+ language += KGlobal::locale()->twoAlphaToLanguageName(m_languageCodeList[ndx]);
+ }
+ m_widget->languageLineEdit->setText(language);
+ configChanged();
+}
+
+void SbdConf::slotLoadButton_clicked()
+{
+ // QString dataDir = KGlobal::dirs()->resourceDirs("data").last() + "/kttsd/stringreplacer/";
+ QString dataDir = KGlobal::dirs()->findAllResources("data", "kttsd/sbd/").last();
+ QString filename = KFileDialog::getOpenFileName(
+ dataDir,
+ "*rc|SBD Config (*rc)",
+ m_widget,
+ "sbd_loadfile");
+ if ( filename.isEmpty() ) return;
+ KConfig* cfg = new KConfig( filename, true, false, 0 );
+ load( cfg, "Filter" );
+ delete cfg;
+ configChanged();
+}
+
+void SbdConf::slotSaveButton_clicked()
+{
+ QString filename = KFileDialog::getSaveFileName(
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/sbd/", false ),
+ "*rc|SBD Config (*rc)",
+ m_widget,
+ "sbd_savefile");
+ if ( filename.isEmpty() ) return;
+ KConfig* cfg = new KConfig( filename, false, false, 0 );
+ save( cfg, "Filter" );
+ delete cfg;
+}
+
+void SbdConf::slotClearButton_clicked()
+{
+ m_widget->nameLineEdit->setText( QString::null );
+ m_widget->reLineEdit->setText( QString::null );
+ m_widget->sbLineEdit->setText( QString::null );
+ m_languageCodeList.clear();
+ m_widget->languageLineEdit->setText( QString::null );
+ m_widget->appIdLineEdit->setText( QString::null );
+ configChanged();
+}
diff --git a/kttsd/filters/sbd/sbdconf.h b/kttsd/filters/sbd/sbdconf.h
new file mode 100644
index 0000000..131a759
--- /dev/null
+++ b/kttsd/filters/sbd/sbdconf.h
@@ -0,0 +1,139 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Standard Sentence Boundary Detection Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _SBDCONF_H_
+#define _SBDCONF_H_
+
+// Qt includes.
+#include <qwidget.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "filterconf.h"
+
+// SBD includes.
+#include "sbdconfwidget.h"
+
+class KDialogBase;
+class EditReplacementWidget;
+
+class SbdConf : public KttsFilterConf
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ SbdConf( QWidget *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor
+ */
+ virtual ~SbdConf();
+
+ /**
+ * This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. Note that KTTSMGR calls this when the plugin is
+ * loaded, so it not necessary to call it in your constructor.
+ * The plugin should read its configuration from the specified group
+ * in the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * loading your configuration.
+ *
+ * When a plugin is first added to KTTSMGR, @e load will be called with
+ * a Null @e configGroup. In this case, the plugin will not have
+ * any instance-specific parameters to load, but it may still wish
+ * to load parameters that apply to all instances of the plugin.
+ */
+ virtual void load(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok". The plugin should save its configuration in the specified
+ * group of the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * saving your configuration.
+ */
+ virtual void save(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file. Note that defaults should
+ * be applied to the on-screen widgets; not to the config file.
+ */
+ virtual void defaults();
+
+ /**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+ virtual bool supportsMultiInstance();
+
+ /**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+ virtual QString userPlugInName();
+
+ /**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * @return True if this filter is a SBD.
+ */
+ virtual bool isSBD();
+
+ private slots:
+ void slotReButton_clicked();
+ void slotLanguageBrowseButton_clicked();
+ void slotLoadButton_clicked();
+ void slotSaveButton_clicked();
+ void slotClearButton_clicked();
+
+ private:
+
+ // Configuration Widget.
+ SbdConfWidget* m_widget;
+ // True if kdeutils Regular Expression Editor is installed.
+ bool m_reEditorInstalled;
+ // Language Code.
+ QStringList m_languageCodeList;
+};
+
+#endif //_SBDCONF_H_
diff --git a/kttsd/filters/sbd/sbdconfwidget.ui b/kttsd/filters/sbd/sbdconfwidget.ui
new file mode 100644
index 0000000..17cd525
--- /dev/null
+++ b/kttsd/filters/sbd/sbdconfwidget.ui
@@ -0,0 +1,363 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>SbdConfWidget</class>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SbdConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>544</width>
+ <height>315</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;WARNING: This filter is a key component of the KTTS system. Please read the KTTS Handbook before modifying these settings.&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>nameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Name:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The name of this filter. Enter any descriptive name you like.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="text">
+ <string>Standard Sentence Boundary Detector</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The name of this filter. Enter any descriptive name you like.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout17</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>reLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Sentence boundary regular expression:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The regular expression that detects boundaries between sentences in text jobs.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>reLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The regular expression that detects boundaries between sentences in text jobs.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>reButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0">
+ <property name="name">
+ <cstring>layout17_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>sbLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Replacement sentence boundary:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This string replaces the matched regular expression. &lt;b&gt;Important&lt;/b&gt;: must end with tab (\t).</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>sbLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This string replaces the matched regular expression. &lt;b&gt;Important&lt;/b&gt;: must end with tab (\t).</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox" row="4" column="0">
+ <property name="name">
+ <cstring>applyGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Apply This &amp;Filter When</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>These settings determines when the filter is applied to text.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Language is:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>languageLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank the filter applies to all text jobs of any language.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>appIdLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Application &amp;ID contains:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter a DCOP Application ID. This filter will only apply to text jobs queued by that application. You may enter more than one ID separated by commas. If blank, this filter applies to text jobs queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>languageLineEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank the filter applies to all text jobs of any language.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>languageBrowseButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to select one or more languages. This filter will be applied to text jobs of those languages.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter a DCOP Application ID. This filter will only apply to text jobs queued by that application. You may enter more than one ID separated by commas. Use &lt;b&gt;knotify&lt;/b&gt; to match all messages sent as KDE notifications. If blank, this filter applies to text jobs queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="5" column="0">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>loadButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Load...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to load a Sentence Boundary Detection configuration from a file.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>saveButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Sa&amp;ve...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to save this Sentence Boundary Detection configuration to a file.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>clearButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Clea&amp;r</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to clear everything.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>nameLineEdit</tabstop>
+ <tabstop>reLineEdit</tabstop>
+ <tabstop>reButton</tabstop>
+ <tabstop>sbLineEdit</tabstop>
+ <tabstop>languageLineEdit</tabstop>
+ <tabstop>languageBrowseButton</tabstop>
+ <tabstop>appIdLineEdit</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/filters/sbd/sbdplugin.cpp b/kttsd/filters/sbd/sbdplugin.cpp
new file mode 100644
index 0000000..ab14080
--- /dev/null
+++ b/kttsd/filters/sbd/sbdplugin.cpp
@@ -0,0 +1,33 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so Sentence Boundary Detection Filter can be used
+ as plug in.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "sbdconf.h"
+#include "sbdproc.h"
+
+typedef K_TYPELIST_2( SbdProc, SbdConf ) SbdPlugin;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_sbdplugin,
+ KGenericFactory<SbdPlugin>("kttsd_sbd") )
+
diff --git a/kttsd/filters/sbd/sbdproc.cpp b/kttsd/filters/sbd/sbdproc.cpp
new file mode 100644
index 0000000..cdc80d9
--- /dev/null
+++ b/kttsd/filters/sbd/sbdproc.cpp
@@ -0,0 +1,784 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Sentence Boundary Detection Filter class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qregexp.h>
+#include <qdom.h>
+#include <qapplication.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <klocale.h>
+#include <kconfig.h>
+
+// KTTS includes.
+#include "utils.h"
+#include "talkercode.h"
+
+// SdbProc includes.
+#include "sbdproc.h"
+
+/**
+ * Constructor.
+ */
+SbdThread::SbdThread( QObject *parent, const char *name ) :
+ QObject( parent, name ),
+ QThread()
+{
+}
+
+/**
+ * Destructor.
+ */
+/*virtual*/ SbdThread::~SbdThread()
+{
+}
+
+/**
+ * Get/Set text being processed.
+ */
+void SbdThread::setText( const QString& text ) { m_text = text; }
+QString SbdThread::text() { return m_text; }
+
+/**
+ * Set/Get TalkerCode.
+ */
+void SbdThread::setTalkerCode( TalkerCode* talkerCode ) { m_talkerCode = talkerCode; }
+TalkerCode* SbdThread::talkerCode() { return m_talkerCode; }
+
+/**
+ * Set Sentence Boundary Regular Expression.
+ * This method will only be called if the application overrode the default.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+void SbdThread::setSbRegExp( const QString& re ) { m_re = re; }
+
+/**
+ * The configured Sentence Boundary Regular Expression.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+void SbdThread::setConfiguredSbRegExp( const QString& re ) { m_configuredRe = re; }
+
+/**
+ * The configured Sentence Boundary that replaces SB regular expression.
+ *
+ * @param sb The sentence boundary replacement.
+ *
+ */
+void SbdThread::setConfiguredSentenceBoundary( const QString& sb ) { m_configuredSentenceBoundary = sb; }
+
+/**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+void SbdThread::setWasModified(bool wasModified) { m_wasModified = wasModified; }
+bool SbdThread::wasModified() { return m_wasModified; }
+
+// Given a tag name, returns SsmlElemType.
+SbdThread::SsmlElemType SbdThread::tagToSsmlElemType( const QString tagName )
+{
+ if ( tagName == "speak" ) return etSpeak;
+ if ( tagName == "voice" ) return etVoice;
+ if ( tagName == "prosody" ) return etProsody;
+ if ( tagName == "emphasis" ) return etEmphasis;
+ if ( tagName == "break" ) return etBreak;
+ if ( tagName == "s" ) return etPS;
+ if ( tagName == "p" ) return etPS;
+ return etNotSsml;
+}
+
+// Parses an SSML element, pushing current settings onto the context stack.
+void SbdThread::pushSsmlElem( SsmlElemType et, const QDomElement& elem )
+{
+ // TODO: Need to convert relative values into absolute values and also convert
+ // only to values recognized by SSML2SABLE stylesheet. Either that or enhance all
+ // the synth stylesheets.
+ QDomNamedNodeMap attrList = elem.attributes();
+ int attrCount = attrList.count();
+ switch ( et )
+ {
+ case etSpeak: {
+ SpeakElem e = m_speakStack.top();
+ for ( int ndx=0; ndx < attrCount; ++ndx )
+ {
+ QDomAttr a = attrList.item( ndx ).toAttr();
+ if ( a.name() == "lang" ) e.lang = a.value();
+ }
+ m_speakStack.push( e );
+ break; }
+ case etVoice: {
+ VoiceElem e = m_voiceStack.top();
+ // TODO: Since Festival chokes on <voice> tags, don't output them at all.
+ // This means we can't support voice changes, and probably more irritatingly,
+ // gender changes either.
+ m_voiceStack.push( e );
+ break; }
+ case etProsody: {
+ ProsodyElem e = m_prosodyStack.top();
+ for ( int ndx=0; ndx < attrCount; ++ndx )
+ {
+ QDomAttr a = attrList.item( ndx ).toAttr();
+ if ( a.name() == "pitch" ) e.pitch = a.value();
+ if ( a.name() == "contour" ) e.contour = a.value();
+ if ( a.name() == "range" ) e.range = a.value();
+ if ( a.name() == "rate" ) e.rate = a.value();
+ if ( a.name() == "duration" ) e.duration = a.value();
+ if ( a.name() == "volume" ) e.volume = a.value();
+ }
+ m_prosodyStack.push( e );
+ break; }
+ case etEmphasis: {
+ EmphasisElem e = m_emphasisStack.top();
+ for ( int ndx=0; ndx < attrCount; ++ndx )
+ {
+ QDomAttr a = attrList.item( ndx ).toAttr();
+ if ( a.name() == "level" ) e.level = a.value();
+ }
+ m_emphasisStack.push( e );
+ break; }
+ case etPS: {
+ PSElem e = m_psStack.top();
+ for ( int ndx=0; ndx < attrCount; ++ndx )
+ {
+ QDomAttr a = attrList.item( ndx ).toAttr();
+ if ( a.name() == "lang" ) e.lang = a.value();
+ }
+ m_psStack.push( e );
+ break; }
+ default: break;
+ }
+}
+
+// Given an attribute name and value, constructs an XML representation of the attribute,
+// i.e., name="value".
+QString SbdThread::makeAttr( const QString& name, const QString& value )
+{
+ if ( value.isEmpty() ) return QString::null;
+ return " " + name + "=\"" + value + "\"";
+}
+
+// Returns an XML representation of an SSML tag from the top of the context stack.
+QString SbdThread::makeSsmlElem( SsmlElemType et )
+{
+ QString s;
+ QString a;
+ switch ( et )
+ {
+ // Must always output speak tag, otherwise kttsd won't think each sentence is SSML.
+ // For all other tags, only output the tag if it contains at least one attribute.
+ case etSpeak: {
+ SpeakElem e = m_speakStack.top();
+ s = "<speak";
+ if ( !e.lang.isEmpty() ) s += makeAttr( "lang", e.lang );
+ s += ">";
+ break; }
+ case etVoice: {
+ VoiceElem e = m_voiceStack.top();
+ a += makeAttr( "lang", e.lang );
+ a += makeAttr( "gender", e.gender );
+ a += makeAttr( "age", QString::number(e.age) );
+ a += makeAttr( "name", e.name );
+ a += makeAttr( "variant", e.variant );
+ if ( !a.isEmpty() ) s = "<voice" + a + ">";
+ break; }
+ case etProsody: {
+ ProsodyElem e = m_prosodyStack.top();
+ a += makeAttr( "pitch", e.pitch );
+ a += makeAttr( "contour", e.contour );
+ a += makeAttr( "range", e.range );
+ a += makeAttr( "rate", e.rate );
+ a += makeAttr( "duration", e.duration );
+ a += makeAttr( "volume", e.volume );
+ if ( !a.isEmpty() ) s = "<prosody" + a + ">";
+ break; }
+ case etEmphasis: {
+ EmphasisElem e = m_emphasisStack.top();
+ a += makeAttr( "level", e.level );
+ if ( !a.isEmpty() ) s = "<emphasis" + a + ">";
+ break; }
+ case etPS: {
+ break; }
+ default: break;
+ }
+ return s;
+}
+
+// Pops element from the indicated context stack.
+void SbdThread::popSsmlElem( SsmlElemType et )
+{
+ switch ( et )
+ {
+ case etSpeak: m_speakStack.pop(); break;
+ case etVoice: m_voiceStack.pop(); break;
+ case etProsody: m_prosodyStack.pop(); break;
+ case etEmphasis: m_emphasisStack.pop(); break;
+ case etPS: m_psStack.pop(); break;
+ default: break;
+ }
+}
+
+// Returns an XML representation of a break element.
+QString SbdThread::makeBreakElem( const QDomElement& e )
+{
+ QString s = "<break";
+ QDomNamedNodeMap attrList = e.attributes();
+ int attrCount = attrList.count();
+ for ( int ndx=0; ndx < attrCount; ++ndx )
+ {
+ QDomAttr a = attrList.item( ndx ).toAttr();
+ s += makeAttr( a.name(), a.value() );
+ }
+ s += ">";
+ return s;
+}
+
+// Converts a text fragment into a CDATA section.
+QString SbdThread::makeCDATA( const QString& text )
+{
+ QString s = "<![CDATA[";
+ s += text;
+ s += "]]>";
+ return s;
+}
+
+// Returns an XML representation of an utterance node consisting of voice,
+// prosody, and emphasis elements.
+QString SbdThread::makeSentence( const QString& text )
+{
+ QString s;
+ QString v = makeSsmlElem( etVoice );
+ QString p = makeSsmlElem( etProsody );
+ QString e = makeSsmlElem( etEmphasis );
+ // TODO: Lang settings from psStack.
+ if ( !v.isEmpty() ) s += v;
+ if ( !p.isEmpty() ) s += p;
+ if ( !e.isEmpty() ) s += e;
+ // Escape ampersands and less thans.
+ QString newText = text;
+ newText.replace(QRegExp("&(?!amp;)"), "&amp;");
+ newText.replace(QRegExp("<(?!lt;)"), "&lt;");
+ s += newText;
+ if ( !e.isEmpty() ) s += "</emphasis>";
+ if ( !p.isEmpty() ) s += "</prosody>";
+ if ( !v.isEmpty() ) s += "</voice>";
+ return s;
+}
+
+// Starts a sentence by returning a speak tag.
+QString SbdThread::startSentence()
+{
+ if ( m_sentenceStarted ) return QString::null;
+ QString s;
+ s += makeSsmlElem( etSpeak );
+ m_sentenceStarted = true;
+ return s;
+}
+
+// Ends a sentence and appends a Tab.
+QString SbdThread::endSentence()
+{
+ if ( !m_sentenceStarted ) return QString::null;
+ QString s = "</speak>";
+ s += "\t";
+ m_sentenceStarted = false;
+ return s;
+}
+
+// Parses a node of the SSML tree and recursively parses its children.
+// Returns the filtered text with each sentence a complete ssml tree.
+QString SbdThread::parseSsmlNode( QDomNode& n, const QString& re )
+{
+ QString result;
+ switch ( n.nodeType() )
+ {
+ case QDomNode::ElementNode: { // = 1
+ QDomElement e = n.toElement();
+ QString tagName = e.tagName();
+ SsmlElemType et = tagToSsmlElemType( tagName );
+ switch ( et )
+ {
+ case etSpeak:
+ case etVoice:
+ case etProsody:
+ case etEmphasis:
+ case etPS:
+ {
+ pushSsmlElem( et, e );
+ QDomNode t = n.firstChild();
+ while ( !t.isNull() )
+ {
+ result += parseSsmlNode( t, re );
+ t = t.nextSibling();
+ }
+ popSsmlElem( et );
+ if ( et == etPS )
+ result += endSentence();
+ break;
+ }
+ case etBreak:
+ {
+ // Break elements are empty.
+ result += makeBreakElem( e );
+ }
+ // Ignore any elements we don't recognize.
+ default: break;
+ }
+ break; }
+ case QDomNode::AttributeNode: { // = 2
+ break; }
+ case QDomNode::TextNode: { // = 3
+ QString s = parsePlainText( n.toText().data(), re );
+ // QString d = s;
+ // d.replace("\t", "\\t");
+ // kdDebug() << "SbdThread::parseSsmlNode: parsedPlainText = [" << d << "]" << endl;
+ QStringList sentenceList = QStringList::split( '\t', s, false );
+ int lastNdx = sentenceList.count() - 1;
+ for ( int ndx=0; ndx < lastNdx; ++ndx )
+ {
+ result += startSentence();
+ result += makeSentence( sentenceList[ndx] );
+ result += endSentence();
+ }
+ // Only output sentence boundary if last text fragment ended a sentence.
+ if ( lastNdx >= 0 )
+ {
+ result += startSentence();
+ result += makeSentence( sentenceList[lastNdx] );
+ if ( s.endsWith( "\t" ) ) result += endSentence();
+ }
+ break; }
+ case QDomNode::CDATASectionNode: { // = 4
+ QString s = parsePlainText( n.toCDATASection().data(), re );
+ QStringList sentenceList = QStringList::split( '\t', s, false );
+ int lastNdx = sentenceList.count() - 1;
+ for ( int ndx=0; ndx < lastNdx; ++ndx )
+ {
+ result += startSentence();
+ result += makeSentence( makeCDATA( sentenceList[ndx] ) );
+ result += endSentence();
+ }
+ // Only output sentence boundary if last text fragment ended a sentence.
+ if ( lastNdx >= 0 )
+ {
+ result += startSentence();
+ result += makeSentence( makeCDATA( sentenceList[lastNdx] ) );
+ if ( s.endsWith( "\t" ) ) result += endSentence();
+ }
+ break; }
+ case QDomNode::EntityReferenceNode: { // = 5
+ break; }
+ case QDomNode::EntityNode: { // = 6
+ break; }
+ case QDomNode::ProcessingInstructionNode: { // = 7
+ break; }
+ case QDomNode::CommentNode: { // = 8
+ break; }
+ case QDomNode::DocumentNode: { // = 9
+ break; }
+ case QDomNode::DocumentTypeNode: { // = 10
+ break; }
+ case QDomNode::DocumentFragmentNode: { // = 11
+ break; }
+ case QDomNode::NotationNode: { // = 12
+ break; }
+ case QDomNode::BaseNode: { // = 21
+ break; }
+ case QDomNode::CharacterDataNode: { // = 22
+ break; }
+ }
+ return result;
+}
+
+// Parses Ssml.
+QString SbdThread::parseSsml( const QString& inputText, const QString& re )
+{
+ QRegExp sentenceDelimiter = QRegExp( re );
+
+ // Read the text into xml dom tree.
+ QDomDocument doc( "" );
+ // If an error occurs parsing the SSML, return "invalid S S M L".
+ if ( !doc.setContent( inputText ) ) return i18n("Invalid S S M L.");
+
+ // Set up context stacks and set defaults for all element attributes.
+ m_speakStack.clear();
+ m_voiceStack.clear();
+ m_prosodyStack.clear();
+ m_emphasisStack.clear();
+ m_psStack.clear();
+ SpeakElem se = { "" };
+ m_speakStack.push ( se );
+ VoiceElem ve = {"", "neutral", 40, "", ""};
+ m_voiceStack.push( ve );
+ ProsodyElem pe = { "medium", "", "medium", "medium", "", "medium" };
+ m_prosodyStack.push( pe );
+ EmphasisElem em = { "" };
+ m_emphasisStack.push( em );
+ PSElem pse = { "" };
+ m_psStack.push ( pse );
+
+ // This flag is used to close out a previous sentence.
+ m_sentenceStarted = false;
+
+ // Get the root element (speak) and recursively process its children.
+ QDomElement docElem = doc.documentElement();
+ QDomNode n = docElem.firstChild();
+ QString ssml = parseSsmlNode( docElem, re );
+
+ // Close out last sentence.
+ if ( m_sentenceStarted ) ssml += "</speak>";
+
+ return ssml;
+}
+
+// Parses code. Each newline is converted into a tab character (\t).
+QString SbdThread::parseCode( const QString& inputText )
+{
+ QString temp = inputText;
+ // Replace newlines with tabs.
+ temp.replace("\n","\t");
+ // Remove leading spaces.
+ temp.replace(QRegExp("\\t +"), "\t");
+ // Remove trailing spaces.
+ temp.replace(QRegExp(" +\\t"), "\t");
+ // Remove blank lines.
+ temp.replace(QRegExp("\t\t+"),"\t");
+ return temp;
+}
+
+// Parses plain text.
+QString SbdThread::parsePlainText( const QString& inputText, const QString& re )
+{
+ // kdDebug() << "SbdThread::parsePlainText: parsing " << inputText << " with re " << re << endl;
+ QRegExp sentenceDelimiter = QRegExp( re );
+ QString temp = inputText;
+ // Replace sentence delimiters with tab.
+ temp.replace(sentenceDelimiter, m_configuredSentenceBoundary);
+ // Replace remaining newlines with spaces.
+ temp.replace("\n"," ");
+ temp.replace("\r"," ");
+ // Remove leading spaces.
+ temp.replace(QRegExp("\\t +"), "\t");
+ // Remove trailing spaces.
+ temp.replace(QRegExp(" +\\t"), "\t");
+ // Remove blank lines.
+ temp.replace(QRegExp("\t\t+"),"\t");
+ return temp;
+}
+
+// This is where the real work takes place.
+/*virtual*/ void SbdThread::run()
+{
+ // kdDebug() << "SbdThread::run: processing text = " << m_text << endl;
+
+ // TODO: Determine if we should do anything or not.
+ m_wasModified = true;
+
+ // Determine what kind of input text we are dealing with.
+ int textType;
+ if ( KttsUtils::hasRootElement( m_text, "speak" ) )
+ textType = ttSsml;
+ else
+ {
+ // Examine just the first 500 chars to see if it is code.
+ QString p = m_text.left( 500 );
+ if ( p.contains( QRegExp( "(/\\*)|(if\\b\\()|(^#include\\b)" ) ) )
+ textType = ttCode;
+ else
+ textType = ttPlain;
+ }
+
+ // If application specified a sentence delimiter regular expression, use that,
+ // otherwise use configured default.
+ QString re = m_re;
+ if ( re.isEmpty() ) re = m_configuredRe;
+
+ // Replace spaces, tabs, and formfeeds with a single space.
+ m_text.replace(QRegExp("[ \\t\\f]+"), " ");
+
+ // Perform the filtering based on type of text.
+ switch ( textType )
+ {
+ case ttSsml:
+ m_text = parseSsml( m_text, re );
+ break;
+
+ case ttCode:
+ m_text = parseCode( m_text );
+ break;
+
+ case ttPlain:
+ m_text = parsePlainText( m_text, re);
+ break;
+ }
+
+ // Clear app-specified sentence delimiter. App must call setSbRegExp for each conversion.
+ m_re = QString::null;
+
+ // kdDebug() << "SbdThread::run: filtered text = " << m_text << endl;
+
+ // Result is in m_text;
+
+ // Post an event. We need to emit filterFinished signal, but not from the
+ // separate thread.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 301);
+ QApplication::postEvent(this, ev);
+}
+
+bool SbdThread::event ( QEvent * e )
+{
+ if ( e->type() == (QEvent::User + 301) )
+ {
+ // kdDebug() << "SbdThread::event: emitting filteringFinished signal." << endl;
+ emit filteringFinished();
+ return true;
+ }
+ else return false;
+}
+
+// ----------------------------------------------------------------------------
+
+/**
+ * Constructor.
+ */
+SbdProc::SbdProc( QObject *parent, const char *name, const QStringList& /*args*/) :
+ KttsFilterProc(parent, name)
+{
+ // kdDebug() << "SbdProc::SbdProc: Running" << endl;
+ m_sbdThread = new SbdThread( parent, *name + "_thread" );
+ connect( m_sbdThread, SIGNAL(filteringFinished()), this, SLOT(slotSbdThreadFilteringFinished()) );
+}
+
+/**
+ * Destructor.
+ */
+SbdProc::~SbdProc()
+{
+ // kdDebug() << "SbdProc::~SbdProc: Running" << endl;
+ if ( m_sbdThread )
+ {
+ if ( m_sbdThread->running() )
+ {
+ m_sbdThread->terminate();
+ m_sbdThread->wait();
+ }
+ delete m_sbdThread;
+ }
+}
+
+/**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+bool SbdProc::init(KConfig* config, const QString& configGroup){
+ // kdDebug() << "PlugInProc::init: Running" << endl;
+ config->setGroup( configGroup );
+// m_configuredRe = config->readEntry( "SentenceDelimiterRegExp", "([\\.\\?\\!\\:\\;])\\s|(\\n *\\n)" );
+ m_configuredRe = config->readEntry( "SentenceDelimiterRegExp", "([\\.\\?\\!\\:\\;])(\\s|$|(\\n *\\n))" );
+ m_sbdThread->setConfiguredSbRegExp( m_configuredRe );
+ QString sb = config->readEntry( "SentenceBoundary", "\\1\t" );
+ sb.replace( "\\t", "\t" );
+ m_sbdThread->setConfiguredSentenceBoundary( sb );
+ m_appIdList = config->readListEntry( "AppID" );
+ m_languageCodeList = config->readListEntry( "LanguageCodes" );
+ return true;
+}
+
+/**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * If so, the filter should implement @ref setSbRegExp() .
+ * @return True if this filter is a SBD.
+ */
+/*virtual*/ bool SbdProc::isSBD() { return true; }
+
+/**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+/*virtual*/ bool SbdProc::supportsAsync() { return true; }
+
+/**
+ * Convert input, returning output. Runs synchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+/*virtual*/ QString SbdProc::convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId)
+{
+ if ( asyncConvert( inputText, talkerCode, appId) )
+ {
+ waitForFinished();
+ // kdDebug() << "SbdProc::convert: returning " << getOutput() << endl;
+ return getOutput();
+ } else return inputText;
+}
+
+/**
+ * Convert input. Runs asynchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ * @return False if the filter cannot perform the conversion.
+ *
+ * When conversion is completed, emits signal @ref filteringFinished. Calling
+ * program may then call @ref getOutput to retrieve converted text. Calling
+ * program must call @ref ackFinished to acknowledge the conversion.
+ */
+/*virtual*/ bool SbdProc::asyncConvert(const QString& inputText, TalkerCode* talkerCode,
+ const QCString& appId)
+{
+ m_sbdThread->setWasModified( false );
+ // If language doesn't match, return input unmolested.
+ if ( !m_languageCodeList.isEmpty() )
+ {
+ QString languageCode = talkerCode->languageCode();
+ // kdDebug() << "StringReplacerProc::convert: converting " << inputText <<
+ // " if language code " << languageCode << " matches " << m_languageCodeList << endl;
+ if ( !m_languageCodeList.contains( languageCode ) )
+ {
+ if ( !talkerCode->countryCode().isEmpty() )
+ {
+ languageCode += '_' + talkerCode->countryCode();
+ // kdDebug() << "StringReplacerProc::convert: converting " << inputText <<
+ // " if language code " << languageCode << " matches " << m_languageCodeList << endl;
+ if ( !m_languageCodeList.contains( languageCode ) ) return false;
+ } else return false;
+ }
+ }
+ // If appId doesn't match, return input unmolested.
+ if ( !m_appIdList.isEmpty() )
+ {
+ // kdDebug() << "SbdProc::convert: converting " << inputText << " if appId "
+ // << appId << " matches " << m_appIdList << endl;
+ bool found = false;
+ QString appIdStr = appId;
+ for ( uint ndx=0; ndx < m_appIdList.count(); ++ndx )
+ {
+ if ( appIdStr.contains(m_appIdList[ndx]) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found ) return false;
+ }
+ m_sbdThread->setText( inputText );
+ m_sbdThread->setTalkerCode( talkerCode );
+ m_state = fsFiltering;
+ m_sbdThread->start();
+ return true;
+}
+
+/**
+ * Waits for a previous call to asyncConvert to finish.
+ */
+/*virtual*/ void SbdProc::waitForFinished()
+{
+ if ( m_sbdThread->running() )
+ {
+ // kdDebug() << "SbdProc::waitForFinished: waiting" << endl;
+ m_sbdThread->wait();
+ // kdDebug() << "SbdProc::waitForFinished: finished waiting" << endl;
+ m_state = fsFinished;
+ }
+}
+
+/**
+ * Returns the state of the Filter.
+ */
+/*virtual*/ int SbdProc::getState() { return m_state; }
+
+/**
+ * Returns the filtered output.
+ */
+/*virtual*/ QString SbdProc::getOutput() { return m_sbdThread->text(); }
+
+/**
+ * Acknowledges the finished filtering.
+ */
+/*virtual*/ void SbdProc::ackFinished()
+{
+ m_state = fsIdle;
+ m_sbdThread->setText( QString::null );
+}
+
+/**
+ * Stops filtering. The filteringStopped signal will emit when filtering
+ * has in fact stopped and state returns to fsIdle;
+ */
+/*virtual*/ void SbdProc::stopFiltering()
+{
+ if ( m_sbdThread->running() )
+ {
+ m_sbdThread->terminate();
+ m_sbdThread->wait();
+ delete m_sbdThread;
+ m_sbdThread = new SbdThread();
+ m_sbdThread->setConfiguredSbRegExp( m_configuredRe );
+ connect( m_sbdThread, SIGNAL(filteringFinished()), this, SLOT(slotSbdThreadFilteringFinished()) );
+ m_state = fsIdle;
+ emit filteringStopped();
+ }
+}
+
+/**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+/*virtual*/ bool SbdProc::wasModified() { return m_sbdThread->wasModified(); }
+
+/**
+ * Set Sentence Boundary Regular Expression.
+ * This method will only be called if the application overrode the default.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+/*virtual*/ void SbdProc::setSbRegExp(const QString& re) { m_sbdThread->setSbRegExp( re ); }
+
+// Received when SBD Thread finishes.
+void SbdProc::slotSbdThreadFilteringFinished()
+{
+ m_state = fsFinished;
+ // kdDebug() << "SbdProc::slotSbdThreadFilteringFinished: emitting filterFinished signal." << endl;
+ emit filteringFinished();
+}
+
+#include "sbdproc.moc"
diff --git a/kttsd/filters/sbd/sbdproc.h b/kttsd/filters/sbd/sbdproc.h
new file mode 100644
index 0000000..6c181d5
--- /dev/null
+++ b/kttsd/filters/sbd/sbdproc.h
@@ -0,0 +1,366 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Sentence Boundary Detection (SBD) Filter class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+/******************************************************************************
+
+ This class performs three kinds of SBD:
+ 1. If the text is SSML, generates new SSML where the prosody and voice
+ tags are fully specified for each sentence. This allows user to
+ advance or rewind by sentence without losing SSML context.
+ Input is considered to be SSML if the top-level element is a
+ <speak> tag.
+ 2. If the text is code, each line is considered to be a sentence.
+ Input is considered to be code if any of the following strings are
+ detected:
+ slash asterisk
+ if left-paren
+ pound include
+ 3. If the text is plain text, performs SBD using specified Regular
+ Expression.
+
+ Text is output with tab characters (\t) separating sentences.
+
+ ******************************************************************************/
+
+#ifndef _SBDPROC_H_
+#define _SBDPROC_H_
+
+// Qt includes.
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qthread.h>
+#include <qvaluestack.h>
+#include <qevent.h>
+
+// KTTS includes.
+#include "filterproc.h"
+
+class TalkerCode;
+class KConfig;
+class QDomElement;
+class QDomNode;
+
+class SbdThread: public QObject, public QThread
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor.
+ */
+ SbdThread( QObject *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor.
+ */
+ virtual ~SbdThread();
+
+ /**
+ * Get/Set text being processed.
+ */
+ void setText( const QString& text );
+ QString text();
+
+ /**
+ * Set/Get TalkerCode.
+ */
+ void setTalkerCode( TalkerCode* talkerCode );
+ TalkerCode* talkerCode();
+
+ /**
+ * Set Sentence Boundary Regular Expression.
+ * This method will only be called if the application overrode the default.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+ void setSbRegExp( const QString& re );
+
+ /**
+ * The configured Sentence Boundary Regular Expression.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+ void setConfiguredSbRegExp( const QString& re );
+
+ /**
+ * The configured Sentence Boundary that replaces SB regular expression.
+ *
+ * @param sb The sentence boundary replacement.
+ *
+ */
+ void setConfiguredSentenceBoundary( const QString& sb );
+
+ /**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+ void setWasModified(bool wasModified);
+ bool wasModified();
+
+ signals:
+ void filteringFinished();
+
+ protected:
+ virtual void run();
+ virtual bool event ( QEvent * e );
+
+ private:
+ enum TextType {
+ ttSsml, // SSML
+ ttCode, // Code
+ ttPlain // Plain text
+ };
+
+ enum SsmlElemType {
+ etSpeak,
+ etVoice,
+ etProsody,
+ etEmphasis,
+ etPS, // Paragraph or sentence (we don't care).
+ etBreak,
+ etNotSsml
+ };
+
+ // Speak Element.
+ struct SpeakElem {
+ QString lang; // xml:lang="en".
+ };
+
+ // Voice Element.
+ struct VoiceElem {
+ QString lang; // xml:lang="en".
+ QString gender; // "male", "female", or "neutral".
+ uint age; // Age in years.
+ QString name; // Synth-specific voice name.
+ QString variant; // Ignored.
+ };
+
+ // Prosody Element.
+ struct ProsodyElem {
+ QString pitch; // "x-low", "low", "medium", "high", "x-high", "default".
+ QString contour; // Pitch contour (ignored).
+ QString range; // "x-low", "low", "medium", "high", "x-high", "default".
+ QString rate; // "x-slow", "slow", "medium", "fast", "x-fast", "default".
+ QString duration; // Ignored.
+ QString volume; // "silent", "x-soft", "soft", "medium", "load", "x-load", "default".
+ };
+
+ // Emphasis Element.
+ struct EmphasisElem {
+ QString level; // "strong", "moderate", "none" and "reduced"
+ };
+
+ // Break Element.
+ struct BreakElem {
+ QString strength; // "x-weak", "weak", "medium" (default value), "strong",
+ // or "x-strong", "none"
+ QString time; // Ignored.
+ };
+
+ // Paragraph and Sentence Elements.
+ struct PSElem {
+ QString lang; // xml:lang="en".
+ };
+
+ // Given a tag name, returns SsmlElemType.
+ SsmlElemType tagToSsmlElemType(const QString tagName);
+ // Parses an SSML element, pushing current settings onto the context stack.
+ void pushSsmlElem( SsmlElemType et, const QDomElement& elem );
+ // Given an attribute name and value, constructs an XML representation of the attribute,
+ // i.e., name="value".
+ QString makeAttr( const QString& name, const QString& value );
+ // Returns an XML representation of an SSML tag from the top of the context stack.
+ QString makeSsmlElem( SsmlElemType et );
+ // Pops element from the indicated context stack.
+ void popSsmlElem( SsmlElemType et );
+ QString makeBreakElem( const QDomElement& e );
+ // Converts a text fragment into a CDATA section.
+ QString makeCDATA( const QString& text );
+ // Returns an XML representation of an utterance node consisting of voice,
+ // prosody, and emphasis elements.
+ QString makeSentence( const QString& text );
+ // Starts a sentence by returning a speak tag.
+ QString startSentence();
+ // Ends a sentence and appends a Tab.
+ QString endSentence();
+ // Parses a node of the SSML tree and recursively parses its children.
+ // Returns the filtered text with each sentence a complete ssml tree.
+ QString parseSsmlNode( QDomNode& n, const QString& re );
+
+ // Parses Ssml.
+ QString parseSsml( const QString& inputText, const QString& re );
+ // Parses code. Each newline is converted into a tab character (\t).
+ QString parseCode( const QString& inputText );
+ // Parses plain text.
+ QString parsePlainText( const QString& inputText, const QString& re );
+
+ // Context stacks.
+ QValueStack<SpeakElem> m_speakStack;
+ QValueStack<VoiceElem> m_voiceStack;
+ QValueStack<ProsodyElem> m_prosodyStack;
+ QValueStack<EmphasisElem> m_emphasisStack;
+ QValueStack<PSElem> m_psStack;
+
+ // The text being processed.
+ QString m_text;
+ // Talker Code.
+ TalkerCode* m_talkerCode;
+ // Configured default Sentence Delimiter regular expression.
+ QString m_configuredRe;
+ // Configured Sentence Boundary replacement expression.
+ QString m_configuredSentenceBoundary;
+ // Application-specified Sentence Delimiter regular expression (if any).
+ QString m_re;
+ // False if input was not modified.
+ bool m_wasModified;
+ // True when a sentence has been started.
+ bool m_sentenceStarted;
+};
+
+class SbdProc : virtual public KttsFilterProc
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor.
+ */
+ SbdProc( QObject *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor.
+ */
+ virtual ~SbdProc();
+
+ /**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+ virtual bool init( KConfig *config, const QString &configGroup );
+
+ /**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * If so, the filter should implement @ref setSbRegExp() .
+ * @return True if this filter is a SBD.
+ */
+ virtual bool isSBD();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Convert input, returning output. Runs synchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+ virtual QString convert( const QString& inputText, TalkerCode* talkerCode, const QCString& appId );
+
+ /**
+ * Convert input. Runs asynchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ * @return False if the filter cannot perform the conversion.
+ *
+ * When conversion is completed, emits signal @ref filteringFinished. Calling
+ * program may then call @ref getOutput to retrieve converted text. Calling
+ * program must call @ref ackFinished to acknowledge the conversion.
+ */
+ virtual bool asyncConvert( const QString& inputText, TalkerCode* talkerCode, const QCString& appId );
+
+ /**
+ * Waits for a previous call to asyncConvert to finish.
+ */
+ virtual void waitForFinished();
+
+ /**
+ * Returns the state of the Filter.
+ */
+ virtual int getState();
+
+ /**
+ * Returns the filtered output.
+ */
+ virtual QString getOutput();
+
+ /**
+ * Acknowledges the finished filtering.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Stops filtering. The filteringStopped signal will emit when filtering
+ * has in fact stopped and state returns to fsIdle;
+ */
+ virtual void stopFiltering();
+
+ /**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+ virtual bool wasModified();
+
+ /**
+ * Set Sentence Boundary Regular Expression.
+ */
+ virtual void setSbRegExp( const QString& re );
+
+ private slots:
+ // Received when SBD Thread finishes.
+ void slotSbdThreadFilteringFinished();
+
+ private:
+ // If not empty, apply filters only to apps using talkers speaking these language codes.
+ QStringList m_languageCodeList;
+ // If not empty, apply filter only to apps containing this string.
+ QStringList m_appIdList;
+ // SBD Thread Object.
+ SbdThread* m_sbdThread;
+ // State.
+ int m_state;
+ // Configured default Sentence Delimiter regular expression.
+ QString m_configuredRe;
+};
+
+#endif // _SBDPROC_H_
diff --git a/kttsd/filters/sbd/standard_sbdrc b/kttsd/filters/sbd/standard_sbdrc
new file mode 100644
index 0000000..76037a5
--- /dev/null
+++ b/kttsd/filters/sbd/standard_sbdrc
@@ -0,0 +1,6 @@
+[Filter]
+AppID=
+LanguageCodes=
+SentenceBoundary=\\1\\t
+SentenceDelimiterRegExp=([\\.\\?\\!\\:\\;])(\\s|$|(\\n *\\n))
+UserFilterName=Standard Sentence Boundary Detector
diff --git a/kttsd/filters/stringreplacer/Makefile.am b/kttsd/filters/stringreplacer/Makefile.am
new file mode 100644
index 0000000..b52085c
--- /dev/null
+++ b/kttsd/filters/stringreplacer/Makefile.am
@@ -0,0 +1,34 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_stringreplacerplugin.la
+
+libkttsd_stringreplacerplugin_la_SOURCES = \
+ stringreplacerconfwidget.ui \
+ editreplacementwidget.ui \
+ stringreplacerconf.cpp \
+ stringreplacerproc.cpp \
+ stringreplacerplugin.cpp
+libkttsd_stringreplacerplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_stringreplacerplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_stringreplacerplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+# Install data files.
+stringreplacerdatadir = $(kde_datadir)/kttsd/stringreplacer/
+stringreplacerdata_DATA = \
+ abbreviations.xml \
+ chat.xml \
+ chat-de.xml \
+ emoticons.xml \
+ polish_festival_fixes.xml \
+ polish_festival_unspeakables.xml \
+ kmail.xml \
+ festival_unspeakable_chars.xml \
+ qt2plaintext.xml
+
+noinst_HEADERS = stringreplacerconfwidget.h editreplacementwidget.h
diff --git a/kttsd/filters/stringreplacer/abbreviations.xml b/kttsd/filters/stringreplacer/abbreviations.xml
new file mode 100644
index 0000000..d04b7aa
--- /dev/null
+++ b/kttsd/filters/stringreplacer/abbreviations.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Abbreviations</name>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[TODO]]></match>
+ <subst><![CDATA[To Do]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[CPU]]></match>
+ <subst><![CDATA[C P U]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[DCOP]]></match>
+ <subst><![CDATA[D Cop]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[IP]]></match>
+ <subst><![CDATA[I P]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[KDE]]></match>
+ <subst><![CDATA[K D E]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[KTTS]]></match>
+ <subst><![CDATA[K T T S]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kttsd]]></match>
+ <subst><![CDATA[K T T S D]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[KTTSD]]></match>
+ <subst><![CDATA[K T T S D]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[TTS]]></match>
+ <subst><![CDATA[T T S]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/chat-de.xml b/kttsd/filters/stringreplacer/chat-de.xml
new file mode 100644
index 0000000..801c144
--- /dev/null
+++ b/kttsd/filters/stringreplacer/chat-de.xml
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Internet Relay Chat and IM (Deutsch)</name>
+ <language-code>de</language-code>
+ <appid>knotify</appid>
+ <appid>kopete</appid>
+ <appid>kvirc</appid>
+ <appid>ksirc</appid>
+ <appid>konversation</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<qt>]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[&lt([^>]+)&gt]]></match>
+ <subst><![CDATA[ \1 meint ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<br>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</qt>]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\;\)]]></match>
+ <subst><![CDATA[ winkt]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\<]]></match>
+ <subst><![CDATA[ traurig]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\/]]></match>
+ <subst><![CDATA[stirnrunzeln]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\>]]></match>
+ <subst><![CDATA[ grinst]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\|]]></match>
+ <subst><![CDATA[ernsthaft]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\|]]></match>
+ <subst><![CDATA[ernsthaft]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\)]]></match>
+ <subst><![CDATA[ laechelt]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\'\(]]></match>
+ <subst><![CDATA[weint]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\(]]></match>
+ <subst><![CDATA[ traurig]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\)]]></match>
+ <subst><![CDATA[ laechelt]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\@]]></match>
+ <subst><![CDATA[ boese]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\$]]></match>
+ <subst><![CDATA[ schaemt sich]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\@\)]]></match>
+ <subst><![CDATA[ katzengesicht]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(6\)]]></match>
+ <subst><![CDATA[ teufelsfratze]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(a\)]]></match>
+ <subst><![CDATA[ engelsgesicht]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:D]]></match>
+ <subst><![CDATA[ grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(h\)]]></match>
+ <subst><![CDATA[ kuhl]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\so\_O]]></match>
+ <subst><![CDATA[ winkt]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:p]]></match>
+ <subst><![CDATA[ baeh]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(s\)]]></match>
+ <subst><![CDATA[ gaehn]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ad]]></match>
+ <subst><![CDATA[fuege hinzu]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[afaik]]></match>
+ <subst><![CDATA[soviel ich weiss]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[afk]]></match>
+ <subst><![CDATA[nicht an tastatur]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[asap]]></match>
+ <subst><![CDATA[so schnell wie moeglich]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[atm]]></match>
+ <subst><![CDATA[momentan]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ayt]]></match>
+ <subst><![CDATA[bist du da]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b4]]></match>
+ <subst><![CDATA[vorher]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b4n]]></match>
+ <subst><![CDATA[tschuess]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bak]]></match>
+ <subst><![CDATA[zurueck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bbl]]></match>
+ <subst><![CDATA[komme spaeter wieder]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bf]]></match>
+ <subst><![CDATA[freund]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b/f]]></match>
+ <subst><![CDATA[freund]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[brb]]></match>
+ <subst><![CDATA[bin gleich wieder da]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[btw]]></match>
+ <subst><![CDATA[nebenbei bemerkt]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cu]]></match>
+ <subst><![CDATA[bis dann]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cul]]></match>
+ <subst><![CDATA[bis spaeter]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cul8r]]></match>
+ <subst><![CDATA[bis spaeter]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cya]]></match>
+ <subst><![CDATA[bis spaeter]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[d/l]]></match>
+ <subst><![CDATA[daunlohd]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[dvd]]></match>
+ <subst><![CDATA[die wie die]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[f2f]]></match>
+ <subst><![CDATA[von angesicht zu angesicht]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[fubar]]></match>
+ <subst><![CDATA[leuft trotz reparatur nicht]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[fyi]]></match>
+ <subst><![CDATA[zu deiner information]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[gf]]></match>
+ <subst><![CDATA[freundin]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[g/f]]></match>
+ <subst><![CDATA[freundin]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[gtg]]></match>
+ <subst><![CDATA[ich muss weck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[hmm]]></match>
+ <subst><![CDATA[aehm]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[hth]]></match>
+ <subst><![CDATA[hoffe es hilft]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ic]]></match>
+ <subst><![CDATA[verstehe]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[iirc]]></match>
+ <subst><![CDATA[wenn ich recht erinnere]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imao]]></match>
+ <subst><![CDATA[meiner arroganten meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imco]]></match>
+ <subst><![CDATA[meiner wohlueberlegten meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ime]]></match>
+ <subst><![CDATA[meiner erfahrung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imho]]></match>
+ <subst><![CDATA[meiner bescheidenen meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imnsho]]></match>
+ <subst><![CDATA[meiner unbescheidenen meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imo]]></match>
+ <subst><![CDATA[meiner meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ip]]></match>
+ <subst><![CDATA[ei pie]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[isdn]]></match>
+ <subst><![CDATA[i es de en]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[k]]></match>
+ <subst><![CDATA[ho key]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kde]]></match>
+ <subst><![CDATA[ka de eh]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kbd]]></match>
+ <subst><![CDATA[tastatur]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lshmba]]></match>
+ <subst><![CDATA[halte mir den bauch vor lachen]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lthtt]]></match>
+ <subst><![CDATA[unbeschreibliches gelaechter]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ltns]]></match>
+ <subst><![CDATA[lange nicht gesehen]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lol]]></match>
+ <subst><![CDATA[h h h]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[m8]]></match>
+ <subst><![CDATA[kumpel]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[msg]]></match>
+ <subst><![CDATA[nachricht]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[np]]></match>
+ <subst><![CDATA[kein problem]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[oic]]></match>
+ <subst><![CDATA[oh verstehe]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ok]]></match>
+ <subst><![CDATA[ho key]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ott]]></match>
+ <subst><![CDATA[übertreiben]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[pc]]></match>
+ <subst><![CDATA[pie cie]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ppc]]></match>
+ <subst><![CDATA[power pie cie]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ppl]]></match>
+ <subst><![CDATA[leute]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rotfl]]></match>
+ <subst><![CDATA[kugelt sich vor lachen]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rotflol]]></match>
+ <subst><![CDATA[bruellt vor lachen]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rsvp]]></match>
+ <subst><![CDATA[antworte bitte]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[scsi]]></match>
+ <subst><![CDATA[skasi]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[suse]]></match>
+ <subst><![CDATA[suse]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[sec]]></match>
+ <subst><![CDATA[sekunde]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[secs]]></match>
+ <subst><![CDATA[sekunden]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[thx]]></match>
+ <subst><![CDATA[danke]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[tnx]]></match>
+ <subst><![CDATA[danke]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wo]]></match>
+ <subst><![CDATA[ohne]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wb]]></match>
+ <subst><![CDATA[willkommen urueck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtf]]></match>
+ <subst><![CDATA[was zum teufel]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wth]]></match>
+ <subst><![CDATA[was zum teufel]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtg]]></match>
+ <subst><![CDATA[gut gemacht]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtgp]]></match>
+ <subst><![CDATA[bitte um privatchett]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wth]]></match>
+ <subst><![CDATA[was zum teufel]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wygiswypf]]></match>
+ <subst><![CDATA[was du kriegst ist was du bezahlst]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[yw]]></match>
+ <subst><![CDATA[gruess diche]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\_]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\|]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\\o\/]]></match>
+ <subst><![CDATA[tschuess]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\/o\\]]></match>
+ <subst><![CDATA[haelt sich die ohren zu]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\:\-\/]]></match>
+ <subst><![CDATA[stirnrunzeln]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/chat.xml b/kttsd/filters/stringreplacer/chat.xml
new file mode 100644
index 0000000..2518824
--- /dev/null
+++ b/kttsd/filters/stringreplacer/chat.xml
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Internet Relay Chat and IM</name>
+ <language-code>en</language-code>
+ <appid>knotify</appid>
+ <appid>kopete</appid>
+ <appid>kvirc</appid>
+ <appid>ksirc</appid>
+ <appid>konversation</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<qt>]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[&lt([^>]+)&gt]]></match>
+ <subst><![CDATA[ \1 says ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<br>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</qt>]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\;\)]]></match>
+ <subst><![CDATA[ winks]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\<]]></match>
+ <subst><![CDATA[ sad face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\/]]></match>
+ <subst><![CDATA[ frowns ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\>]]></match>
+ <subst><![CDATA[ grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\|]]></match>
+ <subst><![CDATA[ straight faced]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\|]]></match>
+ <subst><![CDATA[ straight faced]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\)]]></match>
+ <subst><![CDATA[ smiles]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\'\(]]></match>
+ <subst><![CDATA[ cries]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\(]]></match>
+ <subst><![CDATA[ sad face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\)]]></match>
+ <subst><![CDATA[ smiles]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\@]]></match>
+ <subst><![CDATA[ angry look]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\$]]></match>
+ <subst><![CDATA[ blushes]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\@\)]]></match>
+ <subst><![CDATA[ cat face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(6\)]]></match>
+ <subst><![CDATA[ devil]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(a\)]]></match>
+ <subst><![CDATA[ angel]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:D]]></match>
+ <subst><![CDATA[ grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(h\)]]></match>
+ <subst><![CDATA[ cool shades]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\so\_O]]></match>
+ <subst><![CDATA[ winks]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:p]]></match>
+ <subst><![CDATA[ sticks out tung]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(s\)]]></match>
+ <subst><![CDATA[ sleepy]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ad]]></match>
+ <subst><![CDATA[add]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[afaik]]></match>
+ <subst><![CDATA[as far as I know]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[afk]]></match>
+ <subst><![CDATA[away from keyboard]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[asap]]></match>
+ <subst><![CDATA[as soon as possable]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[atm]]></match>
+ <subst><![CDATA[at the moment]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ayt]]></match>
+ <subst><![CDATA[are you there]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b4]]></match>
+ <subst><![CDATA[before]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b4n]]></match>
+ <subst><![CDATA[bye for now]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bak]]></match>
+ <subst><![CDATA[back]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bbl]]></match>
+ <subst><![CDATA[be back later]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bf]]></match>
+ <subst><![CDATA[boy friend]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b/f]]></match>
+ <subst><![CDATA[boy friend]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[brb]]></match>
+ <subst><![CDATA[be right back]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[btw]]></match>
+ <subst><![CDATA[by the way]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cu]]></match>
+ <subst><![CDATA[see you]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cul]]></match>
+ <subst><![CDATA[see you later]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cul8r]]></match>
+ <subst><![CDATA[see you later]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cya]]></match>
+ <subst><![CDATA[see you later]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[d/l]]></match>
+ <subst><![CDATA[down load]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[dvd]]></match>
+ <subst><![CDATA[de vee de]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[f2f]]></match>
+ <subst><![CDATA[face to face]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[fubar]]></match>
+ <subst><![CDATA[fecked up beyond all repair]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[fyi]]></match>
+ <subst><![CDATA[for your information]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[gf]]></match>
+ <subst><![CDATA[girl friend]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[g/f]]></match>
+ <subst><![CDATA[girl friend]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[gtg]]></match>
+ <subst><![CDATA[got to go]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[hmm]]></match>
+ <subst><![CDATA[hurrmmm]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[hth]]></match>
+ <subst><![CDATA[hope that helps]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ic]]></match>
+ <subst><![CDATA[i see]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[iirc]]></match>
+ <subst><![CDATA[if I recall correctly]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imao]]></match>
+ <subst><![CDATA[in my arrogant opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imco]]></match>
+ <subst><![CDATA[in my considered opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ime]]></match>
+ <subst><![CDATA[in my experience]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imho]]></match>
+ <subst><![CDATA[in my humble opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imnsho]]></match>
+ <subst><![CDATA[in my not so humble opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imo]]></match>
+ <subst><![CDATA[in my opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ip]]></match>
+ <subst><![CDATA[i p]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[isdn]]></match>
+ <subst><![CDATA[i s d n]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[k]]></match>
+ <subst><![CDATA[ho kay]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kde]]></match>
+ <subst><![CDATA[k d e]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kbd]]></match>
+ <subst><![CDATA[keyboard]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lshmba]]></match>
+ <subst><![CDATA[laughing so hard my belly aches]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lthtt]]></match>
+ <subst><![CDATA[laughing too hard to type]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ltns]]></match>
+ <subst><![CDATA[long time no see]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lol]]></match>
+ <subst><![CDATA[lafes out loud]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[m8]]></match>
+ <subst><![CDATA[mate]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[msg]]></match>
+ <subst><![CDATA[message]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[np]]></match>
+ <subst><![CDATA[no problem]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[oic]]></match>
+ <subst><![CDATA[oh i see]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ok]]></match>
+ <subst><![CDATA[ho kay]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ott]]></match>
+ <subst><![CDATA[over the top]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[pc]]></match>
+ <subst><![CDATA[p c]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ppc]]></match>
+ <subst><![CDATA[power p c]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ppl]]></match>
+ <subst><![CDATA[people]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rotfl]]></match>
+ <subst><![CDATA[rolling on the floor laughing]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rotflol]]></match>
+ <subst><![CDATA[rolling on the floor laughing out loud]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rsvp]]></match>
+ <subst><![CDATA[please reply]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[scsi]]></match>
+ <subst><![CDATA[scuzy]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[suse]]></match>
+ <subst><![CDATA[sue see]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[sec]]></match>
+ <subst><![CDATA[second]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[secs]]></match>
+ <subst><![CDATA[seconds]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[thx]]></match>
+ <subst><![CDATA[thanks]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[tnx]]></match>
+ <subst><![CDATA[thanks]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wo]]></match>
+ <subst><![CDATA[without]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wb]]></match>
+ <subst><![CDATA[welcome back]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtf]]></match>
+ <subst><![CDATA[what the heck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wth]]></match>
+ <subst><![CDATA[what the heck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtg]]></match>
+ <subst><![CDATA[way to go]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtgp]]></match>
+ <subst><![CDATA[want to go private]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wth]]></match>
+ <subst><![CDATA[what the heck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wygiswypf]]></match>
+ <subst><![CDATA[what you get is what you pay for]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[yw]]></match>
+ <subst><![CDATA[your welcome]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\_]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\|]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\\o\/]]></match>
+ <subst><![CDATA[ cheers ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\/o\\]]></match>
+ <subst><![CDATA[ covers ears ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\:\-\/]]></match>
+ <subst><![CDATA[ frowns ]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/editreplacementwidget.ui b/kttsd/filters/stringreplacer/editreplacementwidget.ui
new file mode 100644
index 0000000..917cdf8
--- /dev/null
+++ b/kttsd/filters/stringreplacer/editreplacementwidget.ui
@@ -0,0 +1,263 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>EditReplacementWidget</class>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>EditReplacementWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>393</width>
+ <height>148</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>255</horstretch>
+ <verstretch>255</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>typeButtonGroup</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>&amp;Type</string>
+ </property>
+ <property name="exclusive">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>wordRadioButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Word</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>regexpRadioButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Regular &amp;expression</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>caseCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Match &amp;case</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>substLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Replace with:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>matchLineEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>matchLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Match:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>matchLineEdit</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>substLineEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>matchButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="0">
+ <property name="name">
+ <cstring>matchLineEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>wordRadioButton</tabstop>
+ <tabstop>regexpRadioButton</tabstop>
+ <tabstop>caseCheckBox</tabstop>
+ <tabstop>matchLineEdit</tabstop>
+ <tabstop>matchButton</tabstop>
+ <tabstop>substLineEdit</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/filters/stringreplacer/emoticons.xml b/kttsd/filters/stringreplacer/emoticons.xml
new file mode 100644
index 0000000..f522358
--- /dev/null
+++ b/kttsd/filters/stringreplacer/emoticons.xml
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Emoticons (English)</name>
+ <language-code>en</language-code>
+ <appid>knotify</appid>
+ <appid>kopete</appid>
+ <appid>ksirc</appid>
+ <appid>kvirc</appid>
+ <appid>konversation</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\)]]></match>
+ <subst><![CDATA[. smiles]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\)]]></match>
+ <subst><![CDATA[. smiles]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\p]]></match>
+ <subst><![CDATA[. sticks out tung]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:D]]></match>
+ <subst><![CDATA[. grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\>]]></match>
+ <subst><![CDATA[.grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\;\)]]></match>
+ <subst><![CDATA[. winks]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\o\_\0]]></match>
+ <subst><![CDATA[. winks]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\(]]></match>
+ <subst><![CDATA[. sad face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\<]]></match>
+ <subst><![CDATA[. sad face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\\:\|]]></match>
+ <subst><![CDATA[. straight faced]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\|]]></match>
+ <subst><![CDATA[. straight faced]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\$]]></match>
+ <subst><![CDATA[. blushes]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\\(h\)]]></match>
+ <subst><![CDATA[. cool shades]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\@]]></match>
+ <subst><![CDATA[. angry look]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\'\(]]></match>
+ <subst><![CDATA[. cries]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(a\)]]></match>
+ <subst><![CDATA[. angel]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(6\)]]></match>
+ <subst><![CDATA[. devil]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\%\)]]></match>
+ <subst><![CDATA[. hand cuffs]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\[\]]></match>
+ <subst><![CDATA[. bat]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\@\)]]></match>
+ <subst><![CDATA[. cat face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\&\)]]></match>
+ <subst><![CDATA[. dog face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\*\)]]></match>
+ <subst><![CDATA[. star]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(s\)]]></match>
+ <subst><![CDATA[. sleepy]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(Y\)]]></match>
+ <subst><![CDATA[. thumbs up]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(n\)]]></match>
+ <subst><![CDATA[. thumbs down]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\}\)]]></match>
+ <subst><![CDATA[. girl huggs]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\{\)]]></match>
+ <subst><![CDATA[. boy huggs]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(l\)]]></match>
+ <subst><![CDATA[. love]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(U\)]]></match>
+ <subst><![CDATA[. is hart brooken]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(k\)]]></match>
+ <subst><![CDATA[. kisses]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\^\)]]></match>
+ <subst><![CDATA[. birthday cake]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(g\)]]></match>
+ <subst><![CDATA[. a gift]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(f\)]]></match>
+ <subst><![CDATA[. flower]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(w\)]]></match>
+ <subst><![CDATA[. willted flower]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(t\)]]></match>
+ <subst><![CDATA[. telephone]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(e\)]]></match>
+ <subst><![CDATA[. e mail]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(m\)]]></match>
+ <subst><![CDATA[. messenger]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(o\)]]></match>
+ <subst><![CDATA[. time]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(x\)]]></match>
+ <subst><![CDATA[. girl]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(z\)]]></match>
+ <subst><![CDATA[. boy]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(p\)]]></match>
+ <subst><![CDATA[. picture]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\~\)]]></match>
+ <subst><![CDATA[. film]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(b\)]]></match>
+ <subst><![CDATA[. glass of beer]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(d\)]]></match>
+ <subst><![CDATA[. glass of wine]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\#\)]]></match>
+ <subst><![CDATA[. sunny]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(r\)]]></match>
+ <subst><![CDATA[. rainbow]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(8\)]]></match>
+ <subst><![CDATA[. note]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(i\)]]></match>
+ <subst><![CDATA[. idea]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(c\)]]></match>
+ <subst><![CDATA[. coffee cup]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/festival_unspeakable_chars.xml b/kttsd/filters/stringreplacer/festival_unspeakable_chars.xml
new file mode 100644
index 0000000..5086d01
--- /dev/null
+++ b/kttsd/filters/stringreplacer/festival_unspeakable_chars.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Fix Festival Unspeakable Characters</name>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x80]]></match>
+ <subst><![CDATA[ Euro ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x82]]></match>
+ <subst><![CDATA[']]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x84]]></match>
+ <subst><![CDATA["]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x85]]></match>
+ <subst><![CDATA[...]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x89]]></match>
+ <subst><![CDATA[ per Mille ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x8B]]></match>
+ <subst><![CDATA[<]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[\x91-\x92]]]></match>
+ <subst><![CDATA[']]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[\x93-\x94]]]></match>
+ <subst><![CDATA["]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[\x96-\x97]]]></match>
+ <subst><![CDATA[-]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x98]]></match>
+ <subst><![CDATA[~]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x99]]></match>
+ <subst><![CDATA[ trademark ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x9B]]></match>
+ <subst><![CDATA[>]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[\x80-\x9F]]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\{]]></match>
+ <subst><![CDATA[ left curly brace ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\}]]></match>
+ <subst><![CDATA[ right curly brace ]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/kmail.xml b/kttsd/filters/stringreplacer/kmail.xml
new file mode 100644
index 0000000..b0f33d6
--- /dev/null
+++ b/kttsd/filters/stringreplacer/kmail.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Filter by David Power achiestdragon@gmail.com -->
+<wordlist>
+ <name>kmail notify</name>
+ <appid>knotify</appid>
+ <appid>kmail</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<br>]]></match>
+ <subst><![CDATA[,]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</b>]]></match>
+ <subst><![CDATA[,]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[in /local/inbox]]></match>
+ <subst><![CDATA[,]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<b>]]></match>
+ <subst><![CDATA[,]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/kttsd_stringreplacerplugin.desktop b/kttsd/filters/stringreplacer/kttsd_stringreplacerplugin.desktop
new file mode 100644
index 0000000..df8214c
--- /dev/null
+++ b/kttsd/filters/stringreplacer/kttsd_stringreplacerplugin.desktop
@@ -0,0 +1,92 @@
+[Desktop Entry]
+Name=String Replacer
+Name[bg]=Замяна на низове
+Name[ca]=Reemplaçador de cadenes
+Name[cs]=Nahrazení řetězce
+Name[da]=Streng-erstatter
+Name[de]=Zeichenkettenersetzer
+Name[el]=Αντικαταστάτης συμβολοσειρών
+Name[es]=Reemplazador de cadenas
+Name[et]=Stringiasendaja
+Name[eu]=Kate-ordezkatzailea
+Name[fa]=جایگزین‌کنندۀ رشته
+Name[fi]=Tekstien korvaaja
+Name[fr]=Remplacement de chaînes
+Name[ga]=Ionadóir Teaghrán
+Name[gl]=Reemprazamento de Cadeas
+Name[he]=מחליף מחרוזות
+Name[hu]=Sztringcserélő
+Name[is]=Strengja útskiptir
+Name[it]=Sostitutore di stringhe
+Name[ja]=文字列置換
+Name[ka]=სტრიქონის ჩამნაცვლებელი
+Name[km]= ឧបករណ៍​ជំនួស​ខ្សែ​អក្សរ
+Name[lt]=Eilučių pakeitiklis
+Name[mk]=Менувач на низи знаци
+Name[ms]=Pengganti Rentetan
+Name[nb]=Strengerstatter
+Name[nds]=Tekenkeed-Tuscher
+Name[ne]=स्ट्रिङ प्रतिस्थापक
+Name[nl]=Tekstvervanger
+Name[pa]=ਸਤਰ ਤਬਦੀਲ
+Name[pl]=Zastępowanie tekstu
+Name[pt]=Substituição de Textos
+Name[pt_BR]=Substituidor de Strings
+Name[ru]=Автозамена
+Name[sk]=Náhrada reťazca
+Name[sl]=Zamenjevalnik nizov
+Name[sr]=Замењивач знаковних низова
+Name[sr@Latn]=Zamenjivač znakovnih nizova
+Name[sv]=Strängersättning
+Name[ta]=சர இடமாற்றி
+Name[tg]=Ҷойивазкунии автоматӣ
+Name[tr]=Metin Değiştirici
+Name[uk]=Заміна рядків
+Name[vi]=Trình thay Chuỗi
+Name[zh_TW]=字串置換器
+Comment=Generic String Replacement Filter Plugin for KTTS
+Comment[bg]=Приставка филтър за замяна на низове за KTTS
+Comment[ca]=Connector del filtre reemplaçador genèric de cadenes pel KTTS
+Comment[cs]=Modul filtru náhrady řetězce KTTS
+Comment[da]=Generisk strengerstatnings-filter-plugin for KTTS
+Comment[de]=Ein generisches Modul zur Zeichenkettenersetzung für KTTS
+Comment[el]=Γενικό φίλτρο πρόσθετο αντικατάστασης συμβολοσειρών για το KTTS
+Comment[es]=Complemento de filtro genérico de sustituición de cadenas para KTTS
+Comment[et]=KTTS-i üldine stringiasendusfiltri plugin
+Comment[eu]=KTTS-ren kateak ordezkatzeko iragazki-plugin generikoa
+Comment[fa]=وصلۀ پالایۀ جایگزینی رشتۀ عمومی برای KTTS
+Comment[fi]=Yleinen tekstien korvaussuodatinliitännäinen KTTS-ohjelmaan
+Comment[fr]=Module de filtrage de remplacement de chaînes générique pour KTTS
+Comment[gl]=Plugin de Filtro Xenérico de Substituición de Cadeas para KTTS
+Comment[hu]=Általános sztringcserélő modul a KTTS-hez
+Comment[is]=Almennt strengja útskiptinga íforrit fyrir KTTS
+Comment[it]=Plugin generico per il filtro di sostituzione di stringhe per KTTS
+Comment[ja]=KTTS 用汎用文字列置換フィルタプラグイン
+Comment[ka]=ზოგადი სტრიქონის ჩანაცვლების ფილტრის მოდული KTTS-სთვის
+Comment[km]=កម្មវិធី​ជំនួយ​តម្រង​ការ​ជំនួស​ខ្សែអក្សរ​ទូទៅ​សម្រាប់ KTTS
+Comment[lt]=Bendro pobūdžio eilučių pakeitimo filtro priedas, skirtas KTTS
+Comment[mk]=Филтер за KTTS за општа замена на низи знаци
+Comment[ms]=Plugin Penapis Penggantian Rentetan Generik bagi KTTS
+Comment[nb]=Filter-programtillegg til KTTS for streng-erstatning
+Comment[nds]=KTTS-Filtermoduul för dat Utwesseln vun Tekenkeden
+Comment[ne]=KTTS का लागि जेनेरीक स्ट्रिङ प्रतिस्थापन फिल्टर प्लगइन
+Comment[nl]=Generieke tekst-vervang-filter-plugin voor KTTS
+Comment[pl]=Wtyczka zastępowania tekstu dla KTTS
+Comment[pt]='Plugin' Genérico de Substituição de Textos para o KTTS
+Comment[pt_BR]=Plug-in de Filtro genérico de Substituição de Strings Para o KTTS
+Comment[ru]=Фильтр автозамены для KTTS
+Comment[sk]=Všeobecný modul filtra náhrady reťazca v KTTS
+Comment[sl]=Filtrni vstavek KTTS za generični zamenjevalnik nizov
+Comment[sr]=Генерички филтерски прикључак KTTS-а за замену знаковних низова
+Comment[sr@Latn]=Generički filterski priključak KTTS-a za zamenu znakovnih nizova
+Comment[sv]=Insticksprogram för KTTS med generellt strängersättningsfilter
+Comment[ta]=KTTSக்கான அலங்கார சொருகுபொருள் சர இடமாற்றி
+Comment[tg]=Филтри худивазкунӣ барои KTTS
+Comment[tr]=KTTS için Genel Metin Değiştirme Süzgeci Eklentisi
+Comment[uk]=Втулок загального фільтра заміни рядків для KTTS
+Comment[vi]=Trình bổ sung Lọc Thay Chuỗi Chung cho KTTS
+Comment[zh_TW]=KTTS 使用的字串置換外掛程式
+Type=Service
+ServiceTypes=KTTSD/FilterPlugin
+X-KDE-Library=libkttsd_stringreplacerplugin
+X-KDE-Languages=en,en_US,en_GB,en_CA,es,es_mx,cy,de,fi,cs,pl
diff --git a/kttsd/filters/stringreplacer/polish_festival_fixes.xml b/kttsd/filters/stringreplacer/polish_festival_fixes.xml
new file mode 100644
index 0000000..a6f2533
--- /dev/null
+++ b/kttsd/filters/stringreplacer/polish_festival_fixes.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Author of filter: Mikolaj Machowski ( mikmach AT wp DOT pl ) -->
+<wordlist>
+ <name>Filtr polski / Filter for Polish Festival voice</name>
+ <language-code>pl</language-code>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[^a-zA-Z0-9ęóąśłżźćńĘÓĄŚŁŻŹĆŃ\,\"\'\\@#$%^*+=`~]]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/polish_festival_unspeakables.xml b/kttsd/filters/stringreplacer/polish_festival_unspeakables.xml
new file mode 100644
index 0000000..8fbc18a
--- /dev/null
+++ b/kttsd/filters/stringreplacer/polish_festival_unspeakables.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Author of filter: Mikolaj Machowski ( mikmach AT wp DOT pl ) -->
+<wordlist>
+ <name>Polskie niewymawialne / Polish Festival unspeakables</name>
+ <language-code>pl</language-code>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\(]]></match>
+ <subst><![CDATA[ otwieram nawias ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\)]]></match>
+ <subst><![CDATA[ zamykam nawias ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\{]]></match>
+ <subst><![CDATA[ otwieram nawias klamrowy ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\}]]></match>
+ <subst><![CDATA[ zamykam nawias klamrowy ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\[]]></match>
+ <subst><![CDATA[ otwieram nawias kwadratowy ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\]]]></match>
+ <subst><![CDATA[ zamykam nawias kwadratowy ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\<]]></match>
+ <subst><![CDATA[ otwieram nawias trójkątny ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\>]]></match>
+ <subst><![CDATA[ zamykam nawias trójkątny ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\_]]></match>
+ <subst><![CDATA[ znak podkreślenia ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\&]]></match>
+ <subst><![CDATA[ i ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\/]]></match>
+ <subst><![CDATA[ slesz ]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[\\]]></match>
+ <subst><![CDATA[ bekslesz ]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/qt2plaintext.xml b/kttsd/filters/stringreplacer/qt2plaintext.xml
new file mode 100644
index 0000000..8a194ec
--- /dev/null
+++ b/kttsd/filters/stringreplacer/qt2plaintext.xml
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Qt Rich Text to Plain Text</name>
+ <appid>knotify</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<qt>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</qt>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<h1>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<h2>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<h3>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</h1>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</h2>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</h3>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<p>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</p>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<center>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</center>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<blockquote>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</blockquote>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<ul>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</ul>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<ol>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</ol>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<li>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</li>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<a>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</a>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<em>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</em>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<strong>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</strong>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<bold>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</bold>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<b>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</b>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<u>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</u>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<big>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</big>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<small>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</small>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<hr/>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<br/>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<nobr>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</nobr>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<table>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</table>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<tr>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</tr>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<td>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</td>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<th>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</th>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<img src\=]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<a href\=]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[/>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<img>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[">]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<pre>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</pre>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<tt>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</tt>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<code>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</code>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/stringreplacerconf.cpp b/kttsd/filters/stringreplacer/stringreplacerconf.cpp
new file mode 100644
index 0000000..9afa2d5
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerconf.cpp
@@ -0,0 +1,725 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic String Replacement Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qstring.h>
+#include <qhbox.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qradiobutton.h>
+
+// KDE includes.
+#include <kglobal.h>
+#include <klocale.h>
+#include <klistview.h>
+#include <klineedit.h>
+#include <kdialog.h>
+#include <kdialogbase.h>
+#include <kpushbutton.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kregexpeditorinterface.h>
+#include <ktrader.h>
+#include <kparts/componentfactory.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+
+// KTTS includes.
+#include "filterconf.h"
+
+// StringReplacer includes.
+#include "stringreplacerconf.h"
+#include "stringreplacerconf.moc"
+#include "editreplacementwidget.h"
+
+/**
+* Constructor
+*/
+StringReplacerConf::StringReplacerConf( QWidget *parent, const char *name, const QStringList& /*args*/) :
+ KttsFilterConf(parent, name),
+ m_editDlg(0),
+ m_editWidget(0)
+{
+ // kdDebug() << "StringReplacerConf::StringReplacerConf: Running" << endl;
+
+ // Create configuration widget.
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "StringReplacerConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new StringReplacerConfWidget(this, "StringReplacerConfigWidget");
+ layout->addWidget(m_widget);
+ m_widget->substLView->setSortColumn(-1);
+
+ connect(m_widget->nameLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->languageBrowseButton, SIGNAL(clicked()),
+ this, SLOT(slotLanguageBrowseButton_clicked()));
+ connect(m_widget->addButton, SIGNAL(clicked()),
+ this, SLOT(slotAddButton_clicked()));
+ connect(m_widget->upButton, SIGNAL(clicked()),
+ this, SLOT(slotUpButton_clicked()));
+ connect(m_widget->downButton, SIGNAL(clicked()),
+ this, SLOT(slotDownButton_clicked()));
+ connect(m_widget->editButton, SIGNAL(clicked()),
+ this, SLOT(slotEditButton_clicked()));
+ connect(m_widget->removeButton, SIGNAL(clicked()),
+ this, SLOT(slotRemoveButton_clicked()));
+ connect(m_widget->loadButton, SIGNAL(clicked()),
+ this, SLOT(slotLoadButton_clicked()));
+ connect(m_widget->saveButton, SIGNAL(clicked()),
+ this, SLOT(slotSaveButton_clicked()));
+ connect(m_widget->clearButton, SIGNAL(clicked()),
+ this, SLOT(slotClearButton_clicked()));
+ connect(m_widget->substLView, SIGNAL(selectionChanged()),
+ this, SLOT(enableDisableButtons()));
+ connect(m_widget->appIdLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+
+ // Determine if kdeutils Regular Expression Editor is installed.
+ m_reEditorInstalled = !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty();
+
+ // Set up defaults.
+ defaults();
+}
+
+/**
+* Destructor.
+*/
+StringReplacerConf::~StringReplacerConf(){
+ // kdDebug() << "StringReplacerConf::~StringReplacerConf: Running" << endl;
+}
+
+/**
+* This method is invoked whenever the module should read its
+* configuration (most of the times from a config file) and update the
+* user interface. This happens when the user clicks the "Reset" button in
+* the control center, to undo all of his changes and restore the currently
+* valid settings. Note that kttsmgr calls this when the plugin is
+* loaded, so it not necessary to call it in your constructor.
+* The plugin should read its configuration from the specified group
+* in the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* loading your configuration.
+*/
+void StringReplacerConf::load(KConfig* config, const QString& configGroup){
+ // kdDebug() << "StringReplacerConf::load: Running" << endl;
+ // See if this filter previously save its word list.
+ config->setGroup( configGroup );
+ QString wordsFilename = config->readEntry( "WordListFile" );
+ if ( !wordsFilename.isEmpty() )
+ {
+ QString errMsg = loadFromFile( wordsFilename, true );
+ if ( !errMsg.isEmpty() )
+ kdDebug() << "StringReplacerConf::load: " << errMsg << endl;
+ enableDisableButtons();
+ }
+}
+
+// Loads word list and settings from a file. Clearing configuration if clear is True.
+QString StringReplacerConf::loadFromFile( const QString& filename, bool clear)
+{
+ // Open existing word list.
+ QFile file( filename );
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ return i18n("Unable to open file.") + filename;
+ }
+ // QDomDocument doc( "http://www.kde.org/share/apps/kttsd/stringreplacer/wordlist.dtd []" );
+ QDomDocument doc( "" );
+ if ( !doc.setContent( &file ) ) {
+ file.close();
+ return i18n("File not in proper XML format.");
+ }
+ // kdDebug() << "StringReplacerConf::load: document successfully parsed." << endl;
+ file.close();
+
+ // Clear list view.
+ if ( clear ) m_widget->substLView->clear();
+
+ // Name setting.
+ QDomNodeList nameList = doc.elementsByTagName( "name" );
+ QDomNode nameNode = nameList.item( 0 );
+ m_widget->nameLineEdit->setText( nameNode.toElement().text() );
+ // kdDebug() << "StringReplacerConf::load: name = " << nameNode.toElement().text() << endl;
+
+ // Language Codes setting. List may be single element of comma-separated values,
+ // or multiple elements.
+ QString languageCodes;
+ QDomNodeList languageList = doc.elementsByTagName( "language-code" );
+ for ( uint ndx=0; ndx < languageList.count(); ++ndx )
+ {
+ QDomNode languageNode = languageList.item( ndx );
+ if (!languageCodes.isEmpty()) languageCodes += ",";
+ languageCodes += languageNode.toElement().text();
+ }
+ if ( clear )
+ m_languageCodeList = QStringList::split(',', languageCodes, false);
+ else
+ m_languageCodeList += QStringList::split(',', languageCodes, false);
+ QString language;
+ m_languageCodeList.sort();
+ // Eliminate dups.
+ for ( int ndx = m_languageCodeList.count() - 2; ndx >= 0; --ndx )
+ {
+ if ( m_languageCodeList[ndx] == m_languageCodeList[ndx+1] )
+ m_languageCodeList.remove(m_languageCodeList.at(ndx+1));
+ }
+ for ( uint ndx=0; ndx < m_languageCodeList.count(); ++ndx )
+ {
+ if (!language.isEmpty()) language += ",";
+ language += KGlobal::locale()->twoAlphaToLanguageName(m_languageCodeList[ndx]);
+ }
+ m_widget->languageLineEdit->setText(language);
+
+ // AppId. Apply this filter only if DCOP appId of application that queued
+ // the text contains this string. List may be single element of comma-separated values,
+ // or multiple elements.
+ QDomNodeList appIdList = doc.elementsByTagName( "appid" );
+ QString appIds;
+ for ( uint ndx=0; ndx < appIdList.count(); ++ndx )
+ {
+ QDomNode appIdNode = appIdList.item( ndx );
+ if (!appIds.isEmpty()) appIds += ",";
+ appIds += appIdNode.toElement().text();
+ }
+ if ( !clear ) appIds = m_widget->appIdLineEdit->text() + appIds;
+ m_widget->appIdLineEdit->setText( appIds );
+
+ // Word list.
+ QListViewItem* item = 0;
+ if ( !clear ) item = m_widget->substLView->lastChild();
+ QDomNodeList wordList = doc.elementsByTagName("word");
+ const int wordListCount = wordList.count();
+ for (int wordIndex = 0; wordIndex < wordListCount; ++wordIndex)
+ {
+ // kdDebug() << "StringReplacerConf::load: start parsing of word " << wordIndex << endl;
+ QDomNode wordNode = wordList.item(wordIndex);
+ QDomNodeList propList = wordNode.childNodes();
+ QString wordType;
+ QString matchCase = "No"; // Default for old (v<=3.5.3) config files with no <case/>.
+ QString match;
+ QString subst;
+ const int propListCount = propList.count();
+ for (int propIndex = 0; propIndex < propListCount; ++propIndex)
+ {
+ QDomNode propNode = propList.item(propIndex);
+ QDomElement prop = propNode.toElement();
+ if (prop.tagName() == "type") wordType = prop.text();
+ if (prop.tagName() == "case") matchCase = prop.text();
+ if (prop.tagName() == "match") match = prop.text();
+ if (prop.tagName() == "subst") subst = prop.text();
+ }
+ QString wordTypeStr =
+ (wordType=="RegExp"?i18n("Abbreviation for 'Regular Expression'", "RegExp"):i18n("Word"));
+ QString matchCaseStr =
+ (matchCase=="Yes"?i18n("Yes"):i18n("No"));
+ if (!item)
+ item = new KListViewItem(m_widget->substLView, wordTypeStr, matchCaseStr, match, subst);
+ else
+ item = new KListViewItem(m_widget->substLView, item, wordTypeStr, matchCaseStr, match, subst);
+ }
+
+ return QString::null;
+}
+
+/**
+* This function gets called when the user wants to save the settings in
+* the user interface, updating the config files or wherever the
+* configuration is stored. The method is called when the user clicks "Apply"
+* or "Ok". The plugin should save its configuration in the specified
+* group of the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* saving your configuration.
+*/
+void StringReplacerConf::save(KConfig* config, const QString& configGroup){
+ // kdDebug() << "StringReplacerConf::save: Running" << endl;
+ QString wordsFilename =
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/stringreplacer/", true );
+ if ( wordsFilename.isEmpty() )
+ {
+ kdDebug() << "StringReplacerConf::save: no save location" << endl;
+ return;
+ }
+ wordsFilename += configGroup;
+ QString errMsg = saveToFile( wordsFilename );
+ if ( errMsg.isEmpty() )
+ {
+ config->setGroup( configGroup );
+ config->writeEntry( "WordListFile", realFilePath(wordsFilename) );
+ }
+ else
+ kdDebug() << "StringReplacerConf::save: " << errMsg << endl;
+}
+
+// Saves word list and settings to a file.
+QString StringReplacerConf::saveToFile(const QString& filename)
+{
+ // kdDebug() << "StringReplacerConf::saveToFile: saving to file " << wordsFilename << endl;
+
+ QFile file( filename );
+ if ( !file.open( IO_WriteOnly ) )
+ return i18n("Unable to open file ") + filename;
+
+ // QDomDocument doc( "http://www.kde.org/share/apps/kttsd/stringreplacer/wordlist.dtd []" );
+ QDomDocument doc( "" );
+
+ QDomElement root = doc.createElement( "wordlist" );
+ doc.appendChild( root );
+
+ // Name.
+ QDomElement name = doc.createElement( "name" );
+ root.appendChild( name );
+ QDomText t = doc.createTextNode( m_widget->nameLineEdit->text() );
+ name.appendChild( t );
+
+ // Language code.
+ for ( uint ndx=0; ndx < m_languageCodeList.count(); ++ndx )
+ {
+ QDomElement languageCode = doc.createElement( "language-code" );
+ root.appendChild( languageCode );
+ t = doc.createTextNode( m_languageCodeList[ndx] );
+ languageCode.appendChild( t );
+ }
+
+ // Application ID
+ QString appId = m_widget->appIdLineEdit->text().replace(" ", "");
+ if ( !appId.isEmpty() )
+ {
+ QStringList appIdList = QStringList::split(",", appId);
+ for ( uint ndx=0; ndx < appIdList.count(); ++ndx )
+ {
+ QDomElement appIdElem = doc.createElement( "appid" );
+ root.appendChild( appIdElem );
+ t = doc.createTextNode( appIdList[ndx] );
+ appIdElem.appendChild( t );
+ }
+ }
+
+ // Words.
+ QListView* lView = m_widget->substLView;
+ QListViewItem* item = lView->firstChild();
+ while (item)
+ {
+ QDomElement wordTag = doc.createElement( "word" );
+ root.appendChild( wordTag );
+ QDomElement propTag = doc.createElement( "type" );
+ wordTag.appendChild( propTag);
+ QDomText t = doc.createTextNode( item->text(0)==i18n("Word")?"Word":"RegExp" );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "case" );
+ wordTag.appendChild( propTag);
+ t = doc.createTextNode( item->text(1)==i18n("Yes")?"Yes":"No" );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "match" );
+ wordTag.appendChild( propTag);
+ t = doc.createCDATASection( item->text(2) );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "subst" );
+ wordTag.appendChild( propTag);
+ t = doc.createCDATASection( item->text(3) );
+ propTag.appendChild( t );
+
+ item = item->nextSibling();
+ }
+
+ // Write it all out.
+ QTextStream ts( &file );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ ts << doc.toString();
+ // kdDebug() << "StringReplacerConf::saveToFile: writing out " << doc.toString() << endl;
+ file.close();
+
+ return QString::null;
+}
+
+/**
+* This function is called to set the settings in the module to sensible
+* default values. It gets called when hitting the "Default" button. The
+* default values should probably be the same as the ones the application
+* uses when started without a config file. Note that defaults should
+* be applied to the on-screen widgets; not to the config file.
+*/
+void StringReplacerConf::defaults(){
+ // kdDebug() << "StringReplacerConf::defaults: Running" << endl;
+ // Default language is none.
+ m_languageCodeList.clear();
+ m_widget->languageLineEdit->setText( "" );
+ // Default name.
+ m_widget->nameLineEdit->setText( i18n("String Replacer") );
+ m_widget->substLView->clear();
+ // Default App ID is blank.
+ m_widget->appIdLineEdit->setText( "" );
+ enableDisableButtons();
+ // kdDebug() << "StringReplacerConf::defaults: Exiting" << endl;
+}
+
+/**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+bool StringReplacerConf::supportsMultiInstance() { return true; }
+
+/**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+QString StringReplacerConf::userPlugInName()
+{
+ if ( m_widget->substLView->childCount() == 0 ) return QString::null;
+ QString instName = m_widget->nameLineEdit->text();
+ if ( instName.isEmpty() )
+ {
+ QString language;
+ if (m_languageCodeList.count() == 1)
+ language = KGlobal::locale()->twoAlphaToLanguageName(m_languageCodeList[0]);
+ if (m_languageCodeList.count() > 1)
+ language = i18n("Multiple Languages");
+ if (!language.isEmpty())
+ instName = i18n("String Replacer") + " (" + language + ")";
+ }
+ return instName;
+}
+
+void StringReplacerConf::slotLanguageBrowseButton_clicked()
+{
+ // Create a QHBox to host KListView.
+ QHBox* hBox = new QHBox(m_widget, "SelectLanguage_hbox");
+ // Create a KListView and fill with all known languages.
+ KListView* langLView = new KListView(hBox, "SelectLanguage_lview");
+ langLView->addColumn(i18n("Language"));
+ langLView->addColumn(i18n("Code"));
+ langLView->setSelectionMode(QListView::Extended);
+ QStringList allLocales = KGlobal::locale()->allLanguagesTwoAlpha();
+ QString locale;
+ QString languageCode;
+ QString countryCode;
+ QString charSet;
+ QString language;
+ // Blank line so user can select no language.
+ QListViewItem* item = new KListViewItem(langLView, "", "");
+ if (m_languageCodeList.isEmpty()) item->setSelected(true);
+ const int allLocalesCount = allLocales.count();
+ for (int ndx=0; ndx < allLocalesCount; ++ndx)
+ {
+ locale = allLocales[ndx];
+ KGlobal::locale()->splitLocale(locale, languageCode, countryCode, charSet);
+ language = KGlobal::locale()->twoAlphaToLanguageName(languageCode);
+ if (!countryCode.isEmpty()) language +=
+ " (" + KGlobal::locale()->twoAlphaToCountryName(countryCode)+")";
+ item = new KListViewItem(langLView, language, locale);
+ if (m_languageCodeList.contains(locale)) item->setSelected(true);
+ }
+ // Sort by language.
+ langLView->setSorting(0);
+ langLView->sort();
+ // Display the box in a dialog.
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Select Languages"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_widget,
+ "SelectLanguage_dlg",
+ true,
+ true);
+ dlg->setMainWidget(hBox);
+ dlg->setHelp("", "kttsd");
+ dlg->setInitialSize(QSize(300, 500), false);
+ int dlgResult = dlg->exec();
+ languageCode = QString::null;
+ if (dlgResult == QDialog::Accepted)
+ {
+ m_languageCodeList.clear();
+ QListViewItem* item = langLView->firstChild();
+ while (item)
+ {
+ if (item->isSelected()) m_languageCodeList += item->text(1);
+ item = item->nextSibling();
+ }
+ }
+ delete dlg;
+ // TODO: Also delete KListView and QHBox?
+ if (dlgResult != QDialog::Accepted) return;
+ language = "";
+ for ( uint ndx=0; ndx < m_languageCodeList.count(); ++ndx)
+ {
+ if (!language.isEmpty()) language += ",";
+ language += KGlobal::locale()->twoAlphaToLanguageName(m_languageCodeList[ndx]);
+ }
+ QString s1 = m_widget->languageLineEdit->text();
+ m_widget->languageLineEdit->setText(language);
+ // Replace language in the user's filter name.
+ QString s2 = m_widget->nameLineEdit->text();
+ if (m_languageCodeList.count() > 1) language = i18n("Multiple Languages");
+ if ( !s1.isEmpty() )
+ {
+ s2.replace( s1, language );
+ s2.replace( i18n("Multiple Languages"), language );
+ }
+ s2.replace(" ()", "");
+ if ( !s2.contains("(") && !language.isEmpty() ) s2 += " (" + language + ")";
+ m_widget->nameLineEdit->setText(s2);
+ configChanged();
+}
+
+void StringReplacerConf::enableDisableButtons()
+{
+ bool enableBtn = (m_widget->substLView->selectedItem() != 0);
+ if (enableBtn)
+ {
+ m_widget->upButton->setEnabled(
+ m_widget->substLView->selectedItem()->itemAbove() != 0);
+ m_widget->downButton->setEnabled(
+ m_widget->substLView->selectedItem()->itemBelow() != 0);
+ } else {
+ m_widget->upButton->setEnabled(false);
+ m_widget->downButton->setEnabled(false);
+ }
+ m_widget->editButton->setEnabled(enableBtn);
+ m_widget->removeButton->setEnabled(enableBtn);
+ m_widget->clearButton->setEnabled(m_widget->substLView->firstChild());
+ m_widget->saveButton->setEnabled(m_widget->substLView->firstChild());
+}
+
+void StringReplacerConf::slotUpButton_clicked()
+{
+ QListViewItem* item = m_widget->substLView->selectedItem();
+ if (!item) return;
+ QListViewItem* prevItem = item->itemAbove();
+ if (!prevItem) return;
+ prevItem->moveItem(item);
+ m_widget->substLView->setSelected(item, true);
+ m_widget->substLView->ensureItemVisible(item);
+ enableDisableButtons();
+ configChanged();
+}
+
+void StringReplacerConf::slotDownButton_clicked()
+{
+ QListViewItem* item = m_widget->substLView->selectedItem();
+ if (!item) return;
+ QListViewItem* nextItem = item->itemBelow();
+ if (!nextItem) return;
+ item->moveItem(nextItem);
+ m_widget->substLView->setSelected(item, true);
+ m_widget->substLView->ensureItemVisible(item);
+ enableDisableButtons();
+ configChanged();
+}
+
+void StringReplacerConf::slotAddButton_clicked()
+{
+ addOrEditSubstitution( true );
+}
+
+void StringReplacerConf::slotEditButton_clicked()
+{
+ addOrEditSubstitution( false );
+}
+
+// Displays the add/edit string replacement dialog.
+void StringReplacerConf::addOrEditSubstitution(bool isAdd)
+{
+ QListViewItem* item = 0;
+ if (isAdd)
+ item = m_widget->substLView->lastChild();
+ else
+ {
+ item = m_widget->substLView->selectedItem();
+ if (!item) return;
+ }
+ // Create a QHBox to host widget.
+ QHBox* hBox = new QHBox(m_widget, "AddOrEditSubstitution_hbox" );
+ // Create widget.
+ m_editWidget = new EditReplacementWidget( hBox, "AddOrEditSubstitution_widget" );
+ // Set controls if editing existing.
+ m_editWidget->matchButton->setEnabled( false );
+ if (!isAdd)
+ {
+ if ( item->text(0) == i18n("Abbreviation for 'Regular Expression'", "RegExp") )
+ {
+ m_editWidget->regexpRadioButton->setChecked( true );
+ m_editWidget->matchButton->setEnabled( m_reEditorInstalled );
+ }
+ m_editWidget->caseCheckBox->setChecked( (item->text(1))==i18n("Yes") );
+ m_editWidget->matchLineEdit->setText( item->text(2) );
+ m_editWidget->substLineEdit->setText( item->text(3) );
+ }
+ // The match box may not be blank.
+ connect( m_editWidget->matchLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotMatchLineEdit_textChanged(const QString&)) );
+ connect( m_editWidget->regexpRadioButton, SIGNAL(clicked()),
+ this, SLOT(slotTypeButtonGroup_clicked()) );
+ connect( m_editWidget->wordRadioButton, SIGNAL(clicked()),
+ this, SLOT(slotTypeButtonGroup_clicked()) );
+ connect( m_editWidget->matchButton, SIGNAL(clicked()),
+ this, SLOT(slotMatchButton_clicked()) );
+ // Display the box in a dialog.
+ m_editDlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Edit String Replacement"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_widget,
+ "AddOrEditSubstitution_dlg",
+ true,
+ true);
+ // Disable OK button if match field blank.
+ m_editDlg->setMainWidget( hBox );
+ m_editDlg->setHelp( "", "kttsd" );
+ m_editDlg->enableButton( KDialogBase::Ok, !m_editWidget->matchLineEdit->text().isEmpty() );
+ int dlgResult = m_editDlg->exec();
+ QString substType = i18n( "Word" );
+ if ( m_editWidget->regexpRadioButton->isChecked() )
+ substType = i18n("Abbreviation for 'Regular Expression'", "RegExp");
+ QString matchCase = i18n("No");
+ if ( m_editWidget->caseCheckBox->isChecked() ) matchCase = i18n("Yes");
+ QString match = m_editWidget->matchLineEdit->text();
+ QString subst = m_editWidget->substLineEdit->text();
+ delete m_editDlg;
+ m_editDlg = 0;
+ m_editWidget = 0;
+ if (dlgResult != QDialog::Accepted) return;
+ // TODO: Also delete hBox and w?
+ if ( match.isEmpty() ) return;
+ if ( isAdd )
+ {
+ if ( item )
+ item = new KListViewItem( m_widget->substLView, item, substType, matchCase, match, subst );
+ else
+ item = new KListViewItem( m_widget->substLView, substType, matchCase, match, subst );
+ m_widget->substLView->setSelected( item, true );
+ }
+ else
+ {
+ item->setText( 0, substType );
+ item->setText( 1, matchCase );
+ item->setText( 2, match );
+ item->setText( 3, subst );
+ }
+ m_widget->substLView->ensureItemVisible( item );
+ enableDisableButtons();
+ configChanged();
+}
+
+void StringReplacerConf::slotMatchLineEdit_textChanged(const QString& text)
+{
+ // Disable OK button if match field blank.
+ if ( !m_editDlg ) return;
+ m_editDlg->enableButton( KDialogBase::Ok, !text.isEmpty() );
+}
+
+void StringReplacerConf::slotRemoveButton_clicked()
+{
+ QListViewItem* item = m_widget->substLView->selectedItem();
+ if (!item) return;
+ delete item;
+ enableDisableButtons();
+ configChanged();
+}
+
+void StringReplacerConf::slotTypeButtonGroup_clicked()
+{
+ // Enable Regular Expression Editor button if editor is installed (requires kdeutils).
+ if ( !m_editWidget ) return;
+ m_editWidget->matchButton->setEnabled( m_editWidget->regexpRadioButton->isOn() && m_reEditorInstalled );
+}
+
+void StringReplacerConf::slotMatchButton_clicked()
+{
+ // Show Regular Expression Editor dialog if it is installed.
+ if ( !m_editWidget ) return;
+ if ( !m_editDlg ) return;
+ if ( !m_reEditorInstalled ) return;
+ QDialog *editorDialog =
+ KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor" );
+ if ( editorDialog )
+ {
+ // kdeutils was installed, so the dialog was found. Fetch the editor interface.
+ KRegExpEditorInterface *reEditor =
+ static_cast<KRegExpEditorInterface *>(editorDialog->qt_cast( "KRegExpEditorInterface" ) );
+ Q_ASSERT( reEditor ); // This should not fail!// now use the editor.
+ reEditor->setRegExp( m_editWidget->matchLineEdit->text() );
+ int dlgResult = editorDialog->exec();
+ if ( dlgResult == QDialog::Accepted )
+ {
+ QString re = reEditor->regExp();
+ m_editWidget->matchLineEdit->setText( re );
+ m_editDlg->enableButton( KDialogBase::Ok, !re.isEmpty() );
+ }
+ delete editorDialog;
+ } else return;
+}
+
+void StringReplacerConf::slotLoadButton_clicked()
+{
+ // QString dataDir = KGlobal::dirs()->resourceDirs("data").last() + "/kttsd/stringreplacer/";
+ QString dataDir = KGlobal::dirs()->findAllResources("data", "kttsd/stringreplacer/").last();
+ QString filename = KFileDialog::getOpenFileName(
+ dataDir,
+ "*.xml|String Replacer Word List (*.xml)",
+ m_widget,
+ "stringreplacer_loadfile");
+ if ( filename.isEmpty() ) return;
+ QString errMsg = loadFromFile( filename, false );
+ enableDisableButtons();
+ if ( !errMsg.isEmpty() )
+ KMessageBox::sorry( m_widget, errMsg, i18n("Error Opening File") );
+ else
+ configChanged();
+}
+
+void StringReplacerConf::slotSaveButton_clicked()
+{
+ QString filename = KFileDialog::getSaveFileName(
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/stringreplacer/", false ),
+ "*.xml|String Replacer Word List (*.xml)",
+ m_widget,
+ "stringreplacer_savefile");
+ if ( filename.isEmpty() ) return;
+ QString errMsg = saveToFile( filename );
+ enableDisableButtons();
+ if ( !errMsg.isEmpty() )
+ KMessageBox::sorry( m_widget, errMsg, i18n("Error Opening File") );
+}
+
+void StringReplacerConf::slotClearButton_clicked()
+{
+ m_widget->substLView->clear();
+ enableDisableButtons();
+}
diff --git a/kttsd/filters/stringreplacer/stringreplacerconf.h b/kttsd/filters/stringreplacer/stringreplacerconf.h
new file mode 100644
index 0000000..f0312a6
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerconf.h
@@ -0,0 +1,158 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic String Replacement Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _STRINGREPLACERCONF_H_
+#define _STRINGREPLACERCONF_H_
+
+// Qt includes.
+#include <qwidget.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "filterconf.h"
+
+// StringReplacer includes.
+#include "stringreplacerconfwidget.h"
+
+class KDialogBase;
+class EditReplacementWidget;
+
+class StringReplacerConf : public KttsFilterConf
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ StringReplacerConf( QWidget *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor
+ */
+ virtual ~StringReplacerConf();
+
+ enum SubstitutionType {
+ stWord, // Word
+ stRegExp // Regular Expression
+ };
+
+ /**
+ * This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. Note that KTTSMGR calls this when the plugin is
+ * loaded, so it not necessary to call it in your constructor.
+ * The plugin should read its configuration from the specified group
+ * in the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * loading your configuration.
+ *
+ * When a plugin is first added to KTTSMGR, @e load will be called with
+ * a Null @e configGroup. In this case, the plugin will not have
+ * any instance-specific parameters to load, but it may still wish
+ * to load parameters that apply to all instances of the plugin.
+ */
+ virtual void load(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok". The plugin should save its configuration in the specified
+ * group of the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * saving your configuration.
+ */
+ virtual void save(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file. Note that defaults should
+ * be applied to the on-screen widgets; not to the config file.
+ */
+ virtual void defaults();
+
+ /**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+ virtual bool supportsMultiInstance();
+
+ /**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+ virtual QString userPlugInName();
+
+ private slots:
+ void slotLanguageBrowseButton_clicked();
+ void slotAddButton_clicked();
+ void slotUpButton_clicked();
+ void slotDownButton_clicked();
+ void slotEditButton_clicked();
+ void slotRemoveButton_clicked();
+ void slotMatchLineEdit_textChanged(const QString& text);
+ void slotTypeButtonGroup_clicked();
+ void slotMatchButton_clicked();
+ void slotLoadButton_clicked();
+ void slotSaveButton_clicked();
+ void slotClearButton_clicked();
+
+ // EnablesDisables buttons depending upon current item in list view.
+ void enableDisableButtons();
+
+ private:
+ // Displays the add/edit string replacement dialog.
+ void addOrEditSubstitution(bool isAdd);
+ // Loads word list and settings from a file. Clearing configuration if clear is True.
+ QString loadFromFile( const QString& filename, bool clear);
+ // Saves word list and settings to a file.
+ QString saveToFile( const QString& filename );
+
+
+ // Configuration Widget.
+ StringReplacerConfWidget* m_widget;
+ // Edit Dialog and widget.
+ KDialogBase* m_editDlg;
+ EditReplacementWidget* m_editWidget;
+ // True if kdeutils Regular Expression Editor is installed.
+ bool m_reEditorInstalled;
+ // Language Codes.
+ QStringList m_languageCodeList;
+};
+
+#endif //_STRINGREPLACERCONF_H_
diff --git a/kttsd/filters/stringreplacer/stringreplacerconfwidget.ui b/kttsd/filters/stringreplacer/stringreplacerconfwidget.ui
new file mode 100644
index 0000000..e88307f
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerconfwidget.ui
@@ -0,0 +1,474 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>StringReplacerConfWidget</class>
+<comment>Widget for configuring String Replacer Filter for KTTSD.</comment>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>StringReplacerConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>548</width>
+ <height>421</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Configure String Replacer</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>nameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Name:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any name you like for this filter.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any name you like for this filter.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox" row="3" column="0">
+ <property name="name">
+ <cstring>applyGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Apply This &amp;Filter When</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>These settings determines when the filter is applied to text.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Lan&amp;guage is:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>languageLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank the filter applies to all text jobs of any language.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>appIdLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Application &amp;ID contains:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter a DCOP Application ID. This filter will only apply to text jobs queued by that application. You may enter more than one ID separated by commas. If blank, this filter applies to text jobs queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>languageLineEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank the filter applies to all text jobs of any language.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>languageBrowseButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to select one or more languages. This filter will be applied to text jobs of those languages.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter a DCOP Application ID. This filter will only apply to text jobs queued by that application. You may enter more than one ID separated by commas. Use &lt;b&gt;knotify&lt;/b&gt; to match all messages sent as KDE notifications. If blank, this filter applies to text jobs queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>loadButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Load...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to load a word list from a file.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>saveButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Save...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to save word list to a file.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>clearButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>C&amp;lear</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to empty the word list.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout24</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Match Case</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Match</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Replace With</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>substLView</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout23</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Add...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to add another word or regular expression to the list.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>upButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Up</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to move selected word up in the list. Words higher in the list are applied first.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>downButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Do&amp;wn</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to move a word down in the list. Words lower in the list are applied last.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>editButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Edit...</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to modify an existing word or regular expression in the list.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>removeButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to remove a word or regular expression from the list.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer13</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>nameLineEdit</tabstop>
+ <tabstop>substLView</tabstop>
+ <tabstop>addButton</tabstop>
+ <tabstop>upButton</tabstop>
+ <tabstop>downButton</tabstop>
+ <tabstop>editButton</tabstop>
+ <tabstop>removeButton</tabstop>
+ <tabstop>loadButton</tabstop>
+ <tabstop>saveButton</tabstop>
+ <tabstop>clearButton</tabstop>
+ <tabstop>languageLineEdit</tabstop>
+ <tabstop>languageBrowseButton</tabstop>
+ <tabstop>appIdLineEdit</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/filters/stringreplacer/stringreplacerplugin.cpp b/kttsd/filters/stringreplacer/stringreplacerplugin.cpp
new file mode 100644
index 0000000..c3f9678
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerplugin.cpp
@@ -0,0 +1,32 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so String Replacer Filter can be used as plug in.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "stringreplacerconf.h"
+#include "stringreplacerproc.h"
+
+typedef K_TYPELIST_2( StringReplacerProc, StringReplacerConf ) StringReplacerPlugin;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_stringreplacerplugin,
+ KGenericFactory<StringReplacerPlugin>("kttsd_stringreplacer") )
+
diff --git a/kttsd/filters/stringreplacer/stringreplacerproc.cpp b/kttsd/filters/stringreplacer/stringreplacerproc.cpp
new file mode 100644
index 0000000..1b03810
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerproc.cpp
@@ -0,0 +1,231 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic String Replacement Filter Processing class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qdom.h>
+#include <qfile.h>
+#include <qlistview.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+
+// KTTS includes.
+#include "filterproc.h"
+#include "talkercode.h"
+
+// StringReplacer includes.
+#include "stringreplacerproc.h"
+#include "stringreplacerproc.moc"
+
+/**
+ * Constructor.
+ */
+StringReplacerProc::StringReplacerProc( QObject *parent, const char *name, const QStringList& ) :
+ KttsFilterProc(parent, name)
+{
+}
+
+/**
+ * Destructor.
+ */
+/*virtual*/ StringReplacerProc::~StringReplacerProc()
+{
+ m_matchList.clear();
+ m_caseList.clear();
+ m_substList.clear();
+}
+
+/**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+bool StringReplacerProc::init(KConfig* config, const QString& configGroup){
+ // kdDebug() << "StringReplacerProc::init: Running" << endl;
+ QString wordsFilename =
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/stringreplacer/", false );
+ if ( wordsFilename.isEmpty() ) return false;
+ wordsFilename += configGroup;
+ config->setGroup( configGroup );
+ wordsFilename = config->readEntry( "WordListFile", wordsFilename );
+
+ // Open existing word list.
+ QFile file( wordsFilename );
+ if ( !file.open( IO_ReadOnly ) )
+ return false;
+ QDomDocument doc( "" );
+ if ( !doc.setContent( &file ) ) {
+ file.close();
+ return false;
+ }
+ file.close();
+
+ // Clear list.
+ m_matchList.clear();
+ m_caseList.clear();
+ m_substList.clear();
+
+ // Name setting.
+ // QDomNodeList nameList = doc.elementsByTagName( "name" );
+ // QDomNode nameNode = nameList.item( 0 );
+ // m_widget->nameLineEdit->setText( nameNode.toElement().text() );
+
+ // Language Codes setting. List may be single element of comma-separated values,
+ // or multiple elements.
+ m_languageCodeList.clear();
+ QDomNodeList languageList = doc.elementsByTagName( "language-code" );
+ for ( uint ndx=0; ndx < languageList.count(); ++ndx )
+ {
+ QDomNode languageNode = languageList.item( ndx );
+ m_languageCodeList += QStringList::split(',', languageNode.toElement().text(), false);
+ }
+
+ // AppId. Apply this filter only if DCOP appId of application that queued
+ // the text contains this string. List may be single element of comma-separated values,
+ // or multiple elements.
+ m_appIdList.clear();
+ QDomNodeList appIdList = doc.elementsByTagName( "appid" );
+ for ( uint ndx=0; ndx < appIdList.count(); ++ndx )
+ {
+ QDomNode appIdNode = appIdList.item( ndx );
+ m_appIdList += QStringList::split(',', appIdNode.toElement().text(), false);
+ }
+
+ // Word list.
+ QDomNodeList wordList = doc.elementsByTagName("word");
+ const int wordListCount = wordList.count();
+ for (int wordIndex = 0; wordIndex < wordListCount; ++wordIndex)
+ {
+ QDomNode wordNode = wordList.item(wordIndex);
+ QDomNodeList propList = wordNode.childNodes();
+ QString wordType;
+ QString matchCase = "No"; // Default for old (v<=3.5.3) config files with no <case/>.
+ QString match;
+ QString subst;
+ const int propListCount = propList.count();
+ for (int propIndex = 0; propIndex < propListCount; ++propIndex)
+ {
+ QDomNode propNode = propList.item(propIndex);
+ QDomElement prop = propNode.toElement();
+ if (prop.tagName() == "type") wordType = prop.text();
+ if (prop.tagName() == "case") matchCase = prop.text();
+ if (prop.tagName() == "match") match = prop.text();
+ if (prop.tagName() == "subst") subst = prop.text();
+ }
+ // Build Regular Expression for each word's match string.
+ QRegExp rx;
+ rx.setCaseSensitive(matchCase == "Yes");
+ if ( wordType == "Word" )
+ {
+ // TODO: Does \b honor strange non-Latin1 encodings?
+ rx.setPattern( "\\b" + match + "\\b" );
+ }
+ else
+ {
+ rx.setPattern( match );
+ }
+ // Add Regular Expression to list (if valid).
+ if ( rx.isValid() )
+ {
+ m_matchList.append( rx );
+ m_substList.append( subst );
+ }
+ }
+ return true;
+}
+
+/**
+ * Convert input, returning output.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+/*virtual*/ QString StringReplacerProc::convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId)
+{
+ m_wasModified = false;
+ // If language doesn't match, return input unmolested.
+ if ( !m_languageCodeList.isEmpty() )
+ {
+ QString languageCode = talkerCode->languageCode();
+ // kdDebug() << "StringReplacerProc::convert: converting " << inputText <<
+ // " if language code " << languageCode << " matches " << m_languageCodeList << endl;
+ if ( !m_languageCodeList.contains( languageCode ) )
+ {
+ if ( !talkerCode->countryCode().isEmpty() )
+ {
+ languageCode += '_' + talkerCode->countryCode();
+ // kdDebug() << "StringReplacerProc::convert: converting " << inputText <<
+ // " if language code " << languageCode << " matches " << m_languageCodeList << endl;
+ if ( !m_languageCodeList.contains( languageCode ) ) return inputText;
+ } else return inputText;
+ }
+ }
+ // If appId doesn't match, return input unmolested.
+ if ( !m_appIdList.isEmpty() )
+ {
+ // kdDebug() << "StringReplacerProc::convert: converting " << inputText << " if appId "
+ // << appId << " matches " << m_appIdList << endl;
+ bool found = false;
+ QString appIdStr = appId;
+ for ( uint ndx=0; ndx < m_appIdList.count(); ++ndx )
+ {
+ if ( appIdStr.contains(m_appIdList[ndx]) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ {
+ // kdDebug() << "StringReplacerProc::convert: appId not found" << endl;
+ return inputText;
+ }
+ }
+ QString newText = inputText;
+ const int listCount = m_matchList.count();
+ for ( int index = 0; index < listCount; ++index )
+ {
+ //kdDebug() << "newtext = " << newText << " matching " << m_matchList[index].pattern() << " replacing with " << m_substList[index] << endl;
+ newText.replace( m_matchList[index], m_substList[index] );
+ }
+ m_wasModified = true;
+ return newText;
+}
+
+/**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+/*virtual*/ bool StringReplacerProc::wasModified() { return m_wasModified; }
+
diff --git a/kttsd/filters/stringreplacer/stringreplacerproc.h b/kttsd/filters/stringreplacer/stringreplacerproc.h
new file mode 100644
index 0000000..114ebaf
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerproc.h
@@ -0,0 +1,97 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic String Replacement Filter Processing class.
+ This is the interface definition for text filters.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _STRINGREPLACERPROC_H_
+#define _STRINGREPLACERPROC_H_
+
+// Qt includes.
+#include <qobject.h>
+#include <qtextstream.h>
+#include <qvaluelist.h>
+#include <qregexp.h>
+#include <qstringlist.h>
+
+// KTTS includes.
+#include "filterproc.h"
+
+class StringReplacerProc : virtual public KttsFilterProc
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ */
+ StringReplacerProc( QObject *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor.
+ */
+ virtual ~StringReplacerProc();
+
+ /**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Convert input, returning output.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+ virtual QString convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+ /**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+ virtual bool wasModified();
+
+private:
+ // Language codes supported by the filter.
+ QStringList m_languageCodeList;
+ // If not empty, apply filter only to apps containing one or more of these strings.
+ QStringList m_appIdList;
+
+ // List of regular expressions to match.
+ QValueList<QRegExp> m_matchList;
+ // List of match case flag
+ QValueList<QString> m_caseList;
+ // List of substitutions to replace matches.
+ QValueList<QString> m_substList;
+ // True if this filter did anything to the text.
+ bool m_wasModified;
+};
+
+#endif // _STRINGREPLACERPROC_H_
diff --git a/kttsd/filters/talkerchooser/Makefile.am b/kttsd/filters/talkerchooser/Makefile.am
new file mode 100644
index 0000000..66f857d
--- /dev/null
+++ b/kttsd/filters/talkerchooser/Makefile.am
@@ -0,0 +1,25 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_talkerchooserplugin.la
+
+libkttsd_talkerchooserplugin_la_SOURCES = \
+ talkerchooserconfwidget.ui \
+ talkerchooserconf.cpp \
+ talkerchooserproc.cpp \
+ talkerchooserplugin.cpp
+libkttsd_talkerchooserplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_talkerchooserplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_talkerchooserplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+# Install data files.
+talkerchooserdatadir = $(kde_datadir)/kttsd/talkerchooser/
+talkerchooserdata_DATA = \
+ female_notifications_rc
+
+noinst_HEADERS = talkerchooserconfwidget.h
diff --git a/kttsd/filters/talkerchooser/female_notifications_rc b/kttsd/filters/talkerchooser/female_notifications_rc
new file mode 100644
index 0000000..1cbd94c
--- /dev/null
+++ b/kttsd/filters/talkerchooser/female_notifications_rc
@@ -0,0 +1,10 @@
+[Filter]
+AppIDs=knotify
+Gender=*female
+LanguageCode=
+MatchRegExp=
+Rate=
+SynthName=
+TalkerCode=<voice gender="*female" />
+UserFilterName=Obsolete. Use Notifications tab instead.
+Volume=
diff --git a/kttsd/filters/talkerchooser/kttsd_talkerchooserplugin.desktop b/kttsd/filters/talkerchooser/kttsd_talkerchooserplugin.desktop
new file mode 100644
index 0000000..cdf1e45
--- /dev/null
+++ b/kttsd/filters/talkerchooser/kttsd_talkerchooserplugin.desktop
@@ -0,0 +1,89 @@
+[Desktop Entry]
+Name=Talker Chooser
+Name[bg]=Избор на глас
+Name[ca]=Selector de parla
+Name[cs]=Výběr hlasu
+Name[da]=Vælger af oplæser
+Name[de]=Sprecherauswahl
+Name[el]=Επιλογή εκφωνητή
+Name[es]=Selector de lectores
+Name[et]=Kõneleja valimine
+Name[fa]=انتخاب‌کنندۀ گوینده
+Name[fi]=Puhujan valitsin
+Name[fr]=Sélecteur de voix
+Name[ga]=Roghnóir Cainteora
+Name[gl]=Escolla de Locutor
+Name[hu]=Hangválasztó
+Name[is]=Talveljari
+Name[it]=Selezione dell'oratore
+Name[ja]=話者選択
+Name[ka]=მოლაპარაკის ამომრჩეველი
+Name[km]=ឧបករណ៍​ជ្រើស​អ្នក​និយាយ
+Name[mk]=Избирач на говорникот
+Name[ms]=Pemilih Penutur
+Name[nb]=Snakkervelger
+Name[nds]=Snacker-Utwahl
+Name[ne]=वक्ता चयनकर्ता
+Name[nl]=Spreker kiezen
+Name[pa]=ਬੋਲਚਾਲ ਚੋਣਕਾਰ
+Name[pl]=Wybieranie Mówców
+Name[pt]=Escolha de Orador
+Name[pt_BR]=Escolha do Talker
+Name[ru]=Диктор
+Name[sk]=Voľba hovorcu
+Name[sl]=Izbirnik govornika
+Name[sr]=Бирач говорника
+Name[sr@Latn]=Birač govornika
+Name[sv]=Urval av talare
+Name[ta]=டாக்கர் தேர்ந்தெடுப்பான்
+Name[tg]=Диктор
+Name[tr]=Konuşmacı Seçici
+Name[uk]=Вибір диктора
+Name[vi]=Trình chọn Máy nói
+Name[zh_TW]=語音選擇器
+Comment=Generic Talker Chooser Filter Plugin for KTTS
+Comment[bg]=Приставка за избор на глас за KTTS
+Comment[ca]=Connector del filtre selector genèric de parla pel KTTS
+Comment[cs]=Modul filtru výběru hlasu KTTS
+Comment[da]=Generisk vælger af oplæser for KTTS
+Comment[de]=Generischer Sprecherauswahlfilter für KTTS
+Comment[el]=Γενικό φίλτρο πρόσθετο επιλογής εκφωνητή για το KTTS
+Comment[es]=Complemento de audio para KTTSD
+Comment[et]=KTTS-i üldine kõneleja valimise filtri plugin
+Comment[eu]=KTTS-ren hizlariak hautatzeko iragazk-plugin generikoa
+Comment[fa]=وصلۀ پالایۀ انتخاب‌کنندۀ گویندۀ عمومی برای KTTS
+Comment[fi]=Yleinen puhujan valitsin suodatin liitännäinen KTTS-ohjelmalle
+Comment[fr]=Module de filtrage de sélection de voix pour KTTS
+Comment[gl]=Plugin para Escoller o Locutor para KTTS
+Comment[hu]=Általános hangkiválasztó modul a KTTS-hez
+Comment[is]=Almennt talvalsíforrit fyrir KTTS
+Comment[it]=Plugin generico per il filtro di scelta dell'oratore per KTTS
+Comment[ja]=KTTS 用汎用話者選択フィルタプラグイン
+Comment[ka]=მოლაპარაკის ამომრჩეველის ზოგადი ფილტრის მოდული KTTS-სთვის
+Comment[km]=កម្មវិធី​ជំនួយ​ឧបករណ៍​ជ្រើស​រើស​អ្នក​និយាយ​ទូទៅ​សម្រាប់ KTTS
+Comment[mk]=Филтер за KTTS за избирач на општ говорник
+Comment[ms]=Plugin Penapis Pemilih Penutur Generik bagi KTTS
+Comment[nb]=Filter-programtillegg til KTTS for snakkervalg
+Comment[nds]=KTTS-Filtermoduul för dat Utsöken vun den Snacker
+Comment[ne]=KTTS का लागि जेनेरीक वक्ता चयनकर्ता फिल्टर प्लगइन
+Comment[nl]=Generieke plugin om de spreker te kiezen voor KTTS
+Comment[pa]=KTTS ਲਈ ਸਧਾਰਨ ਬੋਲੀ ਚੋਣਕਾਰ ਫਿਲਟਰ ਪਲੱਗਿੰਨ
+Comment[pl]=Wtyczka wyboru Mówców dla KTTS
+Comment[pt]='Plugin' Genérico de Escolha de Orador para o KTTS
+Comment[pt_BR]=Plug-in de Filtro Genérico Para Escolha do Talker do KTTS
+Comment[ru]=Фильтр выбора диктора для KTTS
+Comment[sk]=Všeobecný modul filra na voľbu hovorcu v KTTS
+Comment[sl]=Filtrni vstavek KTTS za generični izbirnik govorca
+Comment[sr]=Генерички филтерски прикључак KTTS-а за бирач говорника
+Comment[sr@Latn]=Generički filterski priključak KTTS-a za birač govornika
+Comment[sv]=Insticksprogram för KTTS med generellt urvalsfilter för talare
+Comment[ta]=KTTS க்கான ஜெனரிக் பேச்சாளர் தேர்ந்தெடுப்பான அலங்கார சொருகுப்பொருள்
+Comment[tg]=Филтри интихоби диктор барои KTTS
+Comment[tr]=KTTS için Genel Konuşma Seçici Süzgeci Eklentisi
+Comment[uk]=Загальний втулок Фільтра вибору диктора для KTTS
+Comment[vi]=Trình bổ sung Lọc Chọn Máy nói Chung cho KTTS
+Comment[zh_TW]=KTTS 使用的語音選擇外掛程式
+Type=Service
+ServiceTypes=KTTSD/FilterPlugin
+X-KDE-Library=libkttsd_talkerchooserplugin
+X-KDE-Languages=en,en_US,en_GB,en_CA,es,es_mx,cy,de,fi,cs,pl
diff --git a/kttsd/filters/talkerchooser/talkerchooserconf.cpp b/kttsd/filters/talkerchooser/talkerchooserconf.cpp
new file mode 100644
index 0000000..0dbf53f
--- /dev/null
+++ b/kttsd/filters/talkerchooser/talkerchooserconf.cpp
@@ -0,0 +1,269 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic Talker Chooser Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qstring.h>
+#include <qhbox.h>
+#include <qlayout.h>
+
+// KDE includes.
+#include <klocale.h>
+#include <klineedit.h>
+#include <kdialog.h>
+#include <kdialogbase.h>
+#include <kcombobox.h>
+#include <kpushbutton.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kregexpeditorinterface.h>
+#include <ktrader.h>
+#include <kparts/componentfactory.h>
+#include <kfiledialog.h>
+
+// KTTS includes.
+
+// TalkerChooser includes.
+#include "talkerchooserconf.h"
+#include "talkerchooserconf.moc"
+
+/**
+* Constructor
+*/
+TalkerChooserConf::TalkerChooserConf( QWidget *parent, const char *name, const QStringList& /*args*/) :
+ KttsFilterConf(parent, name)
+{
+ // kdDebug() << "TalkerChooserConf::TalkerChooserConf: Running" << endl;
+
+ // Create configuration widget.
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "TalkerChooserConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new TalkerChooserConfWidget(this, "TalkerChooserConfigWidget");
+ layout->addWidget(m_widget);
+
+ // Determine if kdeutils Regular Expression Editor is installed.
+ m_reEditorInstalled = !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty();
+ m_widget->reEditorButton->setEnabled(m_reEditorInstalled);
+
+ connect(m_widget->nameLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->reLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->reEditorButton, SIGNAL(clicked()),
+ this, SLOT(slotReEditorButton_clicked()));
+ connect(m_widget->appIdLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->talkerButton, SIGNAL(clicked()),
+ this, SLOT(slotTalkerButton_clicked()));
+
+ connect(m_widget->loadButton, SIGNAL(clicked()),
+ this, SLOT(slotLoadButton_clicked()));
+ connect(m_widget->saveButton, SIGNAL(clicked()),
+ this, SLOT(slotSaveButton_clicked()));
+ connect(m_widget->clearButton, SIGNAL(clicked()),
+ this, SLOT(slotClearButton_clicked()));
+
+ // Set up defaults.
+ defaults();
+}
+
+/**
+* Destructor.
+*/
+TalkerChooserConf::~TalkerChooserConf(){
+ // kdDebug() << "TalkerChooserConf::~TalkerChooserConf: Running" << endl;
+}
+
+/**
+* This method is invoked whenever the module should read its
+* configuration (most of the times from a config file) and update the
+* user interface. This happens when the user clicks the "Reset" button in
+* the control center, to undo all of his changes and restore the currently
+* valid settings. Note that kttsmgr calls this when the plugin is
+* loaded, so it not necessary to call it in your constructor.
+* The plugin should read its configuration from the specified group
+* in the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* loading your configuration.
+*/
+void TalkerChooserConf::load(KConfig* config, const QString& configGroup){
+ // kdDebug() << "TalkerChooserConf::load: Running" << endl;
+ config->setGroup( configGroup );
+ m_widget->nameLineEdit->setText( config->readEntry( "UserFilterName", m_widget->nameLineEdit->text() ) );
+ m_widget->reLineEdit->setText(
+ config->readEntry("MatchRegExp", m_widget->reLineEdit->text()) );
+ m_widget->appIdLineEdit->setText(
+ config->readEntry("AppIDs", m_widget->appIdLineEdit->text()) );
+
+ m_talkerCode = TalkerCode(config->readEntry("TalkerCode"), false);
+ // Legacy settings.
+ QString s = config->readEntry( "LanguageCode" );
+ if (!s.isEmpty()) m_talkerCode.setFullLanguageCode(s);
+ s = config->readEntry( "SynthInName" );
+ if (!s.isEmpty()) m_talkerCode.setPlugInName(s);
+ s = config->readEntry( "Gender" );
+ if (!s.isEmpty()) m_talkerCode.setGender(s);
+ s = config->readEntry( "Volume" );
+ if (!s.isEmpty()) m_talkerCode.setVolume(s);
+ s = config->readEntry( "Rate" );
+ if (!s.isEmpty()) m_talkerCode.setRate(s);
+
+ m_widget->talkerLineEdit->setText(m_talkerCode.getTranslatedDescription());
+}
+
+/**
+* This function gets called when the user wants to save the settings in
+* the user interface, updating the config files or wherever the
+* configuration is stored. The method is called when the user clicks "Apply"
+* or "Ok". The plugin should save its configuration in the specified
+* group of the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* saving your configuration.
+*/
+void TalkerChooserConf::save(KConfig* config, const QString& configGroup){
+ // kdDebug() << "TalkerChooserConf::save: Running" << endl;
+ config->setGroup( configGroup );
+ config->writeEntry( "UserFilterName", m_widget->nameLineEdit->text() );
+ config->writeEntry( "MatchRegExp", m_widget->reLineEdit->text() );
+ config->writeEntry( "AppIDs", m_widget->appIdLineEdit->text().replace(" ", "") );
+ config->writeEntry( "TalkerCode", m_talkerCode.getTalkerCode());
+}
+
+/**
+* This function is called to set the settings in the module to sensible
+* default values. It gets called when hitting the "Default" button. The
+* default values should probably be the same as the ones the application
+* uses when started without a config file. Note that defaults should
+* be applied to the on-screen widgets; not to the config file.
+*/
+void TalkerChooserConf::defaults(){
+ // kdDebug() << "TalkerChooserConf::defaults: Running" << endl;
+ // Default name.
+ m_widget->nameLineEdit->setText( i18n("Talker Chooser") );
+ // Default regular expression is blank.
+ m_widget->reLineEdit->setText( "" );
+ // Default App ID is blank.
+ m_widget->appIdLineEdit->setText( "" );
+ // Default to using default Talker.
+ m_talkerCode = TalkerCode( QString::null, false );
+ m_widget->talkerLineEdit->setText( m_talkerCode.getTranslatedDescription() );
+}
+
+/**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+bool TalkerChooserConf::supportsMultiInstance() { return true; }
+
+/**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be TalkerCode::translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+QString TalkerChooserConf::userPlugInName()
+{
+ if (m_widget->talkerLineEdit->text().isEmpty()) return QString::null;
+ if (m_widget->appIdLineEdit->text().isEmpty() &&
+ m_widget->reLineEdit->text().isEmpty()) return QString::null;
+ QString instName = m_widget->nameLineEdit->text();
+ if (instName.isEmpty()) return QString::null;
+ return instName;
+}
+
+void TalkerChooserConf::slotReEditorButton_clicked()
+{
+ // Show Regular Expression Editor dialog if it is installed.
+ if ( !m_reEditorInstalled ) return;
+ QDialog *editorDialog =
+ KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor" );
+ if ( editorDialog )
+ {
+ // kdeutils was installed, so the dialog was found. Fetch the editor interface.
+ KRegExpEditorInterface *reEditor =
+ static_cast<KRegExpEditorInterface *>(editorDialog->qt_cast( "KRegExpEditorInterface" ) );
+ Q_ASSERT( reEditor ); // This should not fail!// now use the editor.
+ reEditor->setRegExp( m_widget->reLineEdit->text() );
+ int dlgResult = editorDialog->exec();
+ if ( dlgResult == QDialog::Accepted )
+ {
+ QString re = reEditor->regExp();
+ m_widget->reLineEdit->setText( re );
+ }
+ delete editorDialog;
+ } else return;
+}
+
+void TalkerChooserConf::slotTalkerButton_clicked()
+{
+ QString talkerCode = m_talkerCode.getTalkerCode();
+ SelectTalkerDlg dlg( m_widget, "selecttalkerdialog", i18n("Select Talker"), talkerCode, true );
+ int dlgResult = dlg.exec();
+ if ( dlgResult != KDialogBase::Accepted ) return;
+ m_talkerCode = TalkerCode( dlg.getSelectedTalkerCode(), false );
+ m_widget->talkerLineEdit->setText( m_talkerCode.getTranslatedDescription() );
+ configChanged();
+}
+
+void TalkerChooserConf::slotLoadButton_clicked()
+{
+ QString dataDir = KGlobal::dirs()->findAllResources("data", "kttsd/talkerchooser/").last();
+ QString filename = KFileDialog::getOpenFileName(
+ dataDir,
+ "*rc|Talker Chooser Config (*rc)",
+ m_widget,
+ "talkerchooser_loadfile");
+ if ( filename.isEmpty() ) return;
+ KConfig* cfg = new KConfig( filename, true, false, 0 );
+ load( cfg, "Filter" );
+ delete cfg;
+ configChanged();
+}
+
+void TalkerChooserConf::slotSaveButton_clicked()
+{
+ QString filename = KFileDialog::getSaveFileName(
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/talkerchooser/", false ),
+ "*rc|Talker Chooser Config (*rc)",
+ m_widget,
+ "talkerchooser_savefile");
+ if ( filename.isEmpty() ) return;
+ KConfig* cfg = new KConfig( filename, false, false, 0 );
+ save( cfg, "Filter" );
+ delete cfg;
+}
+
+void TalkerChooserConf::slotClearButton_clicked()
+{
+ m_widget->nameLineEdit->setText( QString::null );
+ m_widget->reLineEdit->setText( QString::null );
+ m_widget->appIdLineEdit->setText( QString::null );
+ m_talkerCode = TalkerCode( QString::null, false );
+ m_widget->talkerLineEdit->setText( m_talkerCode.getTranslatedDescription() );
+ configChanged();
+}
diff --git a/kttsd/filters/talkerchooser/talkerchooserconf.h b/kttsd/filters/talkerchooser/talkerchooserconf.h
new file mode 100644
index 0000000..d6b3959
--- /dev/null
+++ b/kttsd/filters/talkerchooser/talkerchooserconf.h
@@ -0,0 +1,134 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic Talker Chooser Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _TALKERCHOOSERCONF_H_
+#define _TALKERCHOOSERCONF_H_
+
+// Qt includes.
+#include <qwidget.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "filterconf.h"
+#include "talkercode.h"
+#include "selecttalkerdlg.h"
+
+// TalkerChooser includes.
+#include "talkerchooserconfwidget.h"
+
+class KDialogBase;
+class EditReplacementWidget;
+
+class TalkerChooserConf : public KttsFilterConf
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ TalkerChooserConf( QWidget *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor
+ */
+ virtual ~TalkerChooserConf();
+
+ /**
+ * This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. Note that KTTSMGR calls this when the plugin is
+ * loaded, so it not necessary to call it in your constructor.
+ * The plugin should read its configuration from the specified group
+ * in the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * loading your configuration.
+ *
+ * When a plugin is first added to KTTSMGR, @e load will be called with
+ * a Null @e configGroup. In this case, the plugin will not have
+ * any instance-specific parameters to load, but it may still wish
+ * to load parameters that apply to all instances of the plugin.
+ */
+ virtual void load(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok". The plugin should save its configuration in the specified
+ * group of the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * saving your configuration.
+ */
+ virtual void save(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file. Note that defaults should
+ * be applied to the on-screen widgets; not to the config file.
+ */
+ virtual void defaults();
+
+ /**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+ virtual bool supportsMultiInstance();
+
+ /**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+ virtual QString userPlugInName();
+
+ private slots:
+ void slotReEditorButton_clicked();
+ void slotTalkerButton_clicked();
+ void slotLoadButton_clicked();
+ void slotSaveButton_clicked();
+ void slotClearButton_clicked();
+
+ private:
+ // Configuration Widget.
+ TalkerChooserConfWidget* m_widget;
+ // True if kdeutils Regular Expression Editor is installed.
+ bool m_reEditorInstalled;
+ // User's chosen Talker Code.
+ TalkerCode m_talkerCode;
+};
+
+#endif //_TALKERCHOOSERCONF_H_
diff --git a/kttsd/filters/talkerchooser/talkerchooserconfwidget.ui b/kttsd/filters/talkerchooser/talkerchooserconfwidget.ui
new file mode 100644
index 0000000..3cdee2e
--- /dev/null
+++ b/kttsd/filters/talkerchooser/talkerchooserconfwidget.ui
@@ -0,0 +1,319 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>TalkerChooserConfWidget</class>
+<comment>Widget for configuring Talker Chooser Filter for KTTSD.</comment>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>TalkerChooserConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>547</width>
+ <height>240</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Configure Talker Chooser</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>nameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Name:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any name you like for this filter.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any name you like for this filter.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>applyGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Apply This Filter When</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>These settings determines when the filter is applied to text.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>reLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Te&amp;xt contains:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>reLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank, the filter applies to all text jobs of any language.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>appIdLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Application &amp;ID contains:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter a DCOP Application ID. This filter will only apply to text jobs queued by that application. You may enter more than one ID separated by commas. If blank, this filter applies to text jobs queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>reLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank, the filter applies to all text jobs of any language.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>reEditorButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to select one or more languages. This filter will be applied to text jobs of those languages.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter a DCOP Application ID. This filter will only apply to text jobs queued by that application. You may enter more than one ID separated by commas. Use &lt;b&gt;knotify&lt;/b&gt; to match all messages sent as KDE notifications. If blank, this filter applies to text jobs queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout19_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>talkerLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Talker:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>talkerLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The new Talker that will be used when the conditions above are met. The default Talker is the topmost in the Talkers tab. Click the button to choose a Talker.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>talkerLineEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="paletteForegroundColor">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The new Talker that will be used when the conditions above are met. The default Talker is the topmost in the Talkers tab. Click the button to choose a Talker.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>talkerButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to select a Talker.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>loadButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Load...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to load a Talker Chooser configuration from a file.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>saveButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Save...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to save this Talker Chooser to a file.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>clearButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Cl&amp;ear</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to clear everything.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>nameLineEdit</tabstop>
+ <tabstop>reLineEdit</tabstop>
+ <tabstop>reEditorButton</tabstop>
+ <tabstop>appIdLineEdit</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/filters/talkerchooser/talkerchooserplugin.cpp b/kttsd/filters/talkerchooser/talkerchooserplugin.cpp
new file mode 100644
index 0000000..4181f6a
--- /dev/null
+++ b/kttsd/filters/talkerchooser/talkerchooserplugin.cpp
@@ -0,0 +1,32 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so Talker Chooser Filter can be used as plug in.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "talkerchooserconf.h"
+#include "talkerchooserproc.h"
+
+typedef K_TYPELIST_2( TalkerChooserProc, TalkerChooserConf ) TalkerChooserPlugin;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_talkerchooserplugin,
+ KGenericFactory<TalkerChooserPlugin>("kttsd_talkerchooser") )
+
diff --git a/kttsd/filters/talkerchooser/talkerchooserproc.cpp b/kttsd/filters/talkerchooser/talkerchooserproc.cpp
new file mode 100644
index 0000000..628b68a
--- /dev/null
+++ b/kttsd/filters/talkerchooser/talkerchooserproc.cpp
@@ -0,0 +1,148 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic Talker Chooser Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qregexp.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kconfig.h>
+
+// KTTS includes.
+#include "talkercode.h"
+
+// Talker Chooser includes.
+#include "talkerchooserproc.h"
+#include "talkerchooserproc.moc"
+
+/**
+ * Constructor.
+ */
+TalkerChooserProc::TalkerChooserProc( QObject *parent, const char *name, const QStringList& /*args*/ ) :
+ KttsFilterProc(parent, name)
+{
+ // kdDebug() << "TalkerChooserProc::TalkerChooserProc: Running" << endl;
+}
+
+/**
+ * Destructor.
+ */
+TalkerChooserProc::~TalkerChooserProc()
+{
+ // kdDebug() << "TalkerChooserProc::~TalkerChooserProc: Running" << endl;
+}
+
+/**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+bool TalkerChooserProc::init(KConfig* config, const QString& configGroup){
+ // kdDebug() << "PlugInProc::init: Running" << endl;
+ config->setGroup( configGroup );
+ m_re = config->readEntry( "MatchRegExp" );
+ m_appIdList = config->readListEntry( "AppIDs" );
+ m_chosenTalkerCode = TalkerCode(config->readEntry("TalkerCode"), false);
+ // Legacy settings.
+ QString s = config->readEntry( "LanguageCode" );
+ if (!s.isEmpty()) m_chosenTalkerCode.setFullLanguageCode(s);
+ s = config->readEntry( "SynthInName" );
+ if (!s.isEmpty()) m_chosenTalkerCode.setPlugInName(s);
+ s = config->readEntry( "Gender" );
+ if (!s.isEmpty()) m_chosenTalkerCode.setGender(s);
+ s = config->readEntry( "Volume" );
+ if (!s.isEmpty()) m_chosenTalkerCode.setVolume(s);
+ s = config->readEntry( "Rate" );
+ if (!s.isEmpty()) m_chosenTalkerCode.setRate(s);
+ return true;
+}
+
+/**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+/*virtual*/ bool TalkerChooserProc::supportsAsync() { return false; }
+
+/**
+ * Convert input, returning output. Runs synchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+/*virtual*/ QString TalkerChooserProc::convert(const QString& inputText, TalkerCode* talkerCode,
+ const QCString& appId)
+{
+ if ( !m_re.isEmpty() )
+ {
+ int pos = inputText.find( QRegExp(m_re) );
+ if ( pos < 0 ) return inputText;
+ }
+ // If appId doesn't match, return input unmolested.
+ if ( !m_appIdList.isEmpty() )
+ {
+ // kdDebug() << "TalkerChooserProc::convert: converting " << inputText << " if appId "
+ // << appId << " matches " << m_appIdList << endl;
+ bool found = false;
+ QString appIdStr = appId;
+ for ( uint ndx=0; ndx < m_appIdList.count(); ++ndx )
+ {
+ if ( appIdStr.contains(m_appIdList[ndx]) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ {
+ // kdDebug() << "TalkerChooserProc::convert: appId not found" << endl;
+ return inputText;
+ }
+ }
+
+ // Set the talker.
+ // kdDebug() << "TalkerChooserProc::convert: setting lang " << m_languageCode <<
+ // " gender " << m_gender << " synth " << m_synth <<
+ // " volume " << m_volume << " rate " << m_rate << endl;
+ // Only override the language if user specified a language code.
+ if (!m_chosenTalkerCode.fullLanguageCode().isEmpty())
+ talkerCode->setFullLanguageCode(m_chosenTalkerCode.fullLanguageCode());
+ talkerCode->setVoice(m_chosenTalkerCode.voice());
+ talkerCode->setGender(m_chosenTalkerCode.gender());
+ talkerCode->setPlugInName(m_chosenTalkerCode.plugInName());
+ talkerCode->setVolume(m_chosenTalkerCode.volume());
+ talkerCode->setRate(m_chosenTalkerCode.rate());
+ return inputText;
+}
diff --git a/kttsd/filters/talkerchooser/talkerchooserproc.h b/kttsd/filters/talkerchooser/talkerchooserproc.h
new file mode 100644
index 0000000..07cde68
--- /dev/null
+++ b/kttsd/filters/talkerchooser/talkerchooserproc.h
@@ -0,0 +1,87 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic Talker Chooser Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _TALKERCHOOSERPROC_H_
+#define _TALKERCHOOSERPROC_H_
+
+// KTTS includes.
+#include "filterproc.h"
+#include "talkercode.h"
+
+class TalkerChooserProc : virtual public KttsFilterProc
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ */
+ TalkerChooserProc( QObject *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor.
+ */
+ virtual ~TalkerChooserProc();
+
+ /**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Convert input, returning output. Runs synchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+ virtual QString convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+private:
+
+ QString m_re;
+ QStringList m_appIdList;
+ TalkerCode m_chosenTalkerCode;
+};
+
+#endif // _TALKERCHOOSERPROC_H_
diff --git a/kttsd/filters/xhtml2ssml/Doxyfile b/kttsd/filters/xhtml2ssml/Doxyfile
new file mode 100644
index 0000000..0061358
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/Doxyfile
@@ -0,0 +1,266 @@
+# Doxyfile 1.3.7-KDevelop
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = xhtml2ssml.kdevelop
+PROJECT_NUMBER = $VERSION$
+OUTPUT_DIRECTORY =
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /home/paul/
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = /home/paul/Kdecvs/kdeaccessibility/kttsd/filters
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.mm \
+ *.C \
+ *.CC \
+ *.C++ \
+ *.II \
+ *.I++ \
+ *.H \
+ *.HH \
+ *.H++ \
+ *.CS \
+ *.PHP \
+ *.PHP3 \
+ *.M \
+ *.MM \
+ *.C \
+ *.H \
+ *.tlh \
+ *.diff \
+ *.patch \
+ *.moc \
+ *.xpm \
+ *.dox
+RECURSIVE = yes
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = yes
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE = xhtml2ssml.tag
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 1000
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/kttsd/filters/xhtml2ssml/demonstration.html b/kttsd/filters/xhtml2ssml/demonstration.html
new file mode 100644
index 0000000..89bf8a3
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/demonstration.html
@@ -0,0 +1,5 @@
+<html>
+ <body>
+ <p>Isn't it such a nice and <strong>bold</strong> day today?</p>
+ </body>
+</html>
diff --git a/kttsd/filters/xhtml2ssml/main.cpp b/kttsd/filters/xhtml2ssml/main.cpp
new file mode 100644
index 0000000..822d068
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/main.cpp
@@ -0,0 +1,22 @@
+
+#include <qapplication.h>
+#include <qfile.h>
+#include <qxml.h>
+#include <qmap.h>
+#include <iostream>
+#include "xhtml2ssml.h"
+#include "xmlelement.h"
+
+int main(int argc, char *argv[]) {
+ QApplication a(argc, argv);
+ QFile f("demonstration.html");
+ QXmlInputSource input(&f);
+ QXmlSimpleReader reader;
+ XHTMLToSSMLParser *parser = new XHTMLToSSMLParser();
+ reader.setContentHandler(parser);
+ reader.parse(input);
+ std::cout << parser->convertedText() << "\n";
+ delete parser;
+ return 0;
+}
+
diff --git a/kttsd/filters/xhtml2ssml/tagmappingrc b/kttsd/filters/xhtml2ssml/tagmappingrc
new file mode 100644
index 0000000..425af8e
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/tagmappingrc
@@ -0,0 +1,5 @@
+# This is a comment
+# and another one
+# a html 'b' or 'strong' tag is mapped to 'emphasis level="strong"'
+b:emphasis level="strong"
+strong:emphasis level="strong"
diff --git a/kttsd/filters/xhtml2ssml/xhtml2ssml.cpp b/kttsd/filters/xhtml2ssml/xhtml2ssml.cpp
new file mode 100644
index 0000000..7c77b9e
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/xhtml2ssml.cpp
@@ -0,0 +1,105 @@
+
+
+/****************************************************************************
+ XHTMLToSSMLParser class
+
+ Parses a piece of XHTML markup and converts into SSML.
+ -------------------
+ Copyright:
+ (C) 2004 by Paul Giannaros <ceruleanblaze@gmail.com>
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <qstring.h>
+#include <qdict.h>
+#include <qxml.h>
+#include <qfile.h>
+#include <iostream>
+
+#include "xmlelement.h"
+#include "xhtml2ssml.h"
+
+
+/// Document parsing begin. Init stuff here.
+bool XHTMLToSSMLParser::startDocument() {
+ /// Read the file which maps xhtml tags -> ssml tags. Look at the file for more information.
+ QFile file("tagmappingrc");
+ if(!file.open(IO_ReadOnly)) {
+ std::cerr << "Could not read config file 'tagmappingrc'. Please check that it exists and is readable.\n";
+ // Kill further parsing
+ return false;
+ }
+ QTextStream stream(&file);
+ // File parsing.
+ bool linestatus = true;
+ while(!stream.atEnd()) {
+ linestatus = readFileConfigEntry(stream.readLine());
+ // If there's some syntactical error in the file then return false.
+ if(!linestatus)
+ return false;
+ /// Maybe call processEvents() to prevent GUI blockages?
+ }
+ return true;
+}
+
+bool XHTMLToSSMLParser::startElement(const QString &, const QString &, const QString &qName, const QXmlAttributes &atts) {
+ QString attributes = "";
+ if(atts.length() > 0) {
+ const int attsLength = atts.lenght();
+ for(int i = 0; i < attsLength; ++i)
+ attributes += " " + atts.qName(i) + "=\"" + atts.value(i) + "\"";
+ }
+ QString fromelement = qName + attributes;
+ // If this element is one of the keys that was specified in the configuration file, get what it should be converted to and
+ // append to the output string.
+ QString toelement = m_xhtml2ssml[fromelement];
+ if(toelement)
+ m_output.append(XMLElement::fromQString(toelement).startTag());
+ return true;
+}
+
+bool XHTMLToSSMLParser::endElement(const QString &, const QString &, const QString &qName) {
+ QString fromelement = qName;
+ QString toelement = m_xhtml2ssml[fromelement];
+ if(toelement)
+ m_output.append(XMLElement::fromQString(toelement).endTag());
+ return true;
+}
+
+bool XHTMLToSSMLParser::characters(const QString &characters) {
+ m_output.append(characters);
+ return true;
+}
+
+
+QString XHTMLToSSMLParser::convertedText() {
+ return m_output.simplifyWhiteSpace();
+}
+
+/// Parse a line from the configuration file which maps xhtml : ssml equivalent.
+/// It makes entries in the m_xhtml2ssml map accordingly.
+/// @param line A line from a file to parse
+/// @returns true if the syntax of the line was okay and the parsing succeeded - false otherwise.
+bool XHTMLToSSMLParser::readFileConfigEntry(const QString &line) {
+ // comments
+ if(line.stripWhiteSpace().startsWith("#")) {
+ return true;
+ }
+ // break into QStringList
+ // the second parameter to split is the string, with all space simplified and all space around the : removed, i.e
+ // "something : somethingelse" -> "something:somethingelse"
+ QStringList keyvalue = QStringList::split(":", line.simplifyWhiteSpace().replace(" :", ":").replace(": ", ":"));
+ if(keyvalue.count() != 2)
+ return false;
+ m_xhtml2ssml[keyvalue[0]] = keyvalue[1];
+ return true;
+}
diff --git a/kttsd/filters/xhtml2ssml/xhtml2ssml.h b/kttsd/filters/xhtml2ssml/xhtml2ssml.h
new file mode 100644
index 0000000..7271dc0
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/xhtml2ssml.h
@@ -0,0 +1,61 @@
+
+/****************************************************************************
+ XHTMLToSSMLParser class
+
+ Parses a piece of XHTML markup and converts into SSML.
+ -------------------
+ Copyright:
+ (C) 2004 by Paul Giannaros <ceruleanblaze@gmail.com>
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef _XHTML2SSML_H_
+#define _XHTML2SSML_H_
+
+#include <qxml.h>
+#include <qmap.h>
+
+typedef QMap<QString, QString> QStringMap;
+class QString;
+
+class XHTMLToSSMLParser : public QXmlDefaultHandler {
+
+public:
+ /// No need to reimplement constructor..
+ /// The document parsing starts
+ bool startDocument();
+ /// start of an element encountered (<element foo="bar">)
+ bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts);
+ /// end of an element encountered (</element>)
+ bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName);
+ /// text encountered (blah bah blah)
+ bool characters(const QString &);
+
+ /// Get the output text that was generated during the parsing.
+ /// @returns The converted text.
+ QString convertedText();
+
+ /// Parse a line from the configuration file which maps xhtml : ssml equivalent.
+ /// It makes entries in the m_xhtml2ssml map accordingly.
+ /// @param line A line from a file to parse
+ /// @returns true if the syntax of the line was okay and the parsing succeeded - false otherwise.
+ bool readFileConfigEntry(const QString &line);
+
+private:
+ /// Dict of xhtml tags -> ssml tags
+ QStringMap m_xhtml2ssml;
+ /// The output of the conversion
+ QString m_output;
+};
+
+#endif
diff --git a/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevelop b/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevelop
new file mode 100644
index 0000000..691735f
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevelop
@@ -0,0 +1,112 @@
+<?xml version = '1.0'?>
+<kdevelop>
+ <general>
+ <author>Paul Giannaros</author>
+ <email>ceruleanblaze@gmail.com</email>
+ <version>$VERSION$</version>
+ <projectmanagement>KDevTrollProject</projectmanagement>
+ <primarylanguage>C++</primarylanguage>
+ <keywords>
+ <keyword>Qt</keyword>
+ </keywords>
+ </general>
+ <kdevfileview>
+ <groups>
+ <group pattern="*.cpp;*.cxx;*.h" name="Sources" />
+ <group pattern="*.ui" name="User Interface" />
+ <group pattern="*.png" name="Icons" />
+ <group pattern="*" name="Others" />
+ <hidenonprojectfiles>false</hidenonprojectfiles>
+ <hidenonlocation>false</hidenonlocation>
+ </groups>
+ <tree>
+ <hidepatterns>*.o,*.lo,CVS</hidepatterns>
+ <hidenonprojectfiles>false</hidenonprojectfiles>
+ </tree>
+ </kdevfileview>
+ <kdevdoctreeview>
+ <ignoretocs>
+ <toc>bash</toc>
+ <toc>bash_bugs</toc>
+ <toc>clanlib</toc>
+ <toc>w3c-dom-level2-html</toc>
+ <toc>fortran_bugs_gcc</toc>
+ <toc>gnome1</toc>
+ <toc>gnustep</toc>
+ <toc>gtk</toc>
+ <toc>gtk_bugs</toc>
+ <toc>haskell</toc>
+ <toc>haskell_bugs_ghc</toc>
+ <toc>java_bugs_gcc</toc>
+ <toc>java_bugs_sun</toc>
+ <toc>kde2book</toc>
+ <toc>opengl</toc>
+ <toc>pascal_bugs_fp</toc>
+ <toc>php</toc>
+ <toc>php_bugs</toc>
+ <toc>perl</toc>
+ <toc>perl_bugs</toc>
+ <toc>python</toc>
+ <toc>python_bugs</toc>
+ <toc>qt-kdev3</toc>
+ <toc>ruby</toc>
+ <toc>ruby_bugs</toc>
+ <toc>sdl</toc>
+ <toc>stl</toc>
+ <toc>w3c-svg</toc>
+ <toc>sw</toc>
+ <toc>w3c-uaag10</toc>
+ <toc>wxwidgets_bugs</toc>
+ </ignoretocs>
+ <ignoredoxygen>
+ <toc>KDE Libraries (Doxygen)</toc>
+ </ignoredoxygen>
+ </kdevdoctreeview>
+ <kdevdebugger>
+ <general>
+ <dbgshell/>
+ </general>
+ </kdevdebugger>
+ <kdevfilecreate>
+ <useglobaltypes>
+ <type ext="ui" />
+ <type ext="cpp" />
+ <type ext="h" />
+ </useglobaltypes>
+ </kdevfilecreate>
+ <kdevtrollproject>
+ <general>
+ <activedir></activedir>
+ </general>
+ <run>
+ <directoryradio>executable</directoryradio>
+ </run>
+ </kdevtrollproject>
+ <kdevcppsupport>
+ <references>
+ <pcs>kdeincludedb</pcs>
+ <pcs>qtincludedb</pcs>
+ <pcs>qtincludesdb</pcs>
+ <pcs>kgmailtoincludedb</pcs>
+ </references>
+ <codecompletion>
+ <includeGlobalFunctions>true</includeGlobalFunctions>
+ <includeTypes>true</includeTypes>
+ <includeEnums>true</includeEnums>
+ <includeTypedefs>false</includeTypedefs>
+ <automaticCodeCompletion>true</automaticCodeCompletion>
+ <automaticArgumentsHint>true</automaticArgumentsHint>
+ <automaticHeaderCompletion>true</automaticHeaderCompletion>
+ <codeCompletionDelay>250</codeCompletionDelay>
+ <argumentsHintDelay>400</argumentsHintDelay>
+ <headerCompletionDelay>250</headerCompletionDelay>
+ </codecompletion>
+ </kdevcppsupport>
+ <kdevcvsservice>
+ <recursivewhenupdate>true</recursivewhenupdate>
+ <prunedirswhenupdate>true</prunedirswhenupdate>
+ <createdirswhenupdate>true</createdirswhenupdate>
+ <recursivewhencommitremove>true</recursivewhencommitremove>
+ <revertoptions>-C</revertoptions>
+ </kdevcvsservice>
+</kdevelop>
diff --git a/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevelop.pcs b/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevelop.pcs
new file mode 100644
index 0000000..4cdb884
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevelop.pcs
Binary files differ
diff --git a/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevses b/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevses
new file mode 100644
index 0000000..7128bc6
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/xhtml2ssml.kdevses
@@ -0,0 +1,38 @@
+<?xml version = '1.0' encoding = 'UTF-8'?>
+<!DOCTYPE KDevPrjSession>
+<KDevPrjSession>
+ <DocsAndViews NumberOfDocuments="5" >
+ <Doc0 NumberOfViews="1" URL="file:/home/paul/Kdecvs/kdeaccessibility/kttsd/filters/xhtml2ssml.cpp" >
+ <View0 line="63" Type="Source" />
+ </Doc0>
+ <Doc1 NumberOfViews="1" URL="file:/home/paul/Kdecvs/kdeaccessibility/kttsd/filters/xhtml2ssml.h" >
+ <View0 line="21" Type="Source" />
+ </Doc1>
+ <Doc2 NumberOfViews="1" URL="file:/home/paul/Kdecvs/kdeaccessibility/kttsd/filters/main.cpp" >
+ <View0 line="17" Type="Source" />
+ </Doc2>
+ <Doc3 NumberOfViews="1" URL="file:/home/paul/Kdecvs/kdeaccessibility/kttsd/filters/xmlelement.cpp" >
+ <View0 line="72" Type="Source" />
+ </Doc3>
+ <Doc4 NumberOfViews="1" URL="file:/home/paul/Kdecvs/kdeaccessibility/kttsd/filters/xmlelement.h" >
+ <View0 line="75" Type="Source" />
+ </Doc4>
+ </DocsAndViews>
+ <pluginList>
+ <kdevbookmarks>
+ <bookmarks/>
+ </kdevbookmarks>
+ <kdevsubversion>
+ <subversion recurseresolve="1" recurserelocate="1" recursemerge="1" recursecommit="1" base="" recursepropget="1" recurseswitch="1" recurseupdate="1" recursepropset="1" recursediff="1" recurserevert="1" forcemove="1" recursecheckout="1" forceremove="1" recurseadd="1" recurseproplist="1" forcemerge="1" />
+ </kdevsubversion>
+ <kdevvalgrind>
+ <executable path="" params="" />
+ <valgrind path="" params="" />
+ <calltree path="" params="" />
+ <kcachegrind path="" />
+ </kdevvalgrind>
+ <kdevdebugger>
+ <breakpointList/>
+ </kdevdebugger>
+ </pluginList>
+</KDevPrjSession>
diff --git a/kttsd/filters/xhtml2ssml/xhtml2ssml.pro b/kttsd/filters/xhtml2ssml/xhtml2ssml.pro
new file mode 100644
index 0000000..a9b5a4a
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/xhtml2ssml.pro
@@ -0,0 +1,10 @@
+######################################################################
+# Automatically generated by qmake (1.07a) Tue Dec 21 21:18:47 2004
+######################################################################
+
+TEMPLATE = app
+INCLUDEPATH += .
+
+# Input
+HEADERS += xhtml2ssml.h xmlelement.h
+SOURCES += main.cpp xhtml2ssml.cpp xmlelement.cpp
diff --git a/kttsd/filters/xhtml2ssml/xmlelement.cpp b/kttsd/filters/xhtml2ssml/xmlelement.cpp
new file mode 100644
index 0000000..53fa4f6
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/xmlelement.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+ XMLElement class
+
+ Representation of an XML element with methods for getting/setting
+ attributes and generating "opening" and "closing" tags.
+ -------------------
+ Copyright:
+ (C) 2004 by Paul Giannaros <ceruleanblaze@gmail.com>
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include "xmlelement.h"
+#include <qstringlist.h>
+#include <iostream>
+
+/// Constructors
+XMLElement::XMLElement() {
+ m_name = "";
+ m_attrmapper = AttributeToValueMap();
+}
+XMLElement::XMLElement(const QString &name) {
+ m_name = name;
+ m_attrmapper = AttributeToValueMap();
+}
+/// Destructor
+XMLElement::~XMLElement() {
+ return;
+}
+
+/// Copy constructor
+XMLElement::XMLElement(const XMLElement &element) {
+ m_attrmapper = element.m_attrmapper;
+ m_name = element.m_name;
+}
+
+/// Assignement operator
+XMLElement XMLElement::operator=(const XMLElement &element) {
+ m_attrmapper = element.m_attrmapper;
+ m_name = element.m_name;
+ return *this;
+}
+
+QString XMLElement::name() {
+ return m_name;
+}
+QString XMLElement::startTag() {
+ QString output = "<" + m_name + " ";
+ for(AttributeToValueMap::Iterator it = m_attrmapper.begin(); it != m_attrmapper.end(); ++it) {
+ output.append(it.key() + "=\"" + it.data() + "\" ");
+ }
+ output = output.left(output.length() - 1);
+ // Get rid of the space at the end and then append a '>'
+ output.append(">");
+ return output;
+}
+
+QString XMLElement::endTag() {
+ return "</" + m_name + ">";
+}
+
+void XMLElement::setAttribute(const QString &attr, const QString &value) {
+ m_attrmapper[attr] = value;
+}
+QString XMLElement::attribute(const QString &attr) {
+ return m_attrmapper[attr];
+}
+
+QString XMLElement::toQString() {
+ QString tag = startTag();
+ return tag.left(tag.length() - 1).right(tag.length() - 2);
+}
+
+XMLElement XMLElement::fromQString(const QString &str) {
+ QStringList sections = QStringList::split(" ", str);
+ QString tagname = sections[0];
+ XMLElement e(tagname.latin1());
+
+ sections.pop_front();
+ // Loop over the remaining strings which are attributes="values"
+ if(sections.count()) {
+ const int sectionsCount = sections.count();
+ for(int i = 0; i < sectionsCount; ++i) {
+ QStringList list = QStringList::split("=", sections[i]);
+ if(list.count() != 2) {
+ std::cerr << "XMLElement::fromQString: Cannot convert list: " << list.join("|") << ". `" << str << "' is not in valid format.\n";
+ return XMLElement(" ");
+ }
+ e.setAttribute(list[0], list[1].left(list[1].length() - 1).right(list[1].length() -2));
+ }
+ }
+ return e;
+}
+
diff --git a/kttsd/filters/xhtml2ssml/xmlelement.h b/kttsd/filters/xhtml2ssml/xmlelement.h
new file mode 100644
index 0000000..c78cd6f
--- /dev/null
+++ b/kttsd/filters/xhtml2ssml/xmlelement.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+ XMLElement class
+
+ Representation of an XML element with methods for getting/setting
+ attributes and generating "opening" and "closing" tags.
+ -------------------
+ Copyright:
+ (C) 2004 by Paul Giannaros <ceruleanblaze@gmail.com>
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef XMLELEMENT_H
+#define XMLELEMENT_H
+
+#include <qmap.h>
+
+class QString;
+
+typedef QMap<QString, QString> AttributeToValueMap;
+
+class XMLElement {
+public:
+ XMLElement();
+ XMLElement(const QString &name);
+ ~XMLElement();
+
+ /// Copy constructor
+ XMLElement(const XMLElement &);
+
+ /// Assignment operator
+ XMLElement operator=(const XMLElement &element);
+
+ /// Get the name of the tag (the text between the greater than and less than symbols).
+ /// @returns the name of the tag.
+ QString name();
+
+ /// set the name of the tag.
+ /// @param name the new name of the tag.
+ void setName(const QString &name);
+
+ /// Get a textual representation of the starting of the tag with all attributes and their values set out.
+ /// @verbatim
+ /// XMLElement element("elem");
+ /// element.addAttribute("foo", "bar");
+ /// element.startTag(); <- <elem foo="bar">
+ /// @endverbatim
+ /// @returns A textual representation of the start of the element.
+ QString startTag();
+
+ /// Get a textual representation of the closed tag that XMLElement represents.
+ /// @returns A textual representation of the closed tag represented by the XMLElement.
+ QString endTag();
+
+ /// Create an attribute and set its value.
+ /// @param attr The attribute.
+ /// @param value The value of the attribute.
+ void setAttribute(const QString &attr, const QString &value);
+
+ /// Get the value of an attribute.
+ /// @param attr The attribute.
+ /// @returns The value of @param attr
+ QString attribute(const QString &attr);
+
+ /// Convert to a QString.
+ /// Had issues with QMap and custom classes. For now you can just convert to/from QString and use
+ /// That as the key/value pair.
+ /// @returns A QString representation of the XMLAttribute.
+ QString toQString();
+
+ /// Create an XMLElement from a QString.
+ /// @param str The QString to convert from. Must be of the following syntax- "foo name=\"bar\""
+ static XMLElement fromQString(const QString &str);
+
+private:
+ /// The name of the tag.
+ QString m_name;
+ /// Attribute : value mappings.
+ AttributeToValueMap m_attrmapper;
+};
+
+#endif
diff --git a/kttsd/filters/xmltransformer/Makefile.am b/kttsd/filters/xmltransformer/Makefile.am
new file mode 100644
index 0000000..93577e5
--- /dev/null
+++ b/kttsd/filters/xmltransformer/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_xmltransformerplugin.la
+
+libkttsd_xmltransformerplugin_la_SOURCES = \
+ xmltransformerconfwidget.ui \
+ xmltransformerconf.cpp \
+ xmltransformerproc.cpp \
+ xmltransformerplugin.cpp
+libkttsd_xmltransformerplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_xmltransformerplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_xmltransformerplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+# Install data files.
+xmltransformerdatadir = $(kde_datadir)/kttsd/xmltransformer/
+xmltransformerdata_DATA = xhtml2ssml.xsl xhtml2ssml_simple.xsl
+
+noinst_HEADERS = xmltransformerconfwidget.h
diff --git a/kttsd/filters/xmltransformer/kttsd_xmltransformerplugin.desktop b/kttsd/filters/xmltransformer/kttsd_xmltransformerplugin.desktop
new file mode 100644
index 0000000..6935088
--- /dev/null
+++ b/kttsd/filters/xmltransformer/kttsd_xmltransformerplugin.desktop
@@ -0,0 +1,88 @@
+[Desktop Entry]
+Name=XML Transformer
+Name[bg]=Трансформиране на XML
+Name[bs]=XML transformacije
+Name[ca]=Transformador XML
+Name[cs]=XML transformace
+Name[da]=XML Transformatør
+Name[de]=XML-Umformer
+Name[el]=XML μεταμορφωτής
+Name[es]=Transformador XML
+Name[et]=XML-i teisendus
+Name[fa]=تبدیل‌کنندۀ XML
+Name[fi]=XML-muunnin
+Name[fr]=Transformation XML
+Name[ga]=Trasfhoirmeoir XML
+Name[gl]=Transformador XML
+Name[hu]=XML-átalakító
+Name[is]=XML ummyndari
+Name[it]=Trasformatore XML
+Name[ja]=XML 変換
+Name[ka]=XML გარდამქმნელი
+Name[km]= កម្មវិធី​ប្លែង​ XML
+Name[mk]=XML-трансформирач
+Name[ms]=Transformer XML
+Name[nds]=XML-Ümwanneln
+Name[ne]=XML रुपान्तरणकर्ता
+Name[nl]=XML-omvormer
+Name[pa]=XML ਤਬਦੀਲੀਕਾਰ
+Name[pl]=Transformacja XML
+Name[pt]=Transformação de XML
+Name[pt_BR]=Transformador XML
+Name[ru]=Преобразователь XML
+Name[sk]=Transformácia XML
+Name[sl]=Pretvornik XML
+Name[sr]=XML трансформатор
+Name[sr@Latn]=XML transformator
+Name[sv]=XML-transformering
+Name[tg]=Тағйирдиҳии XML
+Name[tr]=XML Dönüştürücü
+Name[uk]=Перетворення XML
+Name[vi]=Trình chuyển đổi XML
+Name[zh_TW]=XML 轉換器
+Comment=Generic XML Tranformation Filter Plugin for KTTS
+Comment[bg]=Приставка филтър за трансформиране на XML за KTTS
+Comment[ca]=Connector del filtre genèric del transformador XML pel KTTS
+Comment[cs]=Modul filtru obecné XML transformace KTTS
+Comment[da]=Generisk XML Tranformationsfilter-plugin for KTTS
+Comment[de]=Generisches XML-Umformungs-Filtermodul für KTTS
+Comment[el]=Γενικό φίλτρο πρόσθετο XML μεταμόρφωσης για το KTTS
+Comment[es]=Complemento de Audio para KTTSD
+Comment[et]=KTTS-i üldine XML-i teisenduse filtri plugin
+Comment[eu]=KTTS-ren XML transformazioen iragazki-plugin generikoa
+Comment[fa]=وصلۀ پالایۀ انتقال XML عمومی برای KTTS
+Comment[fi]=Yleinen XML-muuntimen suodatin liitännäinen KTTS-ohjelmalle
+Comment[fr]=Module de filtrage de transformation XML générique pour KTTS
+Comment[gl]=Plugin de Transformación de XML para KTTS
+Comment[hu]=Általános XML-átalakító modul a KTTS-hez
+Comment[is]=Almennt XML ummynda íforrit fyrir KTTS
+Comment[it]=Plugin generico per il filtro di trasformazione XML per KTTS
+Comment[ja]=KTTS 用汎用 XML 変換フィルタプラグイン
+Comment[ka]=ზოგადი XML გარდამქმნელის ფილტრის მოდული KTTS-სთვის
+Comment[km]=កម្មវិធី​ជំនួស​តម្រង​ការ​ប្លែង​ XML ទូទៅ​សម្រាប់ KTTS
+Comment[mk]=Филтер за KTTS за трансформација на општ XML
+Comment[ms]=Plugin Penapis Transformasi XML Generik bagi KTTS
+Comment[nb]=Filter-programtillegg til KTTS for alminnelig XML-transformasjon
+Comment[nds]=KTTS-Filtermoduul för dat Ümwanneln vun XML
+Comment[ne]=KTTS का लागि जेनेरीक XML रुपान्तरण फिल्टर प्लगइन
+Comment[nl]=Generieke filterplugin voor XML-omvorming voor KTTS
+Comment[pa]=KTTS ਲਈ XML ਸੰਚਾਰ ਫਿਲਟਰ
+Comment[pl]=Wtyczka transformacji XML dla KTTS
+Comment[pt]='Plugin' Genérico de Transformação de XML para o KTTS
+Comment[pt_BR]=Plug-in de Filtro Genérico de Transformação XML: para o KTTSD
+Comment[ru]=Фильтр XML для KTTS
+Comment[sk]=Všeobecný modul filtra pre transformáciu XML v KTTS
+Comment[sl]=Filtrni vstavek KTTS za generično preoblikovanje XML
+Comment[sr]=Генерички филтерски прикључак KTTS-а за трансформацију XML-а
+Comment[sr@Latn]=Generički filterski priključak KTTS-a za transformaciju XML-a
+Comment[sv]=Insticksprogram för KTTS med generellt XML-transformeringsfilter
+Comment[ta]=KTTSக்கான ஜெனரிக் XML மாற்று அலங்கார சொருகுப்பொருள்
+Comment[tg]=Филтри XMLбарои KTTS
+Comment[tr]=KTTS için genel XML Dönüştürücü Süzgeci Eklentisi
+Comment[uk]=Втулок загального фільтра перетворення XML для KTTS
+Comment[vi]=Trình bổ sung Lọc Chuyển đổi XML Chung cho KTTS
+Comment[zh_TW]=KTTS 使用的一般 XML 轉換外掛程式
+Type=Service
+ServiceTypes=KTTSD/FilterPlugin
+X-KDE-Library=libkttsd_xmltransformerplugin
+X-KDE-Languages=en,en_US,en_GB,en_CA,es,es_mx,cy,de,fi,cs,pl
diff --git a/kttsd/filters/xmltransformer/xhtml2ssml.xsl b/kttsd/filters/xmltransformer/xhtml2ssml.xsl
new file mode 100644
index 0000000..5c7ca33
--- /dev/null
+++ b/kttsd/filters/xmltransformer/xhtml2ssml.xsl
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ***********************************************************************
+ Stylesheet for transforming XHTML into SSML markup.
+ ============
+ Copyright : (C) 2005 by Gary Cramblitt
+ ============
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ *************************************************************************** -->
+
+<!-- ***********************************************************************
+ The rendering is roughly based on the stylesheet from Appendix A of the
+ CSS2 specification, http://www.w3.org/TR/REC-CSS2/sample.html
+
+ @media speech {
+ H1, H2, H3,
+ H4, H5, H6 { voice-family: paul, male; stress: 20; richness: 90 }
+ H1 { pitch: x-low; pitch-range: 90 }
+ H2 { pitch: x-low; pitch-range: 80 }
+ H3 { pitch: low; pitch-range: 70 }
+ H4 { pitch: medium; pitch-range: 60 }
+ H5 { pitch: medium; pitch-range: 50 }
+ H6 { pitch: medium; pitch-range: 40 }
+ LI, DT, DD { pitch: medium; richness: 60 }
+ DT { stress: 80 }
+ PRE, CODE, TT { pitch: medium; pitch-range: 0; stress: 0; richness: 80 }
+ EM { pitch: medium; pitch-range: 60; stress: 60; richness: 50 }
+ STRONG { pitch: medium; pitch-range: 60; stress: 90; richness: 90 }
+ DFN { pitch: high; pitch-range: 60; stress: 60 }
+ S, STRIKE { richness: 0 }
+ I { pitch: medium; pitch-range: 60; stress: 60; richness: 50 }
+ B { pitch: medium; pitch-range: 60; stress: 90; richness: 90 }
+ U { richness: 0 }
+ A:link { voice-family: harry, male }
+ A:visited { voice-family: betty, female }
+ A:active { voice-family: betty, female; pitch-range: 80; pitch: x-high }
+}
+
+As SSML does not seem to offer an equivalent for "stress" and "richness".
+They are mapped to rate and volume respectively.
+
+ H1 { male; pitch: x-low; range: x-high; rate: slow; volume: x-loud}
+ H2 { male; pitch: x-low; range: high; rate: slow; volume: x-loud }
+ H3 { male; pitch: low; range: high; rate: slow; volume: x-loud }
+ H4 { male; pitch: medium; range: medium; rate: slow; volume: x-loud }
+ H5 { male; pitch: medium; range: low; rate: slow; volume: x-loud }
+ H6 { male; pitch: medium; range: x-low; rate: slow; volume: x-loud }
+ LI, DD { pitch: medium; }
+ DT { pitch: medium; rate: x-fast }
+ PRE, CODE, TT { pitch: medium; range: x-low; rate: slow; volume: loud }
+ EM { pitch: medium; range: medium; rate: medium; volume: loud }
+ STRONG { pitch: medium; range: medium; rate: x-fast; volume: x-loud }
+ DFN { pitch: high; range: medium; rate: medium }
+ S, STRIKE { volume: x-soft }
+ I { pitch: high; range: medium; rate: fast; volume: medium }
+ B { pitch: high; range: medium; rate: x-fast; volume: x-loud }
+ U { volume: medium }
+ A { female }
+
+ *********************************************************************** -->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="xml" indent="no"/>
+
+<!-- root -->
+<xsl:template match="/">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- html -->
+<!-- local-name() must be used in order to ignore namespaces. -->
+<xsl:template match="*[local-name()='html' or local-name()='HTML']">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- Ignore header, speak the body of xhtml document. -->
+<xsl:template match="*[local-name()='head' or local-name()='HEAD']"/>
+<xsl:template match="*[local-name()='body' or local-name()='BODY']">
+ <xsl:element name="speak">
+ <xsl:copy-of select="/html/@lang"/>
+ <xsl:copy-of select="/HTML/@lang"/>
+ <xsl:apply-templates/>
+ </xsl:element>
+</xsl:template>
+
+<!-- Paragraph -->
+<xsl:template match="*[local-name()='p' or local-name()='P']">
+ <p><xsl:apply-templates/></p>
+</xsl:template>
+
+<!-- H1 { pitch: x-low; range: x-high; rate: slow; volume: x-loud } -->
+<xsl:template match="*[local-name()='h1' or local-name()='H1']">
+ <voice gender="male"><prosody pitch="x-low" range="x-high" rate="slow" volume="x-loud">
+ <xsl:apply-templates/>
+ </prosody></voice>
+</xsl:template>
+
+<!-- H2 { male; pitch: x-low; range: high; rate: slow; volume: x-loud } -->
+<xsl:template match="*[local-name()='h2' or local-name()='H2']">
+ <voice gender="male"><prosody pitch="x-low" range="high" rate="slow" volume="x-loud">
+ <xsl:apply-templates/>
+ </prosody></voice>
+</xsl:template>
+
+<!-- H3 { male; pitch: low; range: high; rate: slow; volume: x-loud } -->
+<xsl:template match="*[local-name()='h3' or local-name()='H3']">
+ <voice gender="male"><prosody pitch="low" range="high" rate="slow" volume="x-loud">
+ <xsl:apply-templates/>
+ </prosody></voice>
+</xsl:template>
+
+<!-- H4 { male; pitch: medium; range: medium; rate: slow; volume: x-loud } -->
+<xsl:template match="*[local-name()='h4' or local-name()='H4']">
+ <voice gender="male"><prosody pitch="medium" range="medium" rate="slow" volume="x-loud">
+ <xsl:apply-templates/>
+ </prosody></voice>
+</xsl:template>
+
+<!-- H5 { male; pitch: medium; range: low; rate: slow; volume: x-loud } -->
+<xsl:template match="*[local-name()='h5' or local-name()='H5']">
+ <voice gender="male"><prosody pitch="low" range="low" rate="slow" volume="x-loud">
+ <xsl:apply-templates/>
+ </prosody></voice>
+</xsl:template>
+
+<!-- H6 { male; pitch: medium; range: x-low; rate: slow; volume: x-loud } -->
+<xsl:template match="*[local-name()='h6' or local-name()='H6']">
+ <voice gender="male"><prosody pitch="medium" range="x-low" rate="slow" volume="x-loud">
+ <xsl:apply-templates/>
+ </prosody></voice>
+</xsl:template>
+
+<!-- LI, DD { pitch: medium; } -->
+<xsl:template match="*[local-name()='li' or local-name()='LI']">
+ <prosody pitch="medium">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+<xsl:template match="*[local-name()='dd' or local-name()='DD']">
+ <prosody pitch="medium">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- DT { pitch: medium; rate: x-fast } -->
+<xsl:template match="*[local-name()='dt' or local-name()='DT']">
+ <prosody pitch="medium" rate="x-fast">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- PRE, CODE, TT { pitch: medium; range: x-low; rate: slow; volume: loud } -->
+<xsl:template match="*[local-name()='pre' or local-name()='PRE']">
+ <prosody pitch="medium" range="x-low" rate="slow" volume="loud">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+<xsl:template match="*[local-name()='code' or local-name()='CODE']">
+ <prosody pitch="medium" range="x-low" rate="slow" volume="loud">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+<xsl:template match="*[local-name()='tt' or local-name()='TT']">
+ <prosody pitch="medium" range="x-low" rate="slow" volume="loud">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- EM { pitch: medium; range: medium; rate: medium; volume: loud } -->
+<xsl:template match="*[local-name()='em' or local-name()='EM']">
+ <prosody pitch="medium" range="medium" rate="medium" volume="loud">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- STRONG { pitch: medium; range: medium; rate: x-fast; volume: x-loud } -->
+<xsl:template match="*[local-name()='strong' or local-name()='STRONG']">
+ <prosody pitch="medium" range="medium" rate="x-fast" volume="x-loud">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- DFN { pitch: high; range: medium; rate: medium } -->
+<xsl:template match="*[local-name()='dfn' or local-name()='DFN']">
+ <prosody pitch="high" range="medium" rate="medium">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- S, STRIKE { volume: x-soft } -->
+<xsl:template match="*[local-name()='s' or local-name()='S']">
+ <prosody volume="x-soft">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+<xsl:template match="*[local-name()='strike' or local-name()='STRIKE']">
+ <prosody volume="x-soft">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- I { pitch: high; range: medium; rate: fast; volume: medium } -->
+<xsl:template match="*[local-name()='i' or local-name()='I']">
+ <prosody pitch="high" range="medium" rate="fast" volume="medium">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- B { pitch: high; range: medium; rate: x-fast; volume: x-loud } -->
+<xsl:template match="*[local-name()='b' or local-name()='B']">
+ <prosody pitch="high" range="medium" rate="x-fast" volume="x-loud">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- U { volume: medium } -->
+<xsl:template match="*[local-name()='u' or local-name()='U']">
+ <prosody pitch="medium">
+ <xsl:apply-templates/>
+ </prosody>
+</xsl:template>
+
+<!-- A { female } -->
+<xsl:template match="*[local-name()='a' or local-name()='A']">
+ <voice gender="female">
+ <xsl:apply-templates/>
+ </voice>
+</xsl:template>
+
+<!-- HREF attribute -->
+<xsl:template match="@href">
+ <prosody volume="soft">Address</prosody>
+ <prosody rate="x-fast">
+ <xsl:value-of select="."/>
+ </prosody>
+</xsl:template>
+
+<!-- Ignore scripts. -->
+<xsl:template match="*[local-name()='script' or local-name()='SCRIPT']"/>
+
+<!-- Ignore styles. -->
+<xsl:template match="*[local-name()='style' or local-name()='STYLE']"/>
+
+</xsl:stylesheet>
diff --git a/kttsd/filters/xmltransformer/xhtml2ssml_simple.xsl b/kttsd/filters/xmltransformer/xhtml2ssml_simple.xsl
new file mode 100644
index 0000000..2c1f3be
--- /dev/null
+++ b/kttsd/filters/xmltransformer/xhtml2ssml_simple.xsl
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ***********************************************************************
+ Stylesheet for transforming XHTML into SSML markup.
+ ============
+ Copyright : (C) 2005 by Gary Cramblitt
+ ============
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ *************************************************************************** -->
+
+<!-- ***********************************************************************
+ The rendering takes a minimalist approach, mapping <b>, <em>, <i>
+ etc. to louder voices. Everything else is pretty much mapped to just
+ paragraph and sentence tags. Hyperlink addresses are spoken fast.
+ *********************************************************************** -->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="xml" indent="no"/>
+
+<!-- root -->
+<xsl:template match="/">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- html -->
+<!-- local-name() must be used in order to ignore namespaces. -->
+<xsl:template match="*[local-name()='html' or local-name()='HTML']">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- Ignore header, speak the body of xhtml document. -->
+<xsl:template match="*[local-name()='head' or local-name()='HEAD']"/>
+<xsl:template match="*[local-name()='body' or local-name()='BODY']">
+ <xsl:element name="speak">
+ <xsl:copy-of select="/html/@lang"/>
+ <xsl:copy-of select="/HTML/@lang"/>
+ <xsl:apply-templates/>
+ </xsl:element>
+</xsl:template>
+
+<!-- Paragraph -->
+<xsl:template match="*[local-name()='p' or local-name()='P']">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- H1, H2, H3, H4, H5, H6: ignore tag, speak content as sentence. -->
+<xsl:template match="*[contains('h1|h2|h3|h4|h5|h6|H1|H2|H3|H4|H5|H6|',concat(local-name(),'|'))]">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- DFN, LI, DD, DT: ignore tag, speak content. -->
+<xsl:template match="*[contains('dfn|li|dd|dt|DFN|LI|DD|DT|',concat(local-name(),'|'))]">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- PRE, CODE, TT; ignore tag, speak content. -->
+<xsl:template match="*[contains('pre|code|tt|PRE|CODE|TT|',concat(local-name(),'|'))]">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- EM, STRONG, I, B, S, STRIKE, U: speak emphasized. -->
+<xsl:template match="*[contains('em|strong|i|b|s|strike|EM|STRONG|I|B|S|STRIKE|',concat(local-name(),'|'))]">
+ <emphasis level="strong">
+ <xsl:apply-templates/>
+ </emphasis>
+</xsl:template>
+
+<!-- A: speak hyperlink emphasized, address fast. -->
+<xsl:template match="*[local-name()='a' or local-name()='A']">
+ <xsl:if test="@href">
+ <emphasis level="moderate">
+ <xsl:apply-templates/>
+ </emphasis>
+ <prosody rate="fast" volume="soft">
+ <xsl:value-of select="'Link to. '"/>
+ <xsl:value-of select="@href"/>
+ </prosody>
+ </xsl:if>
+</xsl:template>
+
+<!-- Ignore scripts. -->
+<xsl:template match="*[local-name()='script' or local-name()='SCRIPT']"/>
+
+<!-- Ignore styles. -->
+<xsl:template match="*[local-name()='style' or local-name()='STYLE']"/>
+
+</xsl:stylesheet>
diff --git a/kttsd/filters/xmltransformer/xmltransformerconf.cpp b/kttsd/filters/xmltransformer/xmltransformerconf.cpp
new file mode 100644
index 0000000..76cfd70
--- /dev/null
+++ b/kttsd/filters/xmltransformer/xmltransformerconf.cpp
@@ -0,0 +1,182 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic XML Transformation Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qstring.h>
+#include <qlayout.h>
+
+// KDE includes.
+#include <klocale.h>
+#include <klineedit.h>
+#include <kconfig.h>
+#include <kdialog.h>
+#include <kurlrequester.h>
+#include <kstandarddirs.h>
+
+// KTTS includes.
+#include "filterconf.h"
+
+// XmlTransformer includes.
+#include "xmltransformerconf.h"
+#include "xmltransformerconf.moc"
+
+/**
+* Constructor
+*/
+XmlTransformerConf::XmlTransformerConf( QWidget *parent, const char *name, const QStringList& /*args*/) :
+ KttsFilterConf(parent, name)
+{
+ // kdDebug() << "XmlTransformerConf::XmlTransformerConf: Running" << endl;
+
+ // Create configuration widget.
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "XmlTransformerConfWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new XmlTransformerConfWidget(this, "XmlTransformerConfigWidget");
+ layout->addWidget(m_widget);
+
+ // Set up defaults.
+ defaults();
+
+ // Connect signals.
+ connect( m_widget->nameLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect( m_widget->xsltPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+ connect( m_widget->xsltprocPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+ connect( m_widget->rootElementLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+ connect( m_widget->doctypeLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+ connect( m_widget->appIdLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()) );
+}
+
+/**
+* Destructor.
+*/
+XmlTransformerConf::~XmlTransformerConf(){
+ // kdDebug() << "XmlTransformerConf::~XmlTransformerConf: Running" << endl;
+}
+
+/**
+* This method is invoked whenever the module should read its
+* configuration (most of the times from a config file) and update the
+* user interface. This happens when the user clicks the "Reset" button in
+* the control center, to undo all of his changes and restore the currently
+* valid settings. Note that kttsmgr calls this when the plugin is
+* loaded, so it not necessary to call it in your constructor.
+* The plugin should read its configuration from the specified group
+* in the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* loading your configuration.
+*/
+void XmlTransformerConf::load(KConfig* config, const QString& configGroup){
+ // kdDebug() << "XmlTransformerConf::load: Running" << endl;
+ config->setGroup( configGroup );
+ m_widget->nameLineEdit->setText( config->readEntry( "UserFilterName", m_widget->nameLineEdit->text() ) );
+ m_widget->xsltPath->setURL( config->readEntry( "XsltFilePath", m_widget->xsltPath->url() ) );
+ m_widget->xsltprocPath->setURL( config->readEntry( "XsltprocPath", m_widget->xsltprocPath->url() ) );
+ m_widget->rootElementLineEdit->setText(
+ config->readEntry( "RootElement", m_widget->rootElementLineEdit->text() ) );
+ m_widget->doctypeLineEdit->setText(
+ config->readEntry( "DocType", m_widget->doctypeLineEdit->text() ) );
+ m_widget->appIdLineEdit->setText(
+ config->readEntry( "AppID", m_widget->appIdLineEdit->text() ) );
+}
+
+/**
+* This function gets called when the user wants to save the settings in
+* the user interface, updating the config files or wherever the
+* configuration is stored. The method is called when the user clicks "Apply"
+* or "Ok". The plugin should save its configuration in the specified
+* group of the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* saving your configuration.
+*/
+void XmlTransformerConf::save(KConfig* config, const QString& configGroup){
+ // kdDebug() << "XmlTransformerConf::save: Running" << endl;
+ config->setGroup( configGroup );
+ config->writeEntry( "UserFilterName", m_widget->nameLineEdit->text() );
+ config->writeEntry( "XsltFilePath", realFilePath( m_widget->xsltPath->url() ) );
+ config->writeEntry( "XsltprocPath", realFilePath( m_widget->xsltprocPath->url() ) );
+ config->writeEntry( "RootElement", m_widget->rootElementLineEdit->text() );
+ config->writeEntry( "DocType", m_widget->doctypeLineEdit->text() );
+ config->writeEntry( "AppID", m_widget->appIdLineEdit->text().replace(" ", "") );
+}
+
+/**
+* This function is called to set the settings in the module to sensible
+* default values. It gets called when hitting the "Default" button. The
+* default values should probably be the same as the ones the application
+* uses when started without a config file. Note that defaults should
+* be applied to the on-screen widgets; not to the config file.
+*/
+void XmlTransformerConf::defaults(){
+ // kdDebug() << "XmlTransformerConf::defaults: Running" << endl;
+ // Default name.
+ m_widget->nameLineEdit->setText(i18n( "XML Transformer" ));
+ // Default XSLT path to installed xsl files.
+ m_widget->xsltPath->setURL( locate("data", "kttsd/xmltransformer/") );
+ // Default path to xsltproc.
+ m_widget->xsltprocPath->setURL( "xsltproc" );
+ // Default root element to "html".
+ m_widget->rootElementLineEdit->setText( "html" );
+ // Default doctype to blank.
+ m_widget->doctypeLineEdit->setText( "" );
+ // Default App ID to blank.
+ m_widget->appIdLineEdit->setText( "" );
+ // kdDebug() << "XmlTransformerConf::defaults: Exiting" << endl;
+}
+
+/**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+bool XmlTransformerConf::supportsMultiInstance() { return true; }
+
+/**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+QString XmlTransformerConf::userPlugInName()
+{
+ QString filePath = realFilePath(m_widget->xsltprocPath->url());
+ if (filePath.isEmpty()) return QString::null;
+ if (getLocation(filePath).isEmpty()) return QString::null;
+
+ filePath = realFilePath(m_widget->xsltPath->url());
+ if (filePath.isEmpty()) return QString::null;
+ if (getLocation(filePath).isEmpty()) return QString::null;
+ if (!QFileInfo(filePath).isFile()) return QString::null;
+
+ return m_widget->nameLineEdit->text();
+}
diff --git a/kttsd/filters/xmltransformer/xmltransformerconf.h b/kttsd/filters/xmltransformer/xmltransformerconf.h
new file mode 100644
index 0000000..86df0e2
--- /dev/null
+++ b/kttsd/filters/xmltransformer/xmltransformerconf.h
@@ -0,0 +1,120 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic XML Transformation Filter Configuration class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _XMLTRANSFORMERCONF_H_
+#define _XMLTRANSFORMERCONF_H_
+
+// Qt includes.
+#include <qwidget.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "filterconf.h"
+
+// XmlTransformer includes.
+#include "xmltransformerconfwidget.h"
+
+class XmlTransformerConf : public KttsFilterConf
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ XmlTransformerConf( QWidget *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor
+ */
+ virtual ~XmlTransformerConf();
+
+ /**
+ * This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. Note that KTTSMGR calls this when the plugin is
+ * loaded, so it not necessary to call it in your constructor.
+ * The plugin should read its configuration from the specified group
+ * in the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * loading your configuration.
+ *
+ * When a plugin is first added to KTTSMGR, @e load will be called with
+ * a Null @e configGroup. In this case, the plugin will not have
+ * any instance-specific parameters to load, but it may still wish
+ * to load parameters that apply to all instances of the plugin.
+ */
+ virtual void load(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok". The plugin should save its configuration in the specified
+ * group of the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * saving your configuration.
+ */
+ virtual void save(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file. Note that defaults should
+ * be applied to the on-screen widgets; not to the config file.
+ */
+ virtual void defaults();
+
+ /**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+ virtual bool supportsMultiInstance();
+
+ /**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+ virtual QString userPlugInName();
+
+ private slots:
+
+ private:
+ // Configuration Widget.
+ XmlTransformerConfWidget* m_widget;
+};
+
+#endif //_XMLTRANSFORMERCONF_H_
diff --git a/kttsd/filters/xmltransformer/xmltransformerconfwidget.ui b/kttsd/filters/xmltransformer/xmltransformerconfwidget.ui
new file mode 100644
index 0000000..4975d9c
--- /dev/null
+++ b/kttsd/filters/xmltransformer/xmltransformerconfwidget.ui
@@ -0,0 +1,249 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>XmlTransformerConfWidget</class>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>XmlTransformerConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>548</width>
+ <height>256</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Configure XML Transformer</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any descriptive name you like for this filter.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>xsltPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the full path to an XML Style Language - Transforms (XSLT) stylesheet file. XSLT files usually end with extension .xsl.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>xsltprocPath</cstring>
+ </property>
+ <property name="url" stdset="0">
+ <string>xsltproc</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the path to the xsltproc executable program. If it is in the PATH environment variable, just enter "xsltproc".</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>nameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Name:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any descriptive name you like for this filter.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>xsltLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;XSLT file:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>xsltPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the full path to an XML Style Language - Transforms (XSLT) stylesheet file. XSLT files usually end with extension .xsl.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>xsltprocLabel</cstring>
+ </property>
+ <property name="text">
+ <string>xsltproc &amp;executable:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>xsltprocPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the path to the xsltproc executable program. If it is in the PATH environment variable, just enter "xsltproc".</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>applyGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Apply This &amp;Filter When</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>These settings determines when the filter is applied to text.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>rootElementLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter will be applied only to text having the specified XML root element. If blank, applies to all text. You may enter more than one root element separated by commas. Example: "html".</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>doctypeLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter will be applied only to text having the specified DOCTYPE specification. If blank, applies to all text. You may enter more than one DOCTYPE separated by commas. Example: "xhtml".</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter a DCOP Application ID. This filter will only apply to text queued by that application. You may enter more than one ID separated by commas. Use &lt;b&gt;knotify&lt;/b&gt; to match all messages sent as KDE notifications. If blank, this filter applies to text queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>rootElementLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Root element is:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>rootElementLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter will be applied only to text having the specified XML root element. If blank, applies to all text. You may enter more than one root element separated by commas. Example: "html".</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>doctypeLabel</cstring>
+ </property>
+ <property name="text">
+ <string>or DOC&amp;TYPE is:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>doctypeLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter will be applied only to text having the specified DOCTYPE specification. If blank, applies to all text. You may enter more than one DOCTYPE separated by commas. Example: "xhtml".</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>appIdLabel</cstring>
+ </property>
+ <property name="text">
+ <string>and Application &amp;ID contains:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter a DCOP Application ID. This filter will only apply to text queued by that application. You may enter more than one ID separated by commas. Use &lt;b&gt;knotify&lt;/b&gt; to match all messages sent as KDE notifications. If blank, this filter applies to text queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/filters/xmltransformer/xmltransformerplugin.cpp b/kttsd/filters/xmltransformer/xmltransformerplugin.cpp
new file mode 100644
index 0000000..c76c889
--- /dev/null
+++ b/kttsd/filters/xmltransformer/xmltransformerplugin.cpp
@@ -0,0 +1,31 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so XML Transformer Filter can be used as plug in.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "xmltransformerconf.h"
+#include "xmltransformerproc.h"
+
+typedef K_TYPELIST_2( XmlTransformerProc, XmlTransformerConf ) XmlTransformerPlugin;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_xmltransformerplugin,
+ KGenericFactory<XmlTransformerPlugin>("kttsd_xmltransformer") )
diff --git a/kttsd/filters/xmltransformer/xmltransformerproc.cpp b/kttsd/filters/xmltransformer/xmltransformerproc.cpp
new file mode 100644
index 0000000..d4aa1c5
--- /dev/null
+++ b/kttsd/filters/xmltransformer/xmltransformerproc.cpp
@@ -0,0 +1,385 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic XML Transformation Filter Processing class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qfile.h>
+#include <qregexp.h>
+
+// KDE includes.
+#include <kdeversion.h>
+#include <kconfig.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "filterproc.h"
+#include "utils.h"
+
+// XmlTransformer includes.
+#include "xmltransformerproc.h"
+#include "xmltransformerproc.moc"
+
+/**
+ * Constructor.
+ */
+XmlTransformerProc::XmlTransformerProc( QObject *parent, const char *name, const QStringList& ) :
+ KttsFilterProc(parent, name)
+{
+ m_xsltProc = 0;
+}
+
+/**
+ * Destructor.
+ */
+/*virtual*/ XmlTransformerProc::~XmlTransformerProc()
+{
+ delete m_xsltProc;
+ if (!m_inFilename.isEmpty()) QFile::remove(m_inFilename);
+ if (!m_outFilename.isEmpty()) QFile::remove(m_outFilename);
+}
+
+/**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+bool XmlTransformerProc::init(KConfig* config, const QString& configGroup)
+{
+ // kdDebug() << "XmlTransformerProc::init: Running." << endl;
+ config->setGroup( configGroup );
+ m_UserFilterName = config->readEntry( "UserFilterName" );
+ m_xsltFilePath = config->readEntry( "XsltFilePath" );
+ m_xsltprocPath = config->readEntry( "XsltprocPath" );
+ m_rootElementList = config->readListEntry( "RootElement", ',' );
+ m_doctypeList = config->readListEntry( "DocType", ',' );
+ m_appIdList = config->readListEntry( "AppID", ',' );
+ kdDebug() << "XmlTransformerProc::init: m_xsltprocPath = " << m_xsltprocPath << endl;
+ kdDebug() << "XmlTransformerProc::init: m_xsltFilePath = " << m_xsltFilePath << endl;
+ return ( m_xsltFilePath.isEmpty() || m_xsltprocPath.isEmpty() );
+}
+
+/**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+/*virtual*/ bool XmlTransformerProc::supportsAsync() { return true; }
+
+/**
+ * Convert input, returning output.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+/*virtual*/ QString XmlTransformerProc::convert(const QString& inputText, TalkerCode* talkerCode,
+ const QCString& appId)
+{
+ // kdDebug() << "XmlTransformerProc::convert: Running." << endl;
+ // If not properly configured, do nothing.
+ if ( m_xsltFilePath.isEmpty() || m_xsltprocPath.isEmpty() )
+ {
+ kdDebug() << "XmlTransformerProc::convert: not properly configured" << endl;
+ return inputText;
+ }
+ // Asynchronously convert and wait for completion.
+ if (asyncConvert(inputText, talkerCode, appId))
+ {
+ waitForFinished();
+ m_state = fsIdle;
+ return m_text;
+ } else
+ return inputText;
+}
+
+/**
+ * Convert input. Runs asynchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ * @return False if the filter cannot perform the conversion.
+ *
+ * When conversion is completed, emits signal @ref filteringFinished. Calling
+ * program may then call @ref getOutput to retrieve converted text. Calling
+ * program must call @ref ackFinished to acknowledge the conversion.
+ */
+/*virtual*/ bool XmlTransformerProc::asyncConvert(const QString& inputText, TalkerCode* /*talkerCode*/,
+ const QCString& appId)
+{
+ m_wasModified = false;
+
+ // kdDebug() << "XmlTransformerProc::asyncConvert: Running." << endl;
+ m_text = inputText;
+ // If not properly configured, do nothing.
+ if ( m_xsltFilePath.isEmpty() || m_xsltprocPath.isEmpty() )
+ {
+ kdDebug() << "XmlTransformerProc::asyncConvert: not properly configured." << endl;
+ return false;
+ }
+
+ bool found = false;
+ // If not correct XML type, or DOCTYPE, do nothing.
+ if ( !m_rootElementList.isEmpty() )
+ {
+ // kdDebug() << "XmlTransformerProc::asyncConvert:: searching for root elements " << m_rootElementList << endl;
+ for ( uint ndx=0; ndx < m_rootElementList.count(); ++ndx )
+ {
+ if ( KttsUtils::hasRootElement( inputText, m_rootElementList[ndx] ) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found && m_doctypeList.isEmpty() )
+ {
+ kdDebug() << "XmlTransformerProc::asyncConvert: Did not find root element(s)" << m_rootElementList << endl;
+ return false;
+ }
+ }
+ if ( !found && !m_doctypeList.isEmpty() )
+ {
+ for ( uint ndx=0; ndx < m_doctypeList.count(); ++ndx )
+ {
+ if ( KttsUtils::hasDoctype( inputText, m_doctypeList[ndx] ) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ {
+ // kdDebug() << "XmlTransformerProc::asyncConvert: Did not find doctype(s)" << m_doctypeList << endl;
+ return false;
+ }
+ }
+
+ // If appId doesn't match, return input unmolested.
+ if ( !m_appIdList.isEmpty() )
+ {
+ QString appIdStr = appId;
+ // kdDebug() << "XmlTransformrProc::convert: converting " << inputText << " if appId "
+ // << appId << " matches " << m_appIdList << endl;
+ found = false;
+ for ( uint ndx=0; ndx < m_appIdList.count(); ++ndx )
+ {
+ if ( appIdStr.contains(m_appIdList[ndx]) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ {
+ // kdDebug() << "XmlTransformerProc::asyncConvert: Did not find appId(s)" << m_appIdList << endl;
+ return false;
+ }
+ }
+
+ /// Write @param text to a temporary file.
+ KTempFile inFile(locateLocal("tmp", "kttsd-"), ".xml");
+ m_inFilename = inFile.file()->name();
+ QTextStream* wstream = inFile.textStream();
+ if (wstream == 0) {
+ /// wtf...
+ kdDebug() << "XmlTransformerProc::convert: Can't write to " << m_inFilename << endl;;
+ return false;
+ }
+ // TODO: Is encoding an issue here?
+ // If input does not have xml processing instruction, add it.
+ if (!inputText.startsWith("<?xml")) *wstream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+ // FIXME: Temporary Fix until Konqi returns properly formatted xhtml with & coded as &amp;
+ // This will change & inside a CDATA section, which is not good, and also within comments and
+ // processing instructions, which is OK because we don't speak those anyway.
+ QString text = inputText;
+ text.replace(QRegExp("&(?!amp;)"),"&amp;");
+ *wstream << text;
+ inFile.close();
+#if KDE_VERSION >= KDE_MAKE_VERSION (3,3,0)
+ inFile.sync();
+#endif
+
+ // Get a temporary output file name.
+ KTempFile outFile(locateLocal("tmp", "kttsd-"), ".output");
+ m_outFilename = outFile.file()->name();
+ outFile.close();
+ // outFile.unlink(); // only activate this if necessary.
+
+ /// Spawn an xsltproc process to apply our stylesheet to input file.
+ m_xsltProc = new KProcess;
+ *m_xsltProc << m_xsltprocPath;
+ *m_xsltProc << "-o" << m_outFilename << "--novalid"
+ << m_xsltFilePath << m_inFilename;
+ // Warning: This won't compile under KDE 3.2. See FreeTTS::argsToStringList().
+ // kdDebug() << "SSMLConvert::transform: executing command: " <<
+ // m_xsltProc->args() << endl;
+
+ m_state = fsFiltering;
+ connect(m_xsltProc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*)));
+ connect(m_xsltProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStdout(KProcess*, char*, int)));
+ connect(m_xsltProc, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStderr(KProcess*, char*, int)));
+ if (!m_xsltProc->start(KProcess::NotifyOnExit,
+ static_cast<KProcess::Communication>(KProcess::Stdout | KProcess::Stderr)))
+ {
+ kdDebug() << "XmlTransformerProc::convert: Error starting xsltproc" << endl;
+ m_state = fsIdle;
+ return false;
+ }
+ return true;
+}
+
+// Process output when xsltproc exits.
+void XmlTransformerProc::processOutput()
+{
+ QFile::remove(m_inFilename);
+
+ int exitStatus = 11;
+ if (m_xsltProc->normalExit())
+ exitStatus = m_xsltProc->exitStatus();
+ else
+ kdDebug() << "XmlTransformerProc::processOutput: xsltproc was killed." << endl;
+
+ delete m_xsltProc;
+ m_xsltProc = 0;
+
+ if (exitStatus != 0)
+ {
+ kdDebug() << "XmlTransformerProc::processOutput: xsltproc abnormal exit. Status = " << exitStatus << endl;
+ m_state = fsFinished;
+ QFile::remove(m_outFilename);
+ emit filteringFinished();
+ return;
+ }
+
+ /// Read back the data that was written to /tmp/fileName.output.
+ QFile readfile(m_outFilename);
+ if(!readfile.open(IO_ReadOnly)) {
+ /// uhh yeah... Issues writing to the output file.
+ kdDebug() << "XmlTransformerProc::processOutput: Could not read file " << m_outFilename << endl;
+ m_state = fsFinished;
+ emit filteringFinished();
+ }
+ QTextStream rstream(&readfile);
+ m_text = rstream.read();
+ readfile.close();
+
+ kdDebug() << "XmlTransformerProc::processOutput: Read file at " + m_inFilename + " and created " + m_outFilename + " based on the stylesheet at " << m_xsltFilePath << endl;
+
+ // Clean up.
+ QFile::remove(m_outFilename);
+
+ m_state = fsFinished;
+ m_wasModified = true;
+ emit filteringFinished();
+}
+
+/**
+ * Waits for a previous call to asyncConvert to finish.
+ */
+/*virtual*/ void XmlTransformerProc::waitForFinished()
+{
+ if (m_xsltProc)
+ {
+ if (m_xsltProc->isRunning())
+ {
+ if ( !m_xsltProc->wait( 15 ) )
+ {
+ m_xsltProc->kill();
+ kdDebug() << "XmlTransformerProc::waitForFinished: After waiting 15 seconds, xsltproc process seems to hung. Killing it." << endl;
+ processOutput();
+ }
+ }
+ }
+}
+
+/**
+ * Returns the state of the Filter.
+ */
+/*virtual*/ int XmlTransformerProc::getState() { return m_state; }
+
+/**
+ * Returns the filtered output.
+ */
+/*virtual*/ QString XmlTransformerProc::getOutput() { return m_text; }
+
+/**
+ * Acknowledges the finished filtering.
+ */
+/*virtual*/ void XmlTransformerProc::ackFinished()
+{
+ m_state = fsIdle;
+ m_text = QString::null;
+}
+
+/**
+ * Stops filtering. The filteringStopped signal will emit when filtering
+ * has in fact stopped and state returns to fsIdle;
+ */
+/*virtual*/ void XmlTransformerProc::stopFiltering()
+{
+ m_state = fsStopping;
+ m_xsltProc->kill();
+}
+
+/**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+/*virtual*/ bool XmlTransformerProc::wasModified() { return m_wasModified; }
+
+void XmlTransformerProc::slotProcessExited(KProcess*)
+{
+ // kdDebug() << "XmlTransformerProc::slotProcessExited: xsltproc has exited." << endl;
+ processOutput();
+}
+
+void XmlTransformerProc::slotReceivedStdout(KProcess*, char* /*buffer*/, int /*buflen*/)
+{
+ // QString buf = QString::fromLatin1(buffer, buflen);
+ // kdDebug() << "XmlTransformerProc::slotReceivedStdout: Received from xsltproc: " << buf << endl;
+}
+
+void XmlTransformerProc::slotReceivedStderr(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "XmlTransformerProc::slotReceivedStderr: Received error from xsltproc: " << buf << endl;
+}
+
diff --git a/kttsd/filters/xmltransformer/xmltransformerproc.h b/kttsd/filters/xmltransformer/xmltransformerproc.h
new file mode 100644
index 0000000..7c88dd1
--- /dev/null
+++ b/kttsd/filters/xmltransformer/xmltransformerproc.h
@@ -0,0 +1,167 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic XML Transformation Filter Processing class.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _XMLTRANSFORMERPROC_H_
+#define _XMLTRANSFORMERPROC_H_
+
+// Qt includes.
+#include <qobject.h>
+#include <qstringlist.h>
+
+// KTTS includes.
+#include "filterproc.h"
+
+class KProcess;
+
+class XmlTransformerProc : virtual public KttsFilterProc
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ */
+ XmlTransformerProc( QObject *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor.
+ */
+ virtual ~XmlTransformerProc();
+
+ /**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Convert input, returning output.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+ virtual QString convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+ /**
+ * Convert input. Runs asynchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ * @return False if the filter cannot perform the conversion.
+ *
+ * When conversion is completed, emits signal @ref filteringFinished. Calling
+ * program may then call @ref getOutput to retrieve converted text. Calling
+ * program must call @ref ackFinished to acknowledge the conversion.
+ */
+ virtual bool asyncConvert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+ /**
+ * Waits for a previous call to asyncConvert to finish.
+ */
+ virtual void waitForFinished();
+
+ /**
+ * Returns the state of the Filter.
+ */
+ virtual int getState();
+
+ /**
+ * Returns the filtered output.
+ */
+ virtual QString getOutput();
+
+ /**
+ * Acknowledges the finished filtering.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Stops filtering. The filteringStopped signal will emit when filtering
+ * has in fact stopped and state returns to fsIdle;
+ */
+ virtual void stopFiltering();
+
+ /**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+ virtual bool wasModified();
+
+private slots:
+ void slotProcessExited(KProcess*);
+ void slotReceivedStdout(KProcess* proc, char* buffer, int buflen);
+ void slotReceivedStderr(KProcess* proc, char* buffer, int buflen);
+
+private:
+ // Process output when xsltproc exits.
+ void processOutput();
+
+ // If not empty, only apply to text queued by an applications containing one of these strings.
+ QStringList m_appIdList;
+ // If not empty, only apply to XML that has the specified root element.
+ QStringList m_rootElementList;
+ // If not empty, only apply to XML that has the specified DOCTYPE spec.
+ QStringList m_doctypeList;
+ // The text that is being filtered.
+ QString m_text;
+ // Processing state.
+ int m_state;
+ // xsltproc process.
+ KProcess* m_xsltProc;
+ // Input and Output filenames.
+ QString m_inFilename;
+ QString m_outFilename;
+ // User's name for the filter.
+ QString m_UserFilterName;
+ // XSLT file.
+ QString m_xsltFilePath;
+ // Path to xsltproc processor.
+ QString m_xsltprocPath;
+ // Did this filter modify the text?
+ bool m_wasModified;
+};
+
+#endif // _XMLTRANSFORMERPROC_H_
diff --git a/kttsd/icons/Makefile.am b/kttsd/icons/Makefile.am
new file mode 100644
index 0000000..e5515a8
--- /dev/null
+++ b/kttsd/icons/Makefile.am
@@ -0,0 +1 @@
+KDE_ICON = AUTO
diff --git a/kttsd/icons/hi16-action-female.png b/kttsd/icons/hi16-action-female.png
new file mode 100644
index 0000000..702710f
--- /dev/null
+++ b/kttsd/icons/hi16-action-female.png
Binary files differ
diff --git a/kttsd/icons/hi16-action-male.png b/kttsd/icons/hi16-action-male.png
new file mode 100644
index 0000000..59074a4
--- /dev/null
+++ b/kttsd/icons/hi16-action-male.png
Binary files differ
diff --git a/kttsd/icons/hi16-action-nospeak.png b/kttsd/icons/hi16-action-nospeak.png
new file mode 100644
index 0000000..313ad5a
--- /dev/null
+++ b/kttsd/icons/hi16-action-nospeak.png
Binary files differ
diff --git a/kttsd/icons/hi16-action-speak.png b/kttsd/icons/hi16-action-speak.png
new file mode 100644
index 0000000..69078b9
--- /dev/null
+++ b/kttsd/icons/hi16-action-speak.png
Binary files differ
diff --git a/kttsd/icons/hi22-action-nospeak.png b/kttsd/icons/hi22-action-nospeak.png
new file mode 100644
index 0000000..39de8d3
--- /dev/null
+++ b/kttsd/icons/hi22-action-nospeak.png
Binary files differ
diff --git a/kttsd/icons/hi22-action-speak.png b/kttsd/icons/hi22-action-speak.png
new file mode 100644
index 0000000..1052d56
--- /dev/null
+++ b/kttsd/icons/hi22-action-speak.png
Binary files differ
diff --git a/kttsd/icons/hi32-action-nospeak.png b/kttsd/icons/hi32-action-nospeak.png
new file mode 100644
index 0000000..7882b63
--- /dev/null
+++ b/kttsd/icons/hi32-action-nospeak.png
Binary files differ
diff --git a/kttsd/icons/hi32-action-speak.png b/kttsd/icons/hi32-action-speak.png
new file mode 100644
index 0000000..617025f
--- /dev/null
+++ b/kttsd/icons/hi32-action-speak.png
Binary files differ
diff --git a/kttsd/icons/hi48-action-nospeak.png b/kttsd/icons/hi48-action-nospeak.png
new file mode 100644
index 0000000..86d5220
--- /dev/null
+++ b/kttsd/icons/hi48-action-nospeak.png
Binary files differ
diff --git a/kttsd/icons/hi48-action-speak.png b/kttsd/icons/hi48-action-speak.png
new file mode 100644
index 0000000..26d22ce
--- /dev/null
+++ b/kttsd/icons/hi48-action-speak.png
Binary files differ
diff --git a/kttsd/icons/lo16-action-speak.png b/kttsd/icons/lo16-action-speak.png
new file mode 100644
index 0000000..69078b9
--- /dev/null
+++ b/kttsd/icons/lo16-action-speak.png
Binary files differ
diff --git a/kttsd/icons/lo22-action-speak.png b/kttsd/icons/lo22-action-speak.png
new file mode 100644
index 0000000..1052d56
--- /dev/null
+++ b/kttsd/icons/lo22-action-speak.png
Binary files differ
diff --git a/kttsd/icons/lo32-action-speak.png b/kttsd/icons/lo32-action-speak.png
new file mode 100644
index 0000000..617025f
--- /dev/null
+++ b/kttsd/icons/lo32-action-speak.png
Binary files differ
diff --git a/kttsd/kcmkttsmgr/Makefile.am b/kttsd/kcmkttsmgr/Makefile.am
new file mode 100644
index 0000000..094f59c
--- /dev/null
+++ b/kttsd/kcmkttsmgr/Makefile.am
@@ -0,0 +1,51 @@
+# Include paths.
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(CFLAGS_GST) \
+ $(KTTS_KSPEECH_INCLUDE) \
+ $(all_includes)
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# KCMODULE SECTION
+#########################################################################
+# This is the kcmodule that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+
+kde_module_LTLIBRARIES = kcm_kttsd.la
+
+kspeech_DIR = $(KTTS_KSPEECH_DIR)
+kspeechsink_DIR = $(KTTS_KSPEECH_DIR)
+
+# The source, library search path, and link libraries.
+kcm_kttsd_la_SOURCES = \
+ kspeech.stub \
+ kspeechsink.skel \
+ kcmkttsmgr.cpp \
+ kcmkttsmgrwidget.ui \
+ addtalker.cpp \
+ addtalkerwidget.ui \
+ selectevent.cpp \
+ selecteventwidget.ui
+
+kcm_kttsd_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries)
+kcm_kttsd_la_LIBADD = \
+ $(top_builddir)/kttsd/libkttsd/libkttsd.la \
+ $(LIB_KIO)
+
+# Header files that should not be installed.
+noinst_HEADERS = \
+ kcmkttsmgr.h \
+ kcmkttsmgrwidget.h \
+ kcmkttsmgrwidget.ui.h \
+ addtalker.h \
+ selectevent.h
+
+# K Menu entry.
+xdg_apps_DATA = kcmkttsd.desktop
+
+# Install data files.
+kcmkttsddatadir = $(kde_datadir)/kttsd/
+kcmkttsddata_DATA = kcmkttsd_testmessage.desktop
diff --git a/kttsd/kcmkttsmgr/addtalker.cpp b/kttsd/kcmkttsmgr/addtalker.cpp
new file mode 100644
index 0000000..2353ada
--- /dev/null
+++ b/kttsd/kcmkttsmgr/addtalker.cpp
@@ -0,0 +1,225 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Dialog to allow user to add a new Talker by selecting a language and synthesizer
+ (button). Uses addtalkerwidget.ui.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qradiobutton.h>
+
+// KDE includes.
+#include <kcombobox.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "addtalker.h"
+
+AddTalker::AddTalker(SynthToLangMap synthToLangMap, QWidget* parent, const char* name, WFlags fl)
+ : AddTalkerWidget(parent,name,fl)
+{
+ // Build maps.
+ setSynthToLangMap(synthToLangMap);
+
+ // Fill comboboxes.
+ applyFilter();
+
+ // Default to user's desktop language.
+ QString languageCode = KGlobal::locale()->defaultLanguage();
+ // If there is not a synth that supports the locale, try stripping country code.
+ if (!m_langToSynthMap.contains(languageCode))
+ {
+ QString countryCode;
+ QString charSet;
+ QString twoAlpha;
+ KGlobal::locale()->splitLocale(languageCode, twoAlpha, countryCode, charSet);
+ languageCode = twoAlpha;
+ }
+ // If there is still not a synth that supports the language code, default to "other".
+ if (!m_langToSynthMap.contains(languageCode)) languageCode = "other";
+
+ // Select the language in the language combobox.
+ QString language = languageCodeToLanguage(languageCode);
+ languageSelection->setCurrentItem(language, false);
+
+ // Filter comboboxes.
+ applyFilter();
+
+ // Connect widgets to slots.
+ connect(languageRadioButton, SIGNAL(clicked()), this, SLOT(applyFilter()));
+ connect(synthesizerRadioButton, SIGNAL(clicked()), this, SLOT(applyFilter()));
+ connect(languageSelection, SIGNAL(activated(int)), this, SLOT(applyFilter()));
+ connect(synthesizerSelection, SIGNAL(activated(int)), this, SLOT(applyFilter()));
+}
+
+AddTalker::~AddTalker()
+{
+}
+
+/**
+* Returns user's chosen language code.
+*/
+QString AddTalker::getLanguageCode()
+{
+ return m_languageToLanguageCodeMap[languageSelection->currentText()];
+}
+
+/**
+* Returns user's chosen synthesizer.
+*/
+QString AddTalker::getSynthesizer() { return synthesizerSelection->currentText(); }
+
+// Set the synthesizer-to-languages map.
+// @param synthToLang QMap of supported language codes indexed by synthesizer.
+void AddTalker::setSynthToLangMap(SynthToLangMap synthToLangMap)
+{
+ m_synthToLangMap = synthToLangMap;
+ // "Invert" the map, i.e., map language codes to synthesizers.
+ QStringList synthList = m_synthToLangMap.keys();
+ const int synthListCount = synthList.count();
+ for (int synthNdx=0; synthNdx < synthListCount; ++synthNdx)
+ {
+ QString synth = synthList[synthNdx];
+ QStringList languageCodeList = m_synthToLangMap[synth];
+ const int languageCodeListCount = languageCodeList.count();
+ for (int langNdx=0; langNdx < languageCodeListCount; ++langNdx)
+ {
+ QString languageCode = languageCodeList[langNdx];
+ QStringList synthesizerList = m_langToSynthMap[languageCode];
+ synthesizerList.append(synth);
+ m_langToSynthMap[languageCode] = synthesizerList;
+ }
+ }
+ // Fill language to language code map.
+ QStringList languageCodeList = m_langToSynthMap.keys();
+ const int languageCodeListCount = languageCodeList.count();
+ for (int ndx = 0; ndx < languageCodeListCount; ++ndx)
+ {
+ QString languageCode = languageCodeList[ndx];
+ QString language = languageCodeToLanguage(languageCode);
+ m_languageToLanguageCodeMap[language] = languageCode;
+ }
+}
+
+// Converts a language code plus optional country code to language description.
+QString AddTalker::languageCodeToLanguage(const QString &languageCode)
+{
+ QString twoAlpha;
+ QString countryCode;
+ QString charSet;
+ QString language;
+ if (languageCode == "other")
+ language = i18n("Other");
+ else
+ {
+ KGlobal::locale()->splitLocale(languageCode, twoAlpha, countryCode, charSet);
+ language = KGlobal::locale()->twoAlphaToLanguageName(twoAlpha);
+ }
+ if (!countryCode.isEmpty())
+ language += " (" + KGlobal::locale()->twoAlphaToCountryName(countryCode) + ")";
+ return language;
+}
+
+// Based on user's radio button selection, filters choices for language or synthesizer
+// comboboxes based on what is selected in the other combobox.
+void AddTalker::applyFilter()
+{
+ if (languageRadioButton->isChecked())
+ {
+ // Get current language.
+ QString language = languageSelection->currentText();
+ // Fill language combobox will all possible languages.
+ languageSelection->clear();
+ QStringList languageCodeList = m_langToSynthMap.keys();
+ const int languageCodeListCount = languageCodeList.count();
+ QStringList languageList;
+ for (int ndx=0; ndx < languageCodeListCount; ++ndx)
+ {
+ languageList.append(languageCodeToLanguage(languageCodeList[ndx]));
+ }
+ languageList.sort();
+ for (int ndx=0; ndx < languageCodeListCount; ++ndx)
+ {
+ languageSelection->insertItem(languageList[ndx]);
+ }
+ // Re-select user's selection.
+ languageSelection->setCurrentItem(language, false);
+ // Get current language selection.
+ language = languageSelection->currentText();
+ // Map current language to language code.
+ QString languageCode = m_languageToLanguageCodeMap[language];
+ // Get list of synths that support this language code.
+ QStringList synthList = m_langToSynthMap[languageCode];
+ // Get current user's synth selection.
+ QString synth = synthesizerSelection->currentText();
+ // Fill synthesizer combobox.
+ synthesizerSelection->clear();
+ synthList.sort();
+ const int synthListCount = synthList.count();
+ for (int ndx=0; ndx < synthListCount; ++ndx)
+ {
+ synthesizerSelection->insertItem(synthList[ndx]);
+ }
+ // Re-select user's selection.
+ synthesizerSelection->setCurrentItem(synth, false);
+ }
+ else
+ {
+ // Get current synth selection.
+ QString synth = synthesizerSelection->currentText();
+ // Fill synthesizer combobox with all possible synths.
+ synthesizerSelection->clear();
+ QStringList synthList = m_synthToLangMap.keys();
+ synthList.sort();
+ const int synthListCount = synthList.count();
+ for (int ndx=0; ndx < synthListCount; ++ndx)
+ {
+ synthesizerSelection->insertItem(synthList[ndx]);
+ }
+ // Re-select user's synthesizer.
+ synthesizerSelection->setCurrentItem(synth, false);
+ // Get current synth selection.
+ synth = synthesizerSelection->currentText();
+ // Get list of supported language codes.
+ QStringList languageCodeList = m_synthToLangMap[synth];
+ // Get current user's language selection.
+ QString language = languageSelection->currentText();
+ // Fill language combobox with language descriptions.
+ languageSelection->clear();
+ const int languageCodeListCount = languageCodeList.count();
+ QStringList languageList;
+ for (int ndx=0; ndx < languageCodeListCount; ++ndx)
+ {
+ languageList.append(languageCodeToLanguage(languageCodeList[ndx]));
+ }
+ languageList.sort();
+ for (int ndx=0; ndx < languageCodeListCount; ++ndx)
+ {
+ languageSelection->insertItem(languageList[ndx]);
+ }
+ // Re-select user's language selection.
+ languageSelection->setCurrentItem(language, false);
+ }
+}
+
+#include "addtalker.moc"
+
diff --git a/kttsd/kcmkttsmgr/addtalker.h b/kttsd/kcmkttsmgr/addtalker.h
new file mode 100644
index 0000000..29bbfb5
--- /dev/null
+++ b/kttsd/kcmkttsmgr/addtalker.h
@@ -0,0 +1,89 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Dialog to allow user to add a new Talker by selecting a language and synthesizer
+ (button). Uses addtalkerwidget.ui.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef ADDTALKER_H
+#define ADDTALKER_H
+
+// Qt includes.
+#include <qmap.h>
+
+#include "addtalkerwidget.h"
+
+typedef QMap<QString,QStringList> SynthToLangMap;
+typedef QMap<QString,QStringList> LangToSynthMap;
+
+class AddTalker : public AddTalkerWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ * @param synthToLangMap QMap of supported language codes indexed by synthesizer.
+ * @param parent Inherited KDialog parameter.
+ * @param name Inherited KDialog parameter.
+ */
+ AddTalker(SynthToLangMap synthToLangMap, QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+
+ /**
+ * Destructor.
+ */
+ ~AddTalker();
+
+ /**
+ * Returns user's chosen language code.
+ */
+ QString getLanguageCode();
+
+ /**
+ * Returns user's chosen synthesizer.
+ */
+ QString getSynthesizer();
+
+
+private:
+ /**
+ * Set the synthesizer-to-languages map.
+ * @param synthToLang QMap of supported language codes indexed by synthesizer.
+ */
+ void setSynthToLangMap(SynthToLangMap synthToLangMap);
+
+ // Converts a language code plus optional country code to language description.
+ QString languageCodeToLanguage(const QString &languageCode);
+
+ // QMap of language descriptions to language codes.
+ QMap<QString,QString> m_languageToLanguageCodeMap;
+ // QMap of supported languages indexed by synthesizer.
+ SynthToLangMap m_synthToLangMap;
+ // QMap of synthesizers indexed by language code they support.
+ LangToSynthMap m_langToSynthMap;
+
+private slots:
+ // Based on user's radio button selection, filters choices for language or synthesizer
+ // comboboxes based on what is selected in the other combobox.
+ void applyFilter();
+};
+
+#endif
+
diff --git a/kttsd/kcmkttsmgr/addtalkerwidget.ui b/kttsd/kcmkttsmgr/addtalkerwidget.ui
new file mode 100644
index 0000000..f493138
--- /dev/null
+++ b/kttsd/kcmkttsmgr/addtalkerwidget.ui
@@ -0,0 +1,260 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>AddTalkerWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>AddTalkerWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>469</width>
+ <height>153</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Add Talker</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>buttonGroup2</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KComboBox" row="2" column="1">
+ <property name="name">
+ <cstring>synthesizerSelection</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the speech synthesizer to do the speaking.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>languageSelection</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the language to be spoken. Note that after you configure a Talker, your chosen Language may be overridden by the synthesizer, depending upon the options you choose.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <spacer row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>351</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>synthesizerLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Synthesizer:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>synthesizerSelection</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the speech synthesizer to do the speaking.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="4">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="4">
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>spacer10_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="2" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>showAllLabel</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <underline>1</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Show All</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The radio buttons below determine which box shows all possibilities. The box to the left of the checked button shows all possibilities. The box to the left of the unchecked box only shows those possibilities that match the other box.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Language:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>languageSelection</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the language to be spoken. Note that after you configure a Talker, your chosen Language may be overridden by the synthesizer, depending upon the options you choose.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="3">
+ <property name="name">
+ <cstring>languageRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check to list all the possible languages in the Language box at the left. When a language has been chosen, the Synthesizer box will show only those synthesizers that can speak in the chosen language.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="3">
+ <property name="name">
+ <cstring>synthesizerRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this box to display all the available synthesizers in the Synthesizer box to the left. When a synthesizer is chosen, only the languages that can be spoken by that synthesizer appear in the Language box.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>languageSelection</tabstop>
+ <tabstop>synthesizerSelection</tabstop>
+ <tabstop>languageRadioButton</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/kcmkttsmgr/kcmkttsd.desktop b/kttsd/kcmkttsmgr/kcmkttsd.desktop
new file mode 100644
index 0000000..b54e66e
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsd.desktop
@@ -0,0 +1,142 @@
+[Desktop Entry]
+Type=Application
+Name=Text-to-Speech
+Name[bg]=Синтез на глас
+Name[bs]=Izgovaranje teksta
+Name[ca]=Text a veu
+Name[cs]=Hlasová syntéza
+Name[cy]=Testun-i-Leferydd
+Name[da]=Tekst-til-tale
+Name[de]=Sprachausgabe
+Name[el]=Κείμενο-σε-ομιλία
+Name[es]=Texto a voz
+Name[et]=Tekst kõneks
+Name[eu]=Testutik hizketara
+Name[fa]=متن به گفتار
+Name[fi]=Teksti puheeksi
+Name[fr]=Synthèse vocale
+Name[ga]=Téacs-go-Caint
+Name[gl]=Texto-para-Fala
+Name[he]=טקסט לדיבור
+Name[hu]=Szövegfelolvasó
+Name[is]=Texti-í-tal
+Name[it]=Pronuncia
+Name[ja]=テキスト読み上げ
+Name[ka]=ტექსტი-გახმოვანება
+Name[km]=អត្ថបទ​ដែល​ត្រូវ​និយាយ
+Name[mk]=Текст-во-говор
+Name[ms]=Teks-ke-Tutur
+Name[nb]=Tekst-til-tale
+Name[nds]=Vörleser
+Name[ne]=पाठ वाचक
+Name[nl]=Tekst-tot-spraak
+Name[pa]=ਪਾਠ ਤੋਂ ਬੋਲੀ
+Name[pl]=Odczytywanie tekstu
+Name[pt]=Texto-para-Fala
+Name[pt_BR]=Conversão de texto para fala
+Name[ru]=Синтез речи
+Name[sk]=Text-na-reč
+Name[sl]=Besedilo v govor
+Name[sr]=Текст-у-говор
+Name[sr@Latn]=Tekst-u-govor
+Name[sv]=Text-till-tal
+Name[ta]=உரையில் இருந்து பேச்சுக்கு
+Name[tg]=Таҳлили овоз
+Name[tr]=Metinden Konuşmaya
+Name[uk]=Синтез мовлення з тексту
+Name[vi]=Văn bản sang Tiếng nói
+Name[zh_TW]=文字轉語音
+Comment=Text-to-Speech Control Module
+Comment[bg]=Модул за синтез на глас
+Comment[bs]=Kontrolni modul za izgovaranje teksta
+Comment[ca]=Mòdul de control de text a veu
+Comment[cs]=Modul ovládání hlasové syntézy
+Comment[da]=Kontrolmodul for tekst-til-tale
+Comment[de]=Kontrollmodul für die Sprachausgabe
+Comment[el]=Άρθρωμα ελέγχου κειμένου-σε-ομιλία
+Comment[es]=Modulo de control del sintetizador texto a voz
+Comment[et]=Juhtimiskeskuse teksti kõneks muutmise moodul
+Comment[eu]=Testutik hizketarako modulua
+Comment[fa]=پیمانۀ کنترل متن به گفتار
+Comment[fi]=Teksti puheeksi -hallintamoduuli
+Comment[fr]=Module de configuration de la synthèse vocale
+Comment[ga]=Modúl Rialaithe Téacs-go-Caint
+Comment[gl]=Módulo de Control do Texto-para-Fala
+Comment[he]=מודול מרכז בקרה עבור טקסט לדיבור
+Comment[hu]=A szövegfelolvasó szolgáltatás beállításai
+Comment[is]=Texti-í-tal stjórneining
+Comment[it]=Modulo di controllo di pronuncia
+Comment[ja]=テキスト読み上げ制御モジュール
+Comment[ka]=ტექსტი-სიტყვის მართვის მოდული
+Comment[km]=ម៉ូឌុល​ត្រួតពិនិត្យ​​អត្ថបទ​ដែល​ត្រូវ​និយាយ
+Comment[mk]=Контролен модул за текст-во-говор
+Comment[ms]=Modul Kawalan Teks-ke-Tutur
+Comment[nb]=Styremodul for tekst-til-tale
+Comment[nds]=Kuntrullmoduul för den Vörleser
+Comment[ne]=पाठ वाचक नियन्त्रण मोड्युल
+Comment[nl]=Tekst-tot-spraak configuratiemodule
+Comment[pa]=ਪਾਠ ਤੋਂ ਬੋਲੀ ਕੰਟਰੋਲ ਮੈਡੀਊਲ
+Comment[pl]=Moduł konfiguracji odczytywania tekstu
+Comment[pt]=Módulo de Controlo de Texto-para-Fala
+Comment[pt_BR]=Módulo de Controle de conversão de texto para fala
+Comment[ru]=Настройка синтеза речи
+Comment[sk]=Riadiaci modul text-na-reč
+Comment[sl]=Nadzorni modul besedila v govor
+Comment[sr]=Контролни модул за текст-у-говор
+Comment[sr@Latn]=Kontrolni modul za tekst-u-govor
+Comment[sv]=Text-till-tal inställningsmodul
+Comment[ta]=உரையில் இருந்து பேச்சு கட்டுப்பாட்டு பகுதி
+Comment[tg]=Танзими таҳлили овоз
+Comment[tr]=Metinden Konuşmaya Kontrol Modülü
+Comment[uk]=Модуль керування синтезом мовлення з тексту
+Comment[vi]=Mô đun Điều khiển Văn bản sang Tiếng nói
+Comment[zh_TW]=文字轉語音控制模組
+ServiceTypes=Application,KCModule
+DocPath=kttsd
+NoDisplay=false
+StartupNotify=false
+StartupWMClass=
+Exec=kcmshell kcmkttsd
+Icon=kttsd
+Categories=Qt;KDE;Utility;Accessibility;
+Keywords=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice
+Keywords[bg]=синтез, глас, говор, текст, kttsd, kcmkttsmgr, kttsmgr, tts, ttsd, ktts, text, to, speech, speak, synthesizer, synth, festival, command, freetts, proklam, via, voice
+Keywords[br]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,skrid,da,prezegenn,komz,synthesizer,synth,festival,urzhiad,freetts,proklam,via,mouezh
+Keywords[bs]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,čitanje,izgovaranje
+Keywords[ca]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,a,veu,parla,sintetitzador,síntesi,festival,ordre,freetts,proklam,via,veu
+Keywords[cs]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,mluvit,syntéza,syntetizér,synth,festival,příkaz,freetts,proklam,hlasová,předčítání,čtení
+Keywords[da]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,tekst,til,tale,tal,synthesizer,synth,festival,kommando,freetts,proklam,via,stemme
+Keywords[de]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,Sprachsynthese,Vorlesen,Sprache,Sprachausgabe
+Keywords[el]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,κείμενο,σε,ομιλία,εκφώνηση,synthesizer,synth,festival,εντολή,freetts,proklam,μέσω,φωνή
+Keywords[es]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,texto,a,voz,habla,sintetizador,festival,orden,freetts,proklam,via,voz
+Keywords[et]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,tekst,kõneks,kõne,süntesaator,festival,käsk,freetts,proklam,hääl
+Keywords[eu]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,testua, hizketa,ahoskatu,sintetizadorea,synth,festival,command, freetts,proklam,via,ahotsa
+Keywords[fa]=kttsd،kcmkttsmgr،kttsmgr،tts،ttsd،ktts،متن، به، گفتار، صحبت کردن دهنده، synth، Festival، فرمان، freetts،proklam، از طریق، صدا
+Keywords[fr]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,texte,to,prononcer,énoncer,synthétiseur,synth,festival,command,freetts,proklam,via,voix
+Keywords[ga]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,téacs,go,caint,abair,sintéiseoir,sintéis,festival,ordú,freetts,proklam,via,guth,glór
+Keywords[gl]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,texto,para,fala,falar,sintetizador,sintetizar,festival,comando,freetts,proklam,via,voz
+Keywords[he]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,דיבור,טקסט,מקריא, קול,פסטיבל,מסנטז,סינטי,סינטיזייזר
+Keywords[hu]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,szöveg,hang,beszéd,beszél,szintetizátor,szintetizálás,festival,parancs,freetts,proklam,via,voice
+Keywords[is]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,texti,í,tal,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice
+Keywords[it]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,pronuncia,parlare,sintetizzatore,synth,festival,comando,freetts,proklam,via,voce
+Keywords[mk]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,текст,во,говор,синтисајзер,фестивал,наредба,команда,глас
+Keywords[nb]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,tekst,til,tale,snakke,synthesizer,synth,festival,kommando,freetts,proklam,via,voice
+Keywords[nds]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,Vörleser,vörlesen,Blicksnuut,synth,festival,freetts,proklam,Stimm,Spraakutgaav
+Keywords[nl]=kttsd,tts,ttsd,ktts,text to speech,praten,synthesizer,synth,festival,command,freetts,proklam,via voice,spraakprogramma,geluid,stem,tekst tot spraak,spreken,computerstem
+Keywords[pl]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,tekst,do,mowa,mówienie, synteza,festival,polecenie,głos,mówienie,odczytywanie tekstu
+Keywords[pt]=kttsd,kcmkttsmgr,kttsmgr,tts,TTS,ttsd,ktts,texto,fala,falar,sintetizador,festival,comandar,freetts,proklam,via,voice
+Keywords[pt_BR]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,texto,fala,conversa, sintentizador,ynth,festival,command,freetts,proklam,via,voz
+Keywords[ru]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text-to-speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,голос,речь,синтез,синтез речи
+Keywords[sl]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,besedilo,v,govor,govori,sintetizator,,festival,ukaz,freetts,proklam,preko,glas
+Keywords[sr]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,текст,говор,наредба
+Keywords[sr@Latn]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,tekst,govor,naredba
+Keywords[sv]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,till,tal,läsa,syntes,synt,festival,kommando,freetts,proklam,via,röst
+Keywords[tg]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,овоз,ибора,таҳлили овоз
+Keywords[uk]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,мовлення,синтез,голос,текст,команда,через
+Keywords[vi]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,văn bản,sang,tiếng nói,nói,tổng hợp,tạp,festival,lệnh,freets,proklam,qua,giọng nói
+X-KDE-FactoryName=kttsd
+X-KDE-ParentApp=kcontrol
+X-KDE-SubstituteUID=false
+X-KDE-ModuleType=Library
+X-KDE-Library=kttsd
+Terminal=false
diff --git a/kttsd/kcmkttsmgr/kcmkttsd_testmessage.desktop b/kttsd/kcmkttsmgr/kcmkttsd_testmessage.desktop
new file mode 100644
index 0000000..816bfd7
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsd_testmessage.desktop
@@ -0,0 +1,46 @@
+[Desktop Entry]
+NoDisplay=true
+Name=The text-to-speech system seems to be functioning properly.
+Name[bg]=Системата за синтез на глас изглежда, че функционира нормално.
+Name[ca]=El sistema de text a veu sembla que funciona correctament.
+Name[cs]=Zdá se, že systém hlasové syntézy funguje správně.
+Name[da]=Tekst-til-tale systemet synes at virke rigtigt.
+Name[de]=Die Sprachausgabe scheint ordnungsgemäß zu funktionieren.
+Name[el]=Το σύστημα κειμένου-σε-ομιλία φαίνεται να λειτουργεί κανονικά.
+Name[es]=El sintetizador de texto a voz parece estar funcionando correctamente.
+Name[et]=Teksti kõneks muutmise süsteem paistab korralikult töötavat.
+Name[eu]=Testutik-hizketarako sistemak ongi funtzionatzen duela dirudi.
+Name[fa]=به نظر می‌رسد که سیستم متن به گفتار درست عمل می‌کند.
+Name[fi]=Teksti puheeksi -järjestelmä näyttää toimivan hyvin.
+Name[fr]=Le système de synthèse vocale semble fonctionner correctement.
+Name[ga]=Dealraíonn sé go bhfuil an córas téacs-go-caint ag obair mar is ceart.
+Name[gl]=O sistema de texto-para-fala parece estar a funcionar correctamente.
+Name[he]=נראה כי מערכת הטקסט לדיבור עובדת כהלכה.
+Name[hu]=A szövegfelolvasó rendszer megfelelően működik.
+Name[is]=Texti-í-tal kerfið virðist virka eðlilega.
+Name[it]=Il sistema di pronuncia pare funzionare correttamente.
+Name[ja]=テキスト読み上げシステムは正しく動作しているようです。
+Name[ka]=ტექსტი-გახმოვანება სისტემა როგორც ჩანს სწორად მოქმედებს.
+Name[km]=ប្រព័ន្ធ​អត្ថបទ​ដែល​ត្រូវ​និយាយ​ហាក់ដូចជា​មាន​មុខងារ​ត្រឹមត្រូវ ។
+Name[mk]=Изгледа дека системот за текст-во-говор функционира како што треба.
+Name[ms]=Sistem teks-ke-Tutur berfungsi dengan baik.
+Name[nb]=Tekst-til-tale-systemet ser ut til å virke som det skal.
+Name[nds]=As dat lett funkscheneert de Vörleser as he schall.
+Name[ne]=पाठ वाचक प्रणालीले ठीक रुपमा कार्य गर्ने देखिन्छ
+Name[nl]=Het tekst-tot-spraaksysteem blijkt goed te functioneren.
+Name[pa]=ਇੱਕ ਪਾਠ ਤੋਂ ਬੋਲੀ ਸੰਸਲੇਸ਼ਣ ਸਿਸਟਮ, ਜੋ ਕਿ ਠੀਕ ਤਰਾਂ ਕੰਮ ਕਰਦਾ ਜਾਪਦਾ ਹੈ।
+Name[pl]=System odczytywania tekstu funkcjonuje prawidłowo.
+Name[pt]=O sistema de texto-para-voz parece estar a funcionar correctamente.
+Name[pt_BR]=O sistema de fala do KDE parece estar funcionando corretamente.
+Name[ru]=Система синтеза речи работает нормально.
+Name[sk]=Systém text-na-reč funguje správne.
+Name[sl]=Sistem besedila v govor očitno deluje pravilno.
+Name[sr]=Систем текст-у-говор изгледа да функционише исправно.
+Name[sr@Latn]=Sistem tekst-u-govor izgleda da funkcioniše ispravno.
+Name[sv]=Text till tal-systemet verkar fungera som det ska.
+Name[ta]=உரையில் இருந்து பேச்சு அமைப்பு சரியாக இயங்குகிறது.
+Name[tg]=Системаи таҳлили овоз мӯътадил кор мекунад.
+Name[tr]=Metinden Konuşmaya sistemi düzgün çalışıyor.
+Name[uk]=Система синтезу мовлення з тексту функціонує правильно.
+Name[vi]=Hệ thống văn bản sang tiếng nói có vẻ hoạt động tốt.
+Name[zh_TW]=文字轉語音的系統已正常運作。
diff --git a/kttsd/kcmkttsmgr/kcmkttsmgr.cpp b/kttsd/kcmkttsmgr/kcmkttsmgr.cpp
new file mode 100644
index 0000000..d890446
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsmgr.cpp
@@ -0,0 +1,2713 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KControl module for KTTSD configuration and Job Management
+ -------------------
+ Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández
+ Copyright : (C) 2004-2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Note to programmers. There is a subtle difference between a plugIn name and a
+// synthesizer name. The latter is a translated name, for example, "Festival Interactivo",
+// while the former is alway an English name, example "Festival Interactive".
+
+// C++ includes.
+#include <math.h>
+
+// Qt includes.
+#include <qwidget.h>
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qslider.h>
+#include <qlabel.h>
+#include <qpopupmenu.h>
+#include <qbuttongroup.h>
+
+// KDE includes.
+#include <dcopclient.h>
+#include <klistview.h>
+#include <kparts/componentfactory.h>
+#include <klineedit.h>
+#include <kurlrequester.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <kstandarddirs.h>
+#include <kaboutdata.h>
+#include <kconfig.h>
+#include <knuminput.h>
+#include <kcombobox.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+
+// KTTS includes.
+#include "talkercode.h"
+#include "pluginconf.h"
+#include "filterconf.h"
+#include "testplayer.h"
+#include "player.h"
+#include "selecttalkerdlg.h"
+#include "selectevent.h"
+#include "notify.h"
+#include "utils.h"
+
+// KCMKttsMgr includes.
+#include "kcmkttsmgr.h"
+#include "kcmkttsmgr.moc"
+
+// Some constants.
+// Defaults set when clicking Defaults button.
+const bool embedInSysTrayCheckBoxValue = true;
+const bool showMainWindowOnStartupCheckBoxValue = true;
+
+const bool autostartMgrCheckBoxValue = true;
+const bool autoexitMgrCheckBoxValue = true;
+
+const bool notifyEnableCheckBoxValue = false;
+const bool notifyExcludeEventsWithSoundCheckBoxValue = true;
+
+const bool textPreMsgCheckValue = true;
+const QString textPreMsgValue = i18n("Text interrupted. Message.");
+
+const bool textPreSndCheckValue = false;
+const QString textPreSndValue = "";
+
+const bool textPostMsgCheckValue = true;
+const QString textPostMsgValue = i18n("Resuming text.");
+
+const bool textPostSndCheckValue = false;
+const QString textPostSndValue = "";
+
+const int timeBoxValue = 100;
+
+const bool keepAudioCheckBoxValue = false;
+
+// Make this a plug in.
+typedef KGenericFactory<KCMKttsMgr, QWidget> KCMKttsMgrFactory;
+K_EXPORT_COMPONENT_FACTORY( kcm_kttsd, KCMKttsMgrFactory("kttsd") )
+
+/**
+* Constructor.
+* Makes the list of plug ins.
+* And the languages acording to the plug ins.
+*/
+KCMKttsMgr::KCMKttsMgr(QWidget *parent, const char *name, const QStringList &) :
+ DCOPStub("kttsd", "KSpeech"),
+ DCOPObject("kcmkttsmgr_kspeechsink"),
+ KCModule(KCMKttsMgrFactory::instance(), parent, name)
+{
+ // kdDebug() << "KCMKttsMgr contructor running." << endl;
+
+ // Initialize some variables.
+ m_config = 0;
+ m_jobMgrPart = 0;
+ m_configDlg = 0;
+ m_changed = false;
+ m_suppressConfigChanged = false;
+
+ // Add the KTTS Manager widget
+ QGridLayout *layout = new QGridLayout(this, 0, 0);
+ m_kttsmgrw = new KCMKttsMgrWidget(this, "kttsmgrw");
+ // m_kttsmgrw = new KCMKttsMgrWidget(this);
+ layout->addWidget(m_kttsmgrw, 0, 0);
+
+ // Give buttons icons.
+ // Talkers tab.
+ m_kttsmgrw->higherTalkerPriorityButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("up", KIcon::Small));
+ m_kttsmgrw->lowerTalkerPriorityButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("down", KIcon::Small));
+ m_kttsmgrw->removeTalkerButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("edittrash", KIcon::Small));
+ m_kttsmgrw->configureTalkerButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("configure", KIcon::Small));
+
+ // Filters tab.
+ m_kttsmgrw->higherFilterPriorityButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("up", KIcon::Small));
+ m_kttsmgrw->lowerFilterPriorityButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("down", KIcon::Small));
+ m_kttsmgrw->removeFilterButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("edittrash", KIcon::Small));
+ m_kttsmgrw->configureFilterButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("configure", KIcon::Small));
+
+ // Notify tab.
+ m_kttsmgrw->notifyActionComboBox->clear();
+ for (int ndx = 0; ndx < NotifyAction::count(); ++ndx)
+ m_kttsmgrw->notifyActionComboBox->insertItem( NotifyAction::actionDisplayName( ndx ) );
+ m_kttsmgrw->notifyPresentComboBox->clear();
+ for (int ndx = 0; ndx < NotifyPresent::count(); ++ndx)
+ m_kttsmgrw->notifyPresentComboBox->insertItem( NotifyPresent::presentDisplayName( ndx ) );
+
+ m_kttsmgrw->notifyRemoveButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("edittrash", KIcon::Small));
+ m_kttsmgrw->notifyTestButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("speak", KIcon::Small));
+
+ m_kttsmgrw->sinkComboBox->setEditable(false);
+ m_kttsmgrw->pcmComboBox->setEditable(false);
+
+ // Construct a popup menu for the Sentence Boundary Detector buttons on Filter tab.
+ m_sbdPopmenu = new QPopupMenu( m_kttsmgrw, "SbdPopupMenu" );
+ m_sbdPopmenu->insertItem( i18n("&Edit..."), this, SLOT(slot_configureSbdFilter()), 0, sbdBtnEdit );
+ m_sbdPopmenu->insertItem( KGlobal::iconLoader()->loadIconSet("up", KIcon::Small),
+ i18n("U&p"), this, SLOT(slot_higherSbdFilterPriority()), 0, sbdBtnUp );
+ m_sbdPopmenu->insertItem( KGlobal::iconLoader()->loadIconSet("down", KIcon::Small),
+ i18n("Do&wn"), this, SLOT(slot_lowerSbdFilterPriority()), 0, sbdBtnDown );
+ m_sbdPopmenu->insertItem( i18n("&Add..."), this, SLOT(slot_addSbdFilter()), 0, sbdBtnAdd );
+ m_sbdPopmenu->insertItem( i18n("&Remove"), this, SLOT(slot_removeSbdFilter()), 0, sbdBtnRemove );
+ m_kttsmgrw->sbdButton->setPopup( m_sbdPopmenu );
+
+ // If aRts is available, enable its radio button.
+ // Determine if available by loading its plugin. If it fails, not available.
+ TestPlayer* testPlayer = new TestPlayer();
+ Player* player = testPlayer->createPlayerObject(0);
+ if (player)
+ m_kttsmgrw->artsRadioButton->setEnabled(true);
+ else
+ m_kttsmgrw->artsRadioButton->setEnabled(false);
+ delete player;
+ delete testPlayer;
+
+ // If GStreamer is available, enable its radio button.
+ // Determine if available by loading its plugin. If it fails, not available.
+ testPlayer = new TestPlayer();
+ player = testPlayer->createPlayerObject(1);
+ if (player)
+ {
+ m_kttsmgrw->gstreamerRadioButton->setEnabled(true);
+ m_kttsmgrw->sinkLabel->setEnabled(true);
+ m_kttsmgrw->sinkComboBox->setEnabled(true);
+ QStringList sinkList = player->getPluginList("Sink/Audio");
+ // kdDebug() << "KCMKttsMgr::KCMKttsMgr: GStreamer Sink List = " << sinkList << endl;
+ m_kttsmgrw->sinkComboBox->clear();
+ m_kttsmgrw->sinkComboBox->insertStringList(sinkList);
+ }
+ delete player;
+ delete testPlayer;
+
+ // If ALSA is available, enable its radio button.
+ // Determine if available by loading its plugin. If it fails, not available.
+ testPlayer = new TestPlayer();
+ player = testPlayer->createPlayerObject(2);
+ if (player)
+ {
+ m_kttsmgrw->alsaRadioButton->setEnabled(true);
+ m_kttsmgrw->pcmLabel->setEnabled(true);
+ m_kttsmgrw->pcmComboBox->setEnabled(true);
+ QStringList pcmList = player->getPluginList("");
+ pcmList.append("custom");
+ kdDebug() << "KCMKttsMgr::KCMKttsMgr: ALSA pcmList = " << pcmList << endl;
+ m_kttsmgrw->pcmComboBox->clear();
+ m_kttsmgrw->pcmComboBox->insertStringList(pcmList);
+ }
+ delete player;
+ delete testPlayer;
+
+ // If aKode is available, enable its radio button.
+ // Determine if available by loading its plugin. If it fails, not available.
+ testPlayer = new TestPlayer();
+ player = testPlayer->createPlayerObject(3);
+ if (player)
+ {
+ m_kttsmgrw->akodeRadioButton->setEnabled(true);
+ m_kttsmgrw->akodeSinkLabel->setEnabled(true);
+ m_kttsmgrw->akodeComboBox->setEnabled(true);
+ QStringList pcmList = player->getPluginList("");
+ kdDebug() << "KCMKttsMgr::KCMKttsMgr: aKode Sink List = " << pcmList << endl;
+ m_kttsmgrw->akodeComboBox->clear();
+ m_kttsmgrw->akodeComboBox->insertStringList(pcmList);
+ }
+ delete player;
+ delete testPlayer;
+
+ // Set up Keep Audio Path KURLRequestor.
+ m_kttsmgrw->keepAudioPath->setMode(KFile::Directory);
+ m_kttsmgrw->keepAudioPath->setURL(locateLocal("data", "kttsd/audio/"));
+
+ // Object for the KTTSD configuration.
+ m_config = new KConfig("kttsdrc");
+
+ // Load configuration.
+ load();
+
+ // Connect the signals from the KCMKtssMgrWidget to this class.
+
+ // Talker tab.
+ connect(m_kttsmgrw->addTalkerButton, SIGNAL(clicked()),
+ this, SLOT(slot_addTalker()));
+ connect(m_kttsmgrw->higherTalkerPriorityButton, SIGNAL(clicked()),
+ this, SLOT(slot_higherTalkerPriority()));
+ connect(m_kttsmgrw->lowerTalkerPriorityButton, SIGNAL(clicked()),
+ this, SLOT(slot_lowerTalkerPriority()));
+ connect(m_kttsmgrw->removeTalkerButton, SIGNAL(clicked()),
+ this, SLOT(slot_removeTalker()));
+ connect(m_kttsmgrw->configureTalkerButton, SIGNAL(clicked()),
+ this, SLOT(slot_configureTalker()));
+ connect(m_kttsmgrw->talkersList, SIGNAL(selectionChanged()),
+ this, SLOT(updateTalkerButtons()));
+
+ // Filter tab.
+ connect(m_kttsmgrw->addFilterButton, SIGNAL(clicked()),
+ this, SLOT(slot_addNormalFilter()));
+ connect(m_kttsmgrw->higherFilterPriorityButton, SIGNAL(clicked()),
+ this, SLOT(slot_higherNormalFilterPriority()));
+ connect(m_kttsmgrw->lowerFilterPriorityButton, SIGNAL(clicked()),
+ this, SLOT(slot_lowerNormalFilterPriority()));
+ connect(m_kttsmgrw->removeFilterButton, SIGNAL(clicked()),
+ this, SLOT(slot_removeNormalFilter()));
+ connect(m_kttsmgrw->configureFilterButton, SIGNAL(clicked()),
+ this, SLOT(slot_configureNormalFilter()));
+ connect(m_kttsmgrw->filtersList, SIGNAL(selectionChanged()),
+ this, SLOT(updateFilterButtons()));
+ //connect(m_kttsmgrw->filtersList, SIGNAL(stateChanged()),
+ // this, SLOT(configChanged()));
+ connect(m_kttsmgrw->sbdsList, SIGNAL(selectionChanged()),
+ this, SLOT(updateSbdButtons()));
+
+ // Audio tab.
+ connect(m_kttsmgrw->gstreamerRadioButton, SIGNAL(toggled(bool)),
+ this, SLOT(slotGstreamerRadioButton_toggled(bool)));
+ connect(m_kttsmgrw->alsaRadioButton, SIGNAL(toggled(bool)),
+ this, SLOT(slotAlsaRadioButton_toggled(bool)));
+ connect(m_kttsmgrw->pcmComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotPcmComboBox_activated()));
+ connect(m_kttsmgrw->akodeRadioButton, SIGNAL(toggled(bool)),
+ this, SLOT(slotAkodeRadioButton_toggled(bool)));
+ connect(m_kttsmgrw->timeBox, SIGNAL(valueChanged(int)),
+ this, SLOT(timeBox_valueChanged(int)));
+ connect(m_kttsmgrw->timeSlider, SIGNAL(valueChanged(int)),
+ this, SLOT(timeSlider_valueChanged(int)));
+ connect(m_kttsmgrw->timeBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_kttsmgrw->timeSlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_kttsmgrw->keepAudioCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(keepAudioCheckBox_toggled(bool)));
+ connect(m_kttsmgrw->keepAudioPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+
+ // General tab.
+ connect(m_kttsmgrw->enableKttsdCheckBox, SIGNAL(toggled(bool)),
+ SLOT(enableKttsdToggled(bool)));
+
+ // Notify tab.
+ connect(m_kttsmgrw->notifyEnableCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(slotNotifyEnableCheckBox_toggled(bool)));
+ connect(m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(configChanged()));
+ connect(m_kttsmgrw->notifyAddButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyAddButton_clicked()));
+ connect(m_kttsmgrw->notifyRemoveButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyRemoveButton_clicked()));
+ connect(m_kttsmgrw->notifyClearButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyClearButton_clicked()));
+ connect(m_kttsmgrw->notifyLoadButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyLoadButton_clicked()));
+ connect(m_kttsmgrw->notifySaveButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifySaveButton_clicked()));
+ connect(m_kttsmgrw->notifyListView, SIGNAL(selectionChanged()),
+ this, SLOT(slotNotifyListView_selectionChanged()));
+ connect(m_kttsmgrw->notifyPresentComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotNotifyPresentComboBox_activated(int)));
+ connect(m_kttsmgrw->notifyActionComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotNotifyActionComboBox_activated(int)));
+ connect(m_kttsmgrw->notifyTestButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyTestButton_clicked()));
+ connect(m_kttsmgrw->notifyMsgLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotNotifyMsgLineEdit_textChanged(const QString&)));
+ connect(m_kttsmgrw->notifyTalkerButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyTalkerButton_clicked()));
+
+ // Others.
+ connect(m_kttsmgrw, SIGNAL( configChanged() ),
+ this, SLOT( configChanged() ) );
+ connect(m_kttsmgrw->mainTab, SIGNAL(currentChanged(QWidget*)),
+ this, SLOT(slotTabChanged()));
+
+ // Connect KTTSD DCOP signals to our slots.
+ if (!connectDCOPSignal("kttsd", "KSpeech",
+ "kttsdStarted()",
+ "kttsdStarted()",
+ false)) kdDebug() << "connectDCOPSignal failed" << endl;
+ connectDCOPSignal("kttsd", "KSpeech",
+ "kttsdExiting()",
+ "kttsdExiting()",
+ false);
+
+ // See if KTTSD is already running, and if so, create jobs tab.
+ if (kapp->dcopClient()->isApplicationRegistered("kttsd"))
+ kttsdStarted();
+ else
+ // Start KTTSD if check box is checked.
+ enableKttsdToggled(m_kttsmgrw->enableKttsdCheckBox->isChecked());
+
+ // Switch to Talkers tab if none configured,
+ // otherwise switch to Jobs tab if it is active.
+ if (m_kttsmgrw->talkersList->childCount() == 0)
+ m_kttsmgrw->mainTab->setCurrentPage(wpTalkers);
+ else if (m_kttsmgrw->enableKttsdCheckBox->isChecked())
+ m_kttsmgrw->mainTab->setCurrentPage(wpJobs);
+}
+
+/**
+* Destructor.
+*/
+KCMKttsMgr::~KCMKttsMgr(){
+ // kdDebug() << "KCMKttsMgr::~KCMKttsMgr: Running" << endl;
+ delete m_config;
+}
+
+/**
+* This method is invoked whenever the module should read its
+* configuration (most of the times from a config file) and update the
+* user interface. This happens when the user clicks the "Reset" button in
+* the control center, to undo all of his changes and restore the currently
+* valid settings. NOTE that this is not called after the modules is loaded,
+* so you probably want to call this method in the constructor.
+*/
+void KCMKttsMgr::load()
+{
+ // kdDebug() << "KCMKttsMgr::load: Running" << endl;
+
+ m_changed = false;
+ // Don't emit changed() signal while loading.
+ m_suppressConfigChanged = true;
+
+ // Set the group general for the configuration of kttsd itself (no plug ins)
+ m_config->setGroup("General");
+
+ // Load the configuration of the text interruption messages and sound
+ m_kttsmgrw->textPreMsgCheck->setChecked(m_config->readBoolEntry("TextPreMsgEnabled", textPreMsgCheckValue));
+ m_kttsmgrw->textPreMsg->setText(m_config->readEntry("TextPreMsg", textPreMsgValue));
+ m_kttsmgrw->textPreMsg->setEnabled(m_kttsmgrw->textPreMsgCheck->isChecked());
+
+ m_kttsmgrw->textPreSndCheck->setChecked(m_config->readBoolEntry("TextPreSndEnabled", textPreSndCheckValue));
+ m_kttsmgrw->textPreSnd->setURL(m_config->readEntry("TextPreSnd", textPreSndValue));
+ m_kttsmgrw->textPreSnd->setEnabled(m_kttsmgrw->textPreSndCheck->isChecked());
+
+ m_kttsmgrw->textPostMsgCheck->setChecked(m_config->readBoolEntry("TextPostMsgEnabled", textPostMsgCheckValue));
+ m_kttsmgrw->textPostMsg->setText(m_config->readEntry("TextPostMsg", textPostMsgValue));
+ m_kttsmgrw->textPostMsg->setEnabled(m_kttsmgrw->textPostMsgCheck->isChecked());
+
+ m_kttsmgrw->textPostSndCheck->setChecked(m_config->readBoolEntry("TextPostSndEnabled", textPostSndCheckValue));
+ m_kttsmgrw->textPostSnd->setURL(m_config->readEntry("TextPostSnd", textPostSndValue));
+ m_kttsmgrw->textPostSnd->setEnabled(m_kttsmgrw->textPostSndCheck->isChecked());
+
+ // Overall settings.
+ m_kttsmgrw->embedInSysTrayCheckBox->setChecked(m_config->readBoolEntry("EmbedInSysTray",
+ m_kttsmgrw->embedInSysTrayCheckBox->isChecked()));
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->setChecked(m_config->readBoolEntry(
+ "ShowMainWindowOnStartup", m_kttsmgrw->showMainWindowOnStartupCheckBox->isChecked()));
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->setEnabled(
+ m_kttsmgrw->embedInSysTrayCheckBox->isChecked());
+
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(m_config->readBoolEntry("EnableKttsd",
+ m_kttsmgrw->enableKttsdCheckBox->isChecked()));
+
+ m_kttsmgrw->autostartMgrCheckBox->setChecked(m_config->readBoolEntry("AutoStartManager", true));
+ m_kttsmgrw->autoexitMgrCheckBox->setChecked(m_config->readBoolEntry("AutoExitManager", true));
+
+ // Notification settings.
+ m_kttsmgrw->notifyEnableCheckBox->setChecked(m_config->readBoolEntry("Notify",
+ m_kttsmgrw->notifyEnableCheckBox->isChecked()));
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->setChecked(
+ m_config->readBoolEntry("ExcludeEventsWithSound",
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->isChecked()));
+ slotNotifyClearButton_clicked();
+ loadNotifyEventsFromFile( locateLocal("config", "kttsd_notifyevents.xml"), true );
+ slotNotifyEnableCheckBox_toggled( m_kttsmgrw->notifyEnableCheckBox->isChecked() );
+ // Auto-expand and position on the Default item.
+ QListViewItem* item = m_kttsmgrw->notifyListView->findItem( "default", nlvcEventSrc );
+ if ( item )
+ if ( item->childCount() > 0 ) item = item->firstChild();
+ if ( item ) m_kttsmgrw->notifyListView->ensureItemVisible( item );
+
+ // Audio Output.
+ int audioOutputMethod = 0;
+ if (m_kttsmgrw->gstreamerRadioButton->isChecked()) audioOutputMethod = 1;
+ if (m_kttsmgrw->alsaRadioButton->isChecked()) audioOutputMethod = 2;
+ if (m_kttsmgrw->akodeRadioButton->isChecked()) audioOutputMethod = 3;
+ audioOutputMethod = m_config->readNumEntry("AudioOutputMethod", audioOutputMethod);
+ switch (audioOutputMethod)
+ {
+ case 0:
+ m_kttsmgrw->artsRadioButton->setChecked(true);
+ break;
+ case 1:
+ m_kttsmgrw->gstreamerRadioButton->setChecked(true);
+ break;
+ case 2:
+ m_kttsmgrw->alsaRadioButton->setChecked(true);
+ break;
+ case 3:
+ m_kttsmgrw->akodeRadioButton->setChecked(true);
+ break;
+ }
+ m_kttsmgrw->timeBox->setValue(m_config->readNumEntry("AudioStretchFactor", timeBoxValue));
+ timeBox_valueChanged(m_kttsmgrw->timeBox->value());
+ m_kttsmgrw->keepAudioCheckBox->setChecked(
+ m_config->readBoolEntry("KeepAudio", m_kttsmgrw->keepAudioCheckBox->isChecked()));
+ m_kttsmgrw->keepAudioPath->setURL(
+ m_config->readEntry("KeepAudioPath",
+ m_kttsmgrw->keepAudioPath->url()));
+ m_kttsmgrw->keepAudioPath->setEnabled(m_kttsmgrw->keepAudioCheckBox->isChecked());
+
+ // Last plugin ID. Used to generate a new ID for an added talker.
+ m_lastTalkerID = 0;
+
+ // Last filter ID. Used to generate a new ID for an added filter.
+ m_lastFilterID = 0;
+
+ // Dictionary mapping languages to language codes.
+ m_languagesToCodes.clear();
+
+ // Load existing Talkers into the listview.
+ m_kttsmgrw->talkersList->clear();
+ m_kttsmgrw->talkersList->setSortColumn(-1);
+ QStringList talkerIDsList = m_config->readListEntry("TalkerIDs", ',');
+ if (!talkerIDsList.isEmpty())
+ {
+ QListViewItem* talkerItem = 0;
+ QStringList::ConstIterator itEnd = talkerIDsList.constEnd();
+ for (QStringList::ConstIterator it = talkerIDsList.constBegin(); it != itEnd; ++it)
+ {
+ QString talkerID = *it;
+ // kdDebug() << "KCMKttsMgr::load: talkerID = " << talkerID << endl;
+ m_config->setGroup(QString("Talker_") + talkerID);
+ QString talkerCode = m_config->readEntry("TalkerCode");
+ QString fullLanguageCode;
+ talkerCode = TalkerCode::normalizeTalkerCode(talkerCode, fullLanguageCode);
+ QString language = TalkerCode::languageCodeToLanguage(fullLanguageCode);
+ QString desktopEntryName = m_config->readEntry("DesktopEntryName", QString::null);
+ // If a DesktopEntryName is not in the config file, it was configured before
+ // we started using them, when we stored translated plugin names instead.
+ // Try to convert the translated plugin name to a DesktopEntryName.
+ // DesktopEntryNames are better because user can change their desktop language
+ // and DesktopEntryName won't change.
+ QString synthName;
+ if (desktopEntryName.isEmpty())
+ {
+ synthName = m_config->readEntry("PlugIn", QString::null);
+ // See if the translated name will untranslate. If not, well, sorry.
+ desktopEntryName = TalkerCode::TalkerNameToDesktopEntryName(synthName);
+ // Record the DesktopEntryName from now on.
+ if (!desktopEntryName.isEmpty()) m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ }
+ synthName = TalkerCode::TalkerDesktopEntryNameToName(desktopEntryName);
+ if (!synthName.isEmpty())
+ {
+ // kdDebug() << "KCMKttsMgr::load: talkerCode = " << talkerCode << endl;
+ if (talkerItem)
+ talkerItem = new KListViewItem(m_kttsmgrw->talkersList, talkerItem,
+ talkerID, language, synthName);
+ else
+ talkerItem = new KListViewItem(m_kttsmgrw->talkersList,
+ talkerID, language, synthName);
+ updateTalkerItem(talkerItem, talkerCode);
+ m_languagesToCodes[language] = fullLanguageCode;
+ if (talkerID.toInt() > m_lastTalkerID) m_lastTalkerID = talkerID.toInt();
+ }
+ }
+ }
+
+ // Query for all the KCMKTTSD SynthPlugins and store the list in offers.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/SynthPlugin");
+
+ // Iterate thru the possible plug ins getting their language support codes.
+ for(unsigned int i=0; i < offers.count() ; ++i)
+ {
+ QString synthName = offers[i]->name();
+ QStringList languageCodes = offers[i]->property("X-KDE-Languages").toStringList();
+ // Add language codes to the language-to-language code map.
+ QStringList::ConstIterator endLanguages(languageCodes.constEnd());
+ for( QStringList::ConstIterator it = languageCodes.constBegin(); it != endLanguages; ++it )
+ {
+ QString language = TalkerCode::languageCodeToLanguage(*it);
+ m_languagesToCodes[language] = *it;
+ }
+
+ // All plugins support "Other".
+ // TODO: Eventually, this should not be necessary, since all plugins will know
+ // the languages they support and report them in call to getSupportedLanguages().
+ if (!languageCodes.contains("other")) languageCodes.append("other");
+
+ // Add supported language codes to synthesizer-to-language map.
+ m_synthToLangMap[synthName] = languageCodes;
+ }
+
+ // Add "Other" language.
+ m_languagesToCodes[i18n("Other")] = "other";
+
+ // Load Filters.
+ QListViewItem* filterItem = 0;
+ m_kttsmgrw->filtersList->clear();
+ m_kttsmgrw->sbdsList->clear();
+ m_kttsmgrw->filtersList->setSortColumn(-1);
+ m_kttsmgrw->sbdsList->setSortColumn(-1);
+ m_config->setGroup("General");
+ QStringList filterIDsList = m_config->readListEntry("FilterIDs", ',');
+ // kdDebug() << "KCMKttsMgr::load: FilterIDs = " << filterIDsList << endl;
+ if (!filterIDsList.isEmpty())
+ {
+ QStringList::ConstIterator itEnd = filterIDsList.constEnd();
+ for (QStringList::ConstIterator it = filterIDsList.constBegin(); it != itEnd; ++it)
+ {
+ QString filterID = *it;
+ // kdDebug() << "KCMKttsMgr::load: filterID = " << filterID << endl;
+ m_config->setGroup("Filter_" + filterID);
+ QString desktopEntryName = m_config->readEntry("DesktopEntryName", QString::null);
+ // If a DesktopEntryName is not in the config file, it was configured before
+ // we started using them, when we stored translated plugin names instead.
+ // Try to convert the translated plugin name to a DesktopEntryName.
+ // DesktopEntryNames are better because user can change their desktop language
+ // and DesktopEntryName won't change.
+ QString filterPlugInName;
+ if (desktopEntryName.isEmpty())
+ {
+ filterPlugInName = m_config->readEntry("PlugInName", QString::null);
+ // See if the translated name will untranslate. If not, well, sorry.
+ desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ // Record the DesktopEntryName from now on.
+ if (!desktopEntryName.isEmpty()) m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ }
+ filterPlugInName = FilterDesktopEntryNameToName(desktopEntryName);
+ if (!filterPlugInName.isEmpty())
+ {
+ QString userFilterName = m_config->readEntry("UserFilterName", filterPlugInName);
+ bool multiInstance = m_config->readBoolEntry("MultiInstance", false);
+ // Determine if this filter is a Sentence Boundary Detector (SBD).
+ bool isSbd = m_config->readBoolEntry("IsSBD", false);
+ bool checked = m_config->readBoolEntry("Enabled", false);
+ if (isSbd)
+ {
+ filterItem = m_kttsmgrw->sbdsList->lastChild();
+ if (!filterItem)
+ filterItem = new KListViewItem(m_kttsmgrw->sbdsList,
+ userFilterName, filterID, filterPlugInName);
+ else
+ filterItem = new KListViewItem(m_kttsmgrw->sbdsList, filterItem,
+ userFilterName, filterID, filterPlugInName);
+ } else {
+ filterItem = m_kttsmgrw->filtersList->lastChild();
+ if (!filterItem)
+ filterItem = new KttsCheckListItem(m_kttsmgrw->filtersList,
+ userFilterName, QCheckListItem::CheckBox, this);
+ else
+ filterItem = new KttsCheckListItem(m_kttsmgrw->filtersList, filterItem,
+ userFilterName, QCheckListItem::CheckBox, this);
+ dynamic_cast<QCheckListItem*>(filterItem)->setOn(checked);
+ }
+ filterItem->setText(flvcFilterID, filterID);
+ filterItem->setText(flvcPlugInName, filterPlugInName);
+ if (multiInstance)
+ filterItem->setText(flvcMultiInstance, "T");
+ else
+ filterItem->setText(flvcMultiInstance, "F");
+ if (filterID.toInt() > m_lastFilterID) m_lastFilterID = filterID.toInt();
+ }
+ }
+ }
+
+ // Add at least one unchecked instance of each available filter plugin if there is
+ // not already at least one instance and the filter can autoconfig itself.
+ offers = KTrader::self()->query("KTTSD/FilterPlugin");
+ for (unsigned int i=0; i < offers.count() ; ++i)
+ {
+ QString filterPlugInName = offers[i]->name();
+ QString desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ if (!desktopEntryName.isEmpty() && (countFilterPlugins(filterPlugInName) == 0))
+ {
+ // Must load plugin to determine if it supports multiple instances
+ // and to see if it can autoconfigure itself.
+ KttsFilterConf* filterPlugIn = loadFilterPlugin(desktopEntryName);
+ if (filterPlugIn)
+ {
+ ++m_lastFilterID;
+ QString filterID = QString::number(m_lastFilterID);
+ QString groupName = "Filter_" + filterID;
+ filterPlugIn->load(m_config, groupName);
+ QString userFilterName = filterPlugIn->userPlugInName();
+ if (!userFilterName.isEmpty())
+ {
+ kdDebug() << "KCMKttsMgr::load: auto-configuring filter " << userFilterName << endl;
+ // Determine if plugin is an SBD filter.
+ bool multiInstance = filterPlugIn->supportsMultiInstance();
+ bool isSbd = filterPlugIn->isSBD();
+ if (isSbd)
+ {
+ filterItem = m_kttsmgrw->sbdsList->lastChild();
+ if (!filterItem)
+ filterItem = new KListViewItem(m_kttsmgrw->sbdsList,
+ userFilterName, filterID, filterPlugInName);
+ else
+ filterItem = new KListViewItem(m_kttsmgrw->sbdsList, filterItem,
+ userFilterName, filterID, filterPlugInName);
+ } else {
+ filterItem = m_kttsmgrw->filtersList->lastChild();
+ if (!filterItem)
+ filterItem = new KttsCheckListItem(m_kttsmgrw->filtersList,
+ userFilterName, QCheckListItem::CheckBox, this);
+ else
+ filterItem = new KttsCheckListItem(m_kttsmgrw->filtersList, filterItem,
+ userFilterName, QCheckListItem::CheckBox, this);
+ dynamic_cast<QCheckListItem*>(filterItem)->setOn(false);
+ }
+ filterItem->setText(flvcFilterID, filterID);
+ filterItem->setText(flvcPlugInName, filterPlugInName);
+ if (multiInstance)
+ filterItem->setText(flvcMultiInstance, "T");
+ else
+ filterItem->setText(flvcMultiInstance, "F");
+ m_config->setGroup(groupName);
+ filterPlugIn->save(m_config, groupName);
+ m_config->setGroup(groupName);
+ m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ m_config->writeEntry("UserFilterName", userFilterName);
+ m_config->writeEntry("Enabled", isSbd);
+ m_config->writeEntry("MultiInstance", multiInstance);
+ m_config->writeEntry("IsSBD", isSbd);
+ filterIDsList.append(filterID);
+ } else m_lastFilterID--;
+ } else
+ kdDebug() << "KCMKttsMgr::load: Unable to load filter plugin " << filterPlugInName
+ << " DesktopEntryName " << desktopEntryName << endl;
+ delete filterPlugIn;
+ }
+ }
+ // Rewrite list of FilterIDs in case we added any.
+ QString filterIDs = filterIDsList.join(",");
+ m_config->setGroup("General");
+ m_config->writeEntry("FilterIDs", filterIDs);
+ m_config->sync();
+
+ // Uncheck and disable KTTSD checkbox if no Talkers are configured.
+ if (m_kttsmgrw->talkersList->childCount() == 0)
+ {
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->enableKttsdCheckBox->setEnabled(false);
+ enableKttsdToggled(false);
+ }
+
+ // Enable ShowMainWindowOnStartup checkbox based on EmbedInSysTray checkbox.
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->setEnabled(
+ m_kttsmgrw->embedInSysTrayCheckBox->isChecked());
+
+ // GStreamer settings.
+ m_config->setGroup("GStreamerPlayer");
+ KttsUtils::setCbItemFromText(m_kttsmgrw->sinkComboBox, m_config->readEntry("SinkName", "osssink"));
+
+ // ALSA settings.
+ m_config->setGroup("ALSAPlayer");
+ KttsUtils::setCbItemFromText(m_kttsmgrw->pcmComboBox, m_config->readEntry("PcmName", "default"));
+ m_kttsmgrw->pcmCustom->setText(m_config->readEntry("CustomPcmName", ""));
+
+ // aKode settings.
+ m_config->setGroup("aKodePlayer");
+ KttsUtils::setCbItemFromText(m_kttsmgrw->akodeComboBox, m_config->readEntry("SinkName", "auto"));
+
+ // Update controls based on new states.
+ slotNotifyListView_selectionChanged();
+ updateTalkerButtons();
+ updateFilterButtons();
+ updateSbdButtons();
+ slotGstreamerRadioButton_toggled(m_kttsmgrw->gstreamerRadioButton->isChecked());
+ slotAlsaRadioButton_toggled(m_kttsmgrw->alsaRadioButton->isChecked());
+ slotAkodeRadioButton_toggled(m_kttsmgrw->akodeRadioButton->isChecked());
+
+ m_changed = false;
+ m_suppressConfigChanged = false;
+}
+
+/**
+* This function gets called when the user wants to save the settings in
+* the user interface, updating the config files or wherever the
+* configuration is stored. The method is called when the user clicks "Apply"
+* or "Ok".
+*/
+void KCMKttsMgr::save()
+{
+ // kdDebug() << "KCMKttsMgr::save: Running" << endl;
+ m_changed = false;
+
+ // Clean up config.
+ m_config->deleteGroup("General");
+
+ // Set the group general for the configuration of kttsd itself (no plug ins)
+ m_config->setGroup("General");
+
+ // Set text interrumption messages and paths
+ m_config->writeEntry("TextPreMsgEnabled", m_kttsmgrw->textPreMsgCheck->isChecked());
+ m_config->writeEntry("TextPreMsg", m_kttsmgrw->textPreMsg->text());
+
+ m_config->writeEntry("TextPreSndEnabled", m_kttsmgrw->textPreSndCheck->isChecked());
+ m_config->writeEntry("TextPreSnd", PlugInConf::realFilePath(m_kttsmgrw->textPreSnd->url()));
+
+ m_config->writeEntry("TextPostMsgEnabled", m_kttsmgrw->textPostMsgCheck->isChecked());
+ m_config->writeEntry("TextPostMsg", m_kttsmgrw->textPostMsg->text());
+
+ m_config->writeEntry("TextPostSndEnabled", m_kttsmgrw->textPostSndCheck->isChecked());
+ m_config->writeEntry("TextPostSnd", PlugInConf::realFilePath(m_kttsmgrw->textPostSnd->url()));
+
+ // Overall settings.
+ m_config->writeEntry("EmbedInSysTray", m_kttsmgrw->embedInSysTrayCheckBox->isChecked());
+ m_config->writeEntry("ShowMainWindowOnStartup",
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->isChecked());
+ m_config->writeEntry("AutoStartManager", m_kttsmgrw->autostartMgrCheckBox->isChecked());
+ m_config->writeEntry("AutoExitManager", m_kttsmgrw->autoexitMgrCheckBox->isChecked());
+
+ // Uncheck and disable KTTSD checkbox if no Talkers are configured.
+ // Enable checkbox if at least one Talker is configured.
+ bool enableKttsdWasToggled = false;
+ if (m_kttsmgrw->talkersList->childCount() == 0)
+ {
+ enableKttsdWasToggled = m_kttsmgrw->enableKttsdCheckBox->isChecked();
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->enableKttsdCheckBox->setEnabled(false);
+ // Might as well zero LastTalkerID as well.
+ m_lastTalkerID = 0;
+ }
+ else
+ m_kttsmgrw->enableKttsdCheckBox->setEnabled(true);
+
+ m_config->writeEntry("EnableKttsd", m_kttsmgrw->enableKttsdCheckBox->isChecked());
+
+ // Notification settings.
+ m_config->writeEntry("Notify", m_kttsmgrw->notifyEnableCheckBox->isChecked());
+ m_config->writeEntry("ExcludeEventsWithSound",
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->isChecked());
+ saveNotifyEventsToFile( locateLocal("config", "kttsd_notifyevents.xml") );
+
+ // Audio Output.
+ int audioOutputMethod = 0;
+ if (m_kttsmgrw->gstreamerRadioButton->isChecked()) audioOutputMethod = 1;
+ if (m_kttsmgrw->alsaRadioButton->isChecked()) audioOutputMethod = 2;
+ if (m_kttsmgrw->akodeRadioButton->isChecked()) audioOutputMethod = 3;
+ m_config->writeEntry("AudioOutputMethod", audioOutputMethod);
+ m_config->writeEntry("AudioStretchFactor", m_kttsmgrw->timeBox->value());
+ m_config->writeEntry("KeepAudio", m_kttsmgrw->keepAudioCheckBox->isChecked());
+ m_config->writeEntry("KeepAudioPath", m_kttsmgrw->keepAudioPath->url());
+
+ // Get ordered list of all talker IDs.
+ QStringList talkerIDsList;
+ QListViewItem* talkerItem = m_kttsmgrw->talkersList->firstChild();
+ while (talkerItem)
+ {
+ QListViewItem* nextTalkerItem = talkerItem->itemBelow();
+ QString talkerID = talkerItem->text(tlvcTalkerID);
+ talkerIDsList.append(talkerID);
+ talkerItem = nextTalkerItem;
+ }
+ QString talkerIDs = talkerIDsList.join(",");
+ m_config->writeEntry("TalkerIDs", talkerIDs);
+
+ // Erase obsolete Talker_nn sections.
+ QStringList groupList = m_config->groupList();
+ int groupListCount = groupList.count();
+ for (int groupNdx = 0; groupNdx < groupListCount; ++groupNdx)
+ {
+ QString groupName = groupList[groupNdx];
+ if (groupName.left(7) == "Talker_")
+ {
+ QString groupTalkerID = groupName.mid(7);
+ if (!talkerIDsList.contains(groupTalkerID)) m_config->deleteGroup(groupName);
+ }
+ }
+
+ // Get ordered list of all filter IDs. Record enabled state of each filter.
+ QStringList filterIDsList;
+ QListViewItem* filterItem = m_kttsmgrw->filtersList->firstChild();
+ while (filterItem)
+ {
+ QListViewItem* nextFilterItem = filterItem->itemBelow();
+ QString filterID = filterItem->text(flvcFilterID);
+ filterIDsList.append(filterID);
+ bool checked = dynamic_cast<QCheckListItem*>(filterItem)->isOn();
+ m_config->setGroup("Filter_" + filterID);
+ m_config->writeEntry("Enabled", checked);
+ m_config->writeEntry("IsSBD", false);
+ filterItem = nextFilterItem;
+ }
+ QListViewItem* sbdItem = m_kttsmgrw->sbdsList->firstChild();
+ while (sbdItem)
+ {
+ QListViewItem* nextSbdItem = sbdItem->itemBelow();
+ QString filterID = sbdItem->text(slvcFilterID);
+ filterIDsList.append(filterID);
+ m_config->setGroup("Filter_" + filterID);
+ m_config->writeEntry("Enabled", true);
+ m_config->writeEntry("IsSBD", true);
+ sbdItem = nextSbdItem;
+ }
+ QString filterIDs = filterIDsList.join(",");
+ m_config->setGroup("General");
+ m_config->writeEntry("FilterIDs", filterIDs);
+
+ // Erase obsolete Filter_nn sections.
+ for (int groupNdx = 0; groupNdx < groupListCount; ++groupNdx)
+ {
+ QString groupName = groupList[groupNdx];
+ if (groupName.left(7) == "Filter_")
+ {
+ QString groupFilterID = groupName.mid(7);
+ if (!filterIDsList.contains(groupFilterID)) m_config->deleteGroup(groupName);
+ }
+ }
+
+ // GStreamer settings.
+ m_config->setGroup("GStreamerPlayer");
+ m_config->writeEntry("SinkName", m_kttsmgrw->sinkComboBox->currentText());
+
+ // ALSA settings.
+ m_config->setGroup("ALSAPlayer");
+ m_config->writeEntry("PcmName", m_kttsmgrw->pcmComboBox->currentText());
+ m_config->writeEntry("CustomPcmName", m_kttsmgrw->pcmCustom->text());
+
+ // aKode settings.
+ m_config->setGroup("aKodePlayer");
+ m_config->writeEntry("SinkName", m_kttsmgrw->akodeComboBox->currentText());
+
+ m_config->sync();
+
+ // If we automatically unchecked the Enable KTTSD checkbox, stop KTTSD.
+ if (enableKttsdWasToggled)
+ enableKttsdToggled(false);
+ else
+ {
+ // If KTTSD is running, reinitialize it.
+ DCOPClient *client = kapp->dcopClient();
+ bool kttsdRunning = (client->isApplicationRegistered("kttsd"));
+ if (kttsdRunning)
+ {
+ kdDebug() << "Restarting KTTSD" << endl;
+ QByteArray data;
+ client->send("kttsd", "KSpeech", "reinit()", data);
+ }
+ }
+}
+
+void KCMKttsMgr::slotTabChanged()
+{
+ setButtons(buttons());
+ int currentPageIndex = m_kttsmgrw->mainTab->currentPageIndex();
+ if (currentPageIndex == wpJobs)
+ {
+ if (m_changed)
+ {
+ KMessageBox::information(m_kttsmgrw,
+ i18n("You have made changes to the configuration but have not saved them yet. "
+ "Click Apply to save the changes or Cancel to abandon the changes."));
+ }
+ }
+}
+
+/**
+* This function is called to set the settings in the module to sensible
+* default values. It gets called when hitting the "Default" button. The
+* default values should probably be the same as the ones the application
+* uses when started without a config file.
+*/
+void KCMKttsMgr::defaults() {
+ // kdDebug() << "Running: KCMKttsMgr::defaults: Running"<< endl;
+
+ int currentPageIndex = m_kttsmgrw->mainTab->currentPageIndex();
+ bool changed = false;
+ switch (currentPageIndex)
+ {
+ case wpGeneral:
+ if (m_kttsmgrw->embedInSysTrayCheckBox->isChecked() != embedInSysTrayCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->embedInSysTrayCheckBox->setChecked(embedInSysTrayCheckBoxValue);
+ }
+ if (m_kttsmgrw->showMainWindowOnStartupCheckBox->isChecked() !=
+ showMainWindowOnStartupCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->setChecked(
+ showMainWindowOnStartupCheckBoxValue);
+ }
+ if (m_kttsmgrw->autostartMgrCheckBox->isChecked() != autostartMgrCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->autostartMgrCheckBox->setChecked(
+ autostartMgrCheckBoxValue);
+ }
+ if (m_kttsmgrw->autoexitMgrCheckBox->isChecked() != autoexitMgrCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->autoexitMgrCheckBox->setChecked(
+ autoexitMgrCheckBoxValue);
+ }
+ break;
+
+ case wpNotify:
+ if (m_kttsmgrw->notifyEnableCheckBox->isChecked() != notifyEnableCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->notifyEnableCheckBox->setChecked(notifyEnableCheckBoxValue);
+ m_kttsmgrw->notifyGroup->setChecked( notifyEnableCheckBoxValue );
+ }
+ if (m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->isChecked() !=
+ notifyExcludeEventsWithSoundCheckBoxValue )
+ {
+ changed = true;
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->setChecked(
+ notifyExcludeEventsWithSoundCheckBoxValue );
+ }
+ break;
+
+ case wpInterruption:
+ if (m_kttsmgrw->textPreMsgCheck->isChecked() != textPreMsgCheckValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPreMsgCheck->setChecked(textPreMsgCheckValue);
+ }
+ if (m_kttsmgrw->textPreMsg->text() != i18n(textPreMsgValue.utf8()))
+ {
+ changed = true;
+ m_kttsmgrw->textPreMsg->setText(i18n(textPreMsgValue.utf8()));
+ }
+ if (m_kttsmgrw->textPreSndCheck->isChecked() != textPreSndCheckValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPreSndCheck->setChecked(textPreSndCheckValue);
+ }
+ if (m_kttsmgrw->textPreSnd->url() != textPreSndValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPreSnd->setURL(textPreSndValue);
+ }
+ if (m_kttsmgrw->textPostMsgCheck->isChecked() != textPostMsgCheckValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPostMsgCheck->setChecked(textPostMsgCheckValue);
+ }
+ if (m_kttsmgrw->textPostMsg->text() != i18n(textPostMsgValue.utf8()))
+ {
+ changed = true;
+ m_kttsmgrw->textPostMsg->setText(i18n(textPostMsgValue.utf8()));
+ }
+ if (m_kttsmgrw->textPostSndCheck->isChecked() != textPostSndCheckValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPostSndCheck->setChecked(textPostSndCheckValue);
+ }
+ if (m_kttsmgrw->textPostSnd->url() != textPostSndValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPostSnd->setURL(textPostSndValue);
+ }
+ break;
+
+ case wpAudio:
+ if (!m_kttsmgrw->artsRadioButton->isChecked())
+ {
+ changed = true;
+ m_kttsmgrw->artsRadioButton->setChecked(true);
+ }
+ if (m_kttsmgrw->timeBox->value() != timeBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->timeBox->setValue(timeBoxValue);
+ }
+ if (m_kttsmgrw->keepAudioCheckBox->isChecked() !=
+ keepAudioCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->keepAudioCheckBox->setChecked(keepAudioCheckBoxValue);
+ }
+ if (m_kttsmgrw->keepAudioPath->url() != locateLocal("data", "kttsd/audio/"))
+ {
+ changed = true;
+ m_kttsmgrw->keepAudioPath->setURL(locateLocal("data", "kttsd/audio/"));
+ }
+ m_kttsmgrw->keepAudioPath->setEnabled(m_kttsmgrw->keepAudioCheckBox->isEnabled());
+ }
+ if (changed) configChanged();
+}
+
+/**
+* This is a static method which gets called to realize the modules settings
+* during the startup of KDE. NOTE that most modules do not implement this
+* method, but modules like the keyboard and mouse modules, which directly
+* interact with the X-server, need this method. As this method is static,
+* it can avoid to create an instance of the user interface, which is often
+* not needed in this case.
+*/
+void KCMKttsMgr::init(){
+ // kdDebug() << "KCMKttsMgr::init: Running" << endl;
+}
+
+/**
+* The control center calls this function to decide which buttons should
+* be displayed. For example, it does not make sense to display an "Apply"
+* button for one of the information modules. The value returned can be set by
+* modules using setButtons.
+*/
+int KCMKttsMgr::buttons() {
+ // kdDebug() << "KCMKttsMgr::buttons: Running"<< endl;
+ return KCModule::Ok|KCModule::Apply|KCModule::Help|KCModule::Default;
+}
+
+/**
+* This function returns the small quickhelp.
+* That is displayed in the sidebar in the KControl
+*/
+QString KCMKttsMgr::quickHelp() const{
+ // kdDebug() << "KCMKttsMgr::quickHelp: Running"<< endl;
+ return i18n(
+ "<h1>Text-to-Speech</h1>"
+ "<p>This is the configuration for the text-to-speech dcop service</p>"
+ "<p>This allows other applications to access text-to-speech resources</p>"
+ "<p>Be sure to configure a default language for the language you are using as this will be the language used by most of the applications</p>");
+}
+
+const KAboutData* KCMKttsMgr::aboutData() const{
+ KAboutData *about =
+ new KAboutData(I18N_NOOP("kttsd"), I18N_NOOP("KCMKttsMgr"),
+ 0, 0, KAboutData::License_GPL,
+ I18N_NOOP("(c) 2002, José Pablo Ezequiel Fernández"));
+
+ about->addAuthor("José Pablo Ezequiel Fernández", I18N_NOOP("Author") , "pupeno@kde.org");
+ about->addAuthor("Gary Cramblitt", I18N_NOOP("Maintainer") , "garycramblitt@comcast.net");
+ about->addAuthor("Olaf Schmidt", I18N_NOOP("Contributor"), "ojschmidt@kde.org");
+ about->addAuthor("Paul Giannaros", I18N_NOOP("Contributor"), "ceruleanblaze@gmail.com");
+
+ return about;
+}
+
+/**
+* Loads the configuration plug in for a named talker plug in and type.
+* @param name DesktopEntryName of the Synthesizer.
+* @return Pointer to the configuration plugin for the Talker.
+*/
+PlugInConf* KCMKttsMgr::loadTalkerPlugin(const QString& name)
+{
+ // kdDebug() << "KCMKttsMgr::loadPlugin: Running"<< endl;
+
+ // Find the plugin.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/SynthPlugin",
+ QString("DesktopEntryName == '%1'").arg(name));
+
+ if (offers.count() == 1)
+ {
+ // When the entry is found, load the plug in
+ // First create a factory for the library
+ KLibFactory *factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if(factory){
+ // If the factory is created successfully, instantiate the PlugInConf class for the
+ // specific plug in to get the plug in configuration object.
+ PlugInConf *plugIn = KParts::ComponentFactory::createInstanceFromLibrary<PlugInConf>(
+ offers[0]->library().latin1(), NULL, offers[0]->library().latin1());
+ if(plugIn){
+ // If everything went ok, return the plug in pointer.
+ return plugIn;
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "KCMKttsMgr::loadTalkerPlugin: Unable to instantiate PlugInConf class for plugin " << name << endl;
+ return NULL;
+ }
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "KCMKttsMgr::loadTalkerPlugin: Unable to create Factory object for plugin "
+ << name << endl;
+ return NULL;
+ }
+ }
+ // The plug in was not found (unexpected behaviour, returns null).
+ kdDebug() << "KCMKttsMgr::loadTalkerPlugin: KTrader did not return an offer for plugin "
+ << name << endl;
+ return NULL;
+}
+
+/**
+ * Loads the configuration plug in for a named filter plug in.
+ * @param plugInName DesktopEntryName of the plugin.
+ * @return Pointer to the configuration plugin for the Filter.
+ */
+KttsFilterConf* KCMKttsMgr::loadFilterPlugin(const QString& plugInName)
+{
+ // kdDebug() << "KCMKttsMgr::loadPlugin: Running"<< endl;
+
+ // Find the plugin.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin",
+ QString("DesktopEntryName == '%1'").arg(plugInName));
+
+ if (offers.count() == 1)
+ {
+ // When the entry is found, load the plug in
+ // First create a factory for the library
+ KLibFactory *factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if(factory){
+ // If the factory is created successfully, instantiate the KttsFilterConf class for the
+ // specific plug in to get the plug in configuration object.
+ int errorNo = 0;
+ KttsFilterConf *plugIn =
+ KParts::ComponentFactory::createInstanceFromLibrary<KttsFilterConf>(
+ offers[0]->library().latin1(), NULL, offers[0]->library().latin1(),
+ QStringList(), &errorNo);
+ if(plugIn){
+ // If everything went ok, return the plug in pointer.
+ return plugIn;
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "KCMKttsMgr::loadFilterPlugin: Unable to instantiate KttsFilterConf class for plugin " << plugInName << " error: " << errorNo << endl;
+ return NULL;
+ }
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "KCMKttsMgr::loadFilterPlugin: Unable to create Factory object for plugin " << plugInName << endl;
+ return NULL;
+ }
+ }
+ // The plug in was not found (unexpected behaviour, returns null).
+ kdDebug() << "KCMKttsMgr::loadFilterPlugin: KTrader did not return an offer for plugin " << plugInName << endl;
+ return NULL;
+}
+
+/**
+* Given an item in the talker listview and a talker code, sets the columns of the item.
+* @param talkerItem QListViewItem.
+* @param talkerCode Talker Code.
+*/
+void KCMKttsMgr::updateTalkerItem(QListViewItem* talkerItem, const QString &talkerCode)
+{
+ TalkerCode parsedTalkerCode(talkerCode);
+ QString fullLanguageCode = parsedTalkerCode.fullLanguageCode();
+ if (!fullLanguageCode.isEmpty())
+ {
+ QString language = TalkerCode::languageCodeToLanguage(fullLanguageCode);
+ if (!language.isEmpty())
+ {
+ m_languagesToCodes[language] = fullLanguageCode;
+ talkerItem->setText(tlvcLanguage, language);
+ }
+ }
+ // Don't update the Synthesizer name with plugInName. The former is a translated
+ // name; the latter an English name.
+ // if (!plugInName.isEmpty()) talkerItem->setText(tlvcSynthName, plugInName);
+ if (!parsedTalkerCode.voice().isEmpty())
+ talkerItem->setText(tlvcVoice, parsedTalkerCode.voice());
+ if (!parsedTalkerCode.gender().isEmpty())
+ talkerItem->setText(tlvcGender, TalkerCode::translatedGender(parsedTalkerCode.gender()));
+ if (!parsedTalkerCode.volume().isEmpty())
+ talkerItem->setText(tlvcVolume, TalkerCode::translatedVolume(parsedTalkerCode.volume()));
+ if (!parsedTalkerCode.rate().isEmpty())
+ talkerItem->setText(tlvcRate, TalkerCode::translatedRate(parsedTalkerCode.rate()));
+}
+
+/**
+ * Add a talker.
+ */
+void KCMKttsMgr::slot_addTalker()
+{
+ AddTalker* addTalkerWidget = new AddTalker(m_synthToLangMap, this, "AddTalker_widget");
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Add Talker"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "AddTalker_dlg",
+ true,
+ true);
+ dlg->setMainWidget(addTalkerWidget);
+ dlg->setHelp("select-plugin", "kttsd");
+ int dlgResult = dlg->exec();
+ QString languageCode = addTalkerWidget->getLanguageCode();
+ QString synthName = addTalkerWidget->getSynthesizer();
+ delete dlg;
+ // TODO: Also delete addTalkerWidget?
+ if (dlgResult != QDialog::Accepted) return;
+
+ // If user chose "Other", must now get a language from him.
+ if(languageCode == "other")
+ {
+ // Create a QHBox to host KListView.
+ QHBox* hBox = new QHBox(m_kttsmgrw, "SelectLanguage_hbox");
+ // Create a KListView and fill with all known languages.
+ KListView* langLView = new KListView(hBox, "SelectLanguage_lview");
+ langLView->addColumn(i18n("Language"));
+ langLView->addColumn(i18n("Code"));
+ QStringList allLocales = KGlobal::locale()->allLanguagesTwoAlpha();
+ QString locale;
+ QString countryCode;
+ QString charSet;
+ QString language;
+ const int allLocalesCount = allLocales.count();
+ for (int ndx=0; ndx < allLocalesCount; ++ndx)
+ {
+ locale = allLocales[ndx];
+ language = TalkerCode::languageCodeToLanguage(locale);
+ new KListViewItem(langLView, language, locale);
+ }
+ // Sort by language.
+ langLView->setSorting(0);
+ langLView->sort();
+ // Display the box in a dialog.
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Select Language"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "SelectLanguage_dlg",
+ true,
+ true);
+ dlg->setMainWidget(hBox);
+ dlg->setHelp("select-plugin", "kttsd");
+ dlg->setInitialSize(QSize(200, 500), false);
+ dlgResult = dlg->exec();
+ languageCode = QString::null;
+ if (langLView->selectedItem()) languageCode = langLView->selectedItem()->text(1);
+ delete dlg;
+ // TODO: Also delete KListView and QHBox?
+ if (dlgResult != QDialog::Accepted) return;
+ }
+
+ if (languageCode.isEmpty()) return;
+ QString language = TalkerCode::languageCodeToLanguage(languageCode);
+ if (language.isEmpty()) return;
+
+ m_languagesToCodes[language] = languageCode;
+
+ // Assign a new Talker ID for the talker. Wraps around to 1.
+ QString talkerID = QString::number(m_lastTalkerID + 1);
+
+ // Erase extraneous Talker configuration entries that might be there.
+ m_config->deleteGroup(QString("Talker_")+talkerID);
+ m_config->sync();
+
+ // Convert translated plugin name to DesktopEntryName.
+ QString desktopEntryName = TalkerCode::TalkerNameToDesktopEntryName(synthName);
+ // This shouldn't happen, but just in case.
+ if (desktopEntryName.isEmpty()) return;
+
+ // Load the plugin.
+ m_loadedTalkerPlugIn = loadTalkerPlugin(desktopEntryName);
+ if (!m_loadedTalkerPlugIn) return;
+
+ // Give plugin the user's language code and permit plugin to autoconfigure itself.
+ m_loadedTalkerPlugIn->setDesiredLanguage(languageCode);
+ m_loadedTalkerPlugIn->load(m_config, QString("Talker_")+talkerID);
+
+ // If plugin was able to configure itself, it returns a full talker code.
+ // If not, display configuration dialog for user to configure the plugin.
+ QString talkerCode = m_loadedTalkerPlugIn->getTalkerCode();
+ if (talkerCode.isEmpty())
+ {
+ // Display configuration dialog.
+ configureTalker();
+ // Did user Cancel?
+ if (!m_loadedTalkerPlugIn)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ return;
+ }
+ talkerCode = m_loadedTalkerPlugIn->getTalkerCode();
+ }
+
+ // If still no Talker Code, abandon.
+ if (!talkerCode.isEmpty())
+ {
+ // Let plugin save its configuration.
+ m_config->setGroup(QString("Talker_")+talkerID);
+ m_loadedTalkerPlugIn->save(m_config, QString("Talker_"+talkerID));
+
+ // Record last Talker ID used for next add.
+ m_lastTalkerID = talkerID.toInt();
+
+ // Record configuration data. Note, might as well do this now.
+ m_config->setGroup(QString("Talker_")+talkerID);
+ m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ talkerCode = TalkerCode::normalizeTalkerCode(talkerCode, languageCode);
+ m_config->writeEntry("TalkerCode", talkerCode);
+ m_config->sync();
+
+ // Add listview item.
+ QListViewItem* talkerItem = m_kttsmgrw->talkersList->lastChild();
+ if (talkerItem)
+ talkerItem = new KListViewItem(m_kttsmgrw->talkersList, talkerItem,
+ QString::number(m_lastTalkerID), language, synthName);
+ else
+ talkerItem = new KListViewItem(m_kttsmgrw->talkersList,
+ QString::number(m_lastTalkerID), language, synthName);
+
+ // Set additional columns of the listview item.
+ updateTalkerItem(talkerItem, talkerCode);
+
+ // Make sure visible.
+ m_kttsmgrw->talkersList->ensureItemVisible(talkerItem);
+
+ // Select the new item, update buttons.
+ m_kttsmgrw->talkersList->setSelected(talkerItem, true);
+ updateTalkerButtons();
+
+ // Inform Control Center that change has been made.
+ configChanged();
+ }
+
+ // Don't need plugin in memory anymore.
+ delete m_loadedTalkerPlugIn;
+ m_loadedTalkerPlugIn = 0;
+ if (m_configDlg)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ }
+
+ // kdDebug() << "KCMKttsMgr::addTalker: done." << endl;
+}
+
+void KCMKttsMgr::slot_addNormalFilter()
+{
+ addFilter( false );
+}
+
+void KCMKttsMgr:: slot_addSbdFilter()
+{
+ addFilter( true );
+}
+
+/**
+* Add a filter.
+*/
+void KCMKttsMgr::addFilter( bool sbd)
+{
+ // Build a list of filters that support multiple instances and let user choose.
+ KListView* lView = m_kttsmgrw->filtersList;
+ if (sbd) lView = m_kttsmgrw->sbdsList;
+
+ QStringList filterPlugInNames;
+ QListViewItem* item = lView->firstChild();
+ while (item)
+ {
+ if (item->text(flvcMultiInstance) == "T")
+ {
+ if (!filterPlugInNames.contains(item->text(flvcPlugInName)))
+ filterPlugInNames.append(item->text(flvcPlugInName));
+ }
+ item = item->nextSibling();
+ }
+ // Append those available plugins not yet in the list at all.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin");
+ for (unsigned int i=0; i < offers.count() ; ++i)
+ {
+ QString filterPlugInName = offers[i]->name();
+ if (countFilterPlugins(filterPlugInName) == 0)
+ {
+ QString desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ KttsFilterConf* filterConf = loadFilterPlugin(desktopEntryName);
+ if (filterConf)
+ {
+ if (filterConf->isSBD() == sbd)
+ filterPlugInNames.append(filterPlugInName);
+ delete filterConf;
+ }
+ }
+ }
+
+ // If no choice (shouldn't happen), bail out.
+ // kdDebug() << "KCMKttsMgr::addFilter: filterPluginNames = " << filterPlugInNames << endl;
+ if (filterPlugInNames.count() == 0) return;
+
+ // If exactly one choice, skip selection dialog, otherwise display list to user to select from.
+ bool okChosen = false;
+ QString filterPlugInName;
+ if (filterPlugInNames.count() > 1)
+ {
+ filterPlugInName = KInputDialog::getItem(
+ i18n("Select Filter"),
+ i18n("Filter"),
+ filterPlugInNames,
+ 0,
+ false,
+ &okChosen,
+ m_kttsmgrw,
+ "selectfilter_kttsd");
+ if (!okChosen) return;
+ } else
+ filterPlugInName = filterPlugInNames[0];
+
+ // Assign a new Filter ID for the filter. Wraps around to 1.
+ QString filterID = QString::number(m_lastFilterID + 1);
+
+ // Erase extraneous Filter configuration entries that might be there.
+ m_config->deleteGroup(QString("Filter_")+filterID);
+ m_config->sync();
+
+ // Get DesktopEntryName from the translated name.
+ QString desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ // This shouldn't happen, but just in case.
+ if (desktopEntryName.isEmpty()) return;
+
+ // Load the plugin.
+ m_loadedFilterPlugIn = loadFilterPlugin(desktopEntryName);
+ if (!m_loadedFilterPlugIn) return;
+
+ // Permit plugin to autoconfigure itself.
+ m_loadedFilterPlugIn->load(m_config, QString("Filter_")+filterID);
+
+ // Display configuration dialog for user to configure the plugin.
+ configureFilter();
+
+ // Did user Cancel?
+ if (!m_loadedFilterPlugIn)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ return;
+ }
+
+ // Get user's name for Filter.
+ QString userFilterName = m_loadedFilterPlugIn->userPlugInName();
+
+ // If user properly configured the plugin, save its configuration.
+ if ( !userFilterName.isEmpty() )
+ {
+ // Let plugin save its configuration.
+ m_config->setGroup(QString("Filter_")+filterID);
+ m_loadedFilterPlugIn->save(m_config, QString("Filter_"+filterID));
+
+ // Record last Filter ID used for next add.
+ m_lastFilterID = filterID.toInt();
+
+ // Determine if filter supports multiple instances.
+ bool multiInstance = m_loadedFilterPlugIn->supportsMultiInstance();
+
+ // Record configuration data. Note, might as well do this now.
+ m_config->setGroup(QString("Filter_")+filterID);
+ m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ m_config->writeEntry("UserFilterName", userFilterName);
+ m_config->writeEntry("MultiInstance", multiInstance);
+ m_config->writeEntry("Enabled", true);
+ m_config->writeEntry("IsSBD", sbd);
+ m_config->sync();
+
+ // Add listview item.
+ QListViewItem* filterItem = lView->lastChild();
+ if (sbd)
+ {
+ if (filterItem)
+ filterItem = new KListViewItem( lView, filterItem, userFilterName );
+ else
+ filterItem = new KListViewItem( lView, userFilterName );
+ }
+ else
+ {
+ if (filterItem)
+ filterItem = new KttsCheckListItem(lView, filterItem,
+ userFilterName, QCheckListItem::CheckBox, this);
+ else
+ filterItem = new KttsCheckListItem(lView,
+ userFilterName, QCheckListItem::CheckBox, this);
+ dynamic_cast<QCheckListItem*>(filterItem)->setOn(true);
+ }
+ filterItem->setText(flvcFilterID, QString::number(m_lastFilterID));
+ filterItem->setText(flvcPlugInName, filterPlugInName);
+ if (multiInstance)
+ filterItem->setText(flvcMultiInstance, "T");
+ else
+ filterItem->setText(flvcMultiInstance, "F");
+
+ // Make sure visible.
+ lView->ensureItemVisible(filterItem);
+
+ // Select the new item, update buttons.
+ lView->setSelected(filterItem, true);
+ if (sbd)
+ updateSbdButtons();
+ else
+ updateFilterButtons();
+
+ // Inform Control Center that change has been made.
+ configChanged();
+ }
+
+ // Don't need plugin in memory anymore.
+ delete m_loadedFilterPlugIn;
+ m_loadedFilterPlugIn = 0;
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+
+ // kdDebug() << "KCMKttsMgr::addFilter: done." << endl;
+}
+
+/**
+* Remove talker.
+*/
+void KCMKttsMgr::slot_removeTalker(){
+ // kdDebug() << "KCMKttsMgr::removeTalker: Running"<< endl;
+
+ // Get the selected talker.
+ QListViewItem *itemToRemove = m_kttsmgrw->talkersList->selectedItem();
+ if (!itemToRemove) return;
+
+ // Delete the talker from configuration file.
+// QString talkerID = itemToRemove->text(tlvcTalkerID);
+// m_config->deleteGroup("Talker_"+talkerID, true, false);
+
+ // Delete the talker from list view.
+ delete itemToRemove;
+
+ updateTalkerButtons();
+
+ // Emit configuraton changed.
+ configChanged();
+}
+
+void KCMKttsMgr::slot_removeNormalFilter()
+{
+ removeFilter( false );
+}
+
+void KCMKttsMgr::slot_removeSbdFilter()
+{
+ removeFilter( true );
+}
+
+/**
+* Remove filter.
+*/
+void KCMKttsMgr::removeFilter( bool sbd )
+{
+ // kdDebug() << "KCMKttsMgr::removeFilter: Running"<< endl;
+
+ KListView* lView = m_kttsmgrw->filtersList;
+ if (sbd) lView = m_kttsmgrw->sbdsList;
+ // Get the selected filter.
+ QListViewItem *itemToRemove = lView->selectedItem();
+ if (!itemToRemove) return;
+
+ // Delete the filter from configuration file.
+// QString filterID = itemToRemove->text(flvcFilterID);
+// m_config->deleteGroup("Filter_"+filterID, true, false);
+
+ // Delete the filter from list view.
+ delete itemToRemove;
+
+ if (sbd)
+ updateSbdButtons();
+ else
+ updateFilterButtons();
+
+ // Emit configuraton changed.
+ configChanged();
+}
+
+void KCMKttsMgr::slot_higherTalkerPriority()
+{
+ higherItemPriority( m_kttsmgrw->talkersList );
+ updateTalkerButtons();
+}
+
+void KCMKttsMgr::slot_higherNormalFilterPriority()
+{
+ higherItemPriority( m_kttsmgrw->filtersList );
+ updateFilterButtons();
+}
+
+void KCMKttsMgr::slot_higherSbdFilterPriority()
+{
+ higherItemPriority( m_kttsmgrw->sbdsList );
+ updateSbdButtons();
+}
+
+/**
+* This is called whenever user clicks the Up button.
+*/
+void KCMKttsMgr::higherItemPriority( KListView* lView )
+{
+ QListViewItem* item = lView->selectedItem();
+ if (!item) return;
+ QListViewItem* prevItem = item->itemAbove();
+ if (!prevItem) return;
+ prevItem->moveItem(item);
+ lView->setSelected(item, true);
+ lView->ensureItemVisible( item );
+ configChanged();
+}
+
+void KCMKttsMgr::slot_lowerTalkerPriority()
+{
+ lowerItemPriority( m_kttsmgrw->talkersList );
+ updateTalkerButtons();
+}
+
+void KCMKttsMgr::slot_lowerNormalFilterPriority()
+{
+ lowerItemPriority( m_kttsmgrw->filtersList );
+ updateFilterButtons();
+}
+
+void KCMKttsMgr::slot_lowerSbdFilterPriority()
+{
+ lowerItemPriority( m_kttsmgrw->sbdsList );
+ updateSbdButtons();
+}
+
+/**
+* This is called whenever user clicks the Down button.
+*/
+void KCMKttsMgr::lowerItemPriority( KListView* lView )
+{
+ QListViewItem* item = lView->selectedItem();
+ if (!item) return;
+ QListViewItem* nextItem = item->itemBelow();
+ if (!nextItem) return;
+ item->moveItem(nextItem);
+ lView->setSelected(item, true);
+ lView->ensureItemVisible( item );
+ configChanged();
+}
+
+/**
+* Update the status of the Talker buttons.
+*/
+void KCMKttsMgr::updateTalkerButtons(){
+ // kdDebug() << "KCMKttsMgr::updateTalkerButtons: Running"<< endl;
+ if(m_kttsmgrw->talkersList->selectedItem()){
+ m_kttsmgrw->removeTalkerButton->setEnabled(true);
+ m_kttsmgrw->configureTalkerButton->setEnabled(true);
+ m_kttsmgrw->higherTalkerPriorityButton->setEnabled(
+ m_kttsmgrw->talkersList->selectedItem()->itemAbove() != 0);
+ m_kttsmgrw->lowerTalkerPriorityButton->setEnabled(
+ m_kttsmgrw->talkersList->selectedItem()->itemBelow() != 0);
+ } else {
+ m_kttsmgrw->removeTalkerButton->setEnabled(false);
+ m_kttsmgrw->configureTalkerButton->setEnabled(false);
+ m_kttsmgrw->higherTalkerPriorityButton->setEnabled(false);
+ m_kttsmgrw->lowerTalkerPriorityButton->setEnabled(false);
+ }
+ // kdDebug() << "KCMKttsMgr::updateTalkerButtons: Exiting"<< endl;
+}
+
+/**
+* Update the status of the normal Filter buttons.
+*/
+void KCMKttsMgr::updateFilterButtons(){
+ // kdDebug() << "KCMKttsMgr::updateFilterButtons: Running"<< endl;
+ QListViewItem* item = m_kttsmgrw->filtersList->selectedItem();
+ if (item) {
+ m_kttsmgrw->removeFilterButton->setEnabled(true);
+ m_kttsmgrw->configureFilterButton->setEnabled(true);
+ m_kttsmgrw->higherFilterPriorityButton->setEnabled(
+ m_kttsmgrw->filtersList->selectedItem()->itemAbove() != 0);
+ m_kttsmgrw->lowerFilterPriorityButton->setEnabled(
+ m_kttsmgrw->filtersList->selectedItem()->itemBelow() != 0);
+ } else {
+ m_kttsmgrw->removeFilterButton->setEnabled(false);
+ m_kttsmgrw->configureFilterButton->setEnabled(false);
+ m_kttsmgrw->higherFilterPriorityButton->setEnabled(false);
+ m_kttsmgrw->lowerFilterPriorityButton->setEnabled(false);
+ }
+ // kdDebug() << "KCMKttsMgr::updateFilterButtons: Exiting"<< endl;
+}
+
+/**
+ * Update the status of the SBD buttons.
+ */
+void KCMKttsMgr::updateSbdButtons(){
+ // kdDebug() << "KCMKttsMgr::updateSbdButtons: Running"<< endl;
+ QListViewItem* item = m_kttsmgrw->sbdsList->selectedItem();
+ if (item) {
+ m_sbdPopmenu->setItemEnabled( sbdBtnEdit, true );
+ m_sbdPopmenu->setItemEnabled( sbdBtnUp,
+ m_kttsmgrw->sbdsList->selectedItem()->itemAbove() != 0 );
+ m_sbdPopmenu->setItemEnabled( sbdBtnDown,
+ m_kttsmgrw->sbdsList->selectedItem()->itemBelow() != 0 );
+ m_sbdPopmenu->setItemEnabled( sbdBtnRemove, true );
+ } else {
+ m_sbdPopmenu->setItemEnabled( sbdBtnEdit, false );
+ m_sbdPopmenu->setItemEnabled( sbdBtnUp, false );
+ m_sbdPopmenu->setItemEnabled( sbdBtnDown, false );
+ m_sbdPopmenu->setItemEnabled( sbdBtnRemove, false );
+ }
+ // kdDebug() << "KCMKttsMgr::updateSbdButtons: Exiting"<< endl;
+}
+
+/**
+* This signal is emitted whenever user checks/unchecks the Enable TTS System check box.
+*/
+void KCMKttsMgr::enableKttsdToggled(bool)
+{
+ // Prevent re-entrancy.
+ static bool reenter;
+ if (reenter) return;
+ reenter = true;
+ // See if KTTSD is running.
+ DCOPClient *client = kapp->dcopClient();
+ bool kttsdRunning = (client->isApplicationRegistered("kttsd"));
+ // kdDebug() << "KCMKttsMgr::enableKttsdToggled: kttsdRunning = " << kttsdRunning << endl;
+ // If Enable KTTSD check box is checked and it is not running, then start KTTSD.
+ if (m_kttsmgrw->enableKttsdCheckBox->isChecked())
+ {
+ if (!kttsdRunning)
+ {
+ // kdDebug() << "KCMKttsMgr::enableKttsdToggled:: Starting KTTSD" << endl;
+ QString error;
+ if (KApplication::startServiceByDesktopName("kttsd", QStringList(), &error))
+ {
+ kdDebug() << "Starting KTTSD failed with message " << error << endl;
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->notifyTestButton->setEnabled(false);
+ }
+ }
+ }
+ else
+ // If check box is not checked and it is running, then stop KTTSD.
+ {
+ if (kttsdRunning)
+ {
+ // kdDebug() << "KCMKttsMgr::enableKttsdToggled:: Stopping KTTSD" << endl;
+ QByteArray data;
+ client->send("kttsd", "KSpeech", "kttsdExit()", data);
+ }
+ }
+ reenter = false;
+}
+
+/**
+* This signal is emitted whenever user checks/unchecks the GStreamer radio button.
+*/
+void KCMKttsMgr::slotGstreamerRadioButton_toggled(bool state)
+{
+ m_kttsmgrw->sinkLabel->setEnabled(state);
+ m_kttsmgrw->sinkComboBox->setEnabled(state);
+}
+
+/**
+* This signal is emitted whenever user checks/unchecks the ALSA radio button.
+*/
+void KCMKttsMgr::slotAlsaRadioButton_toggled(bool state)
+{
+ m_kttsmgrw->pcmLabel->setEnabled(state);
+ m_kttsmgrw->pcmComboBox->setEnabled(state);
+ m_kttsmgrw->pcmCustom->setEnabled(state && m_kttsmgrw->pcmComboBox->currentText() == "custom");
+}
+
+/**
+* This is emitted whenever user activates the ALSA pcm combobox.
+*/
+void KCMKttsMgr::slotPcmComboBox_activated()
+{
+ m_kttsmgrw->pcmCustom->setEnabled(m_kttsmgrw->pcmComboBox->currentText() == "custom");
+}
+
+/**
+* This signal is emitted whenever user checks/unchecks the aKode radio button.
+*/
+void KCMKttsMgr::slotAkodeRadioButton_toggled(bool state)
+{
+ m_kttsmgrw->akodeSinkLabel->setEnabled(state);
+ m_kttsmgrw->akodeComboBox->setEnabled(state);
+}
+
+/**
+* This slot is called whenever KTTSD starts or restarts.
+*/
+void KCMKttsMgr::kttsdStarted()
+{
+ // kdDebug() << "KCMKttsMgr::kttsdStarted: Running" << endl;
+ bool kttsdLoaded = (m_jobMgrPart != 0);
+ // Load Job Manager Part library.
+ if (!kttsdLoaded)
+ {
+ KLibFactory *factory = KLibLoader::self()->factory( "libkttsjobmgrpart" );
+ if (factory)
+ {
+ // Create the Job Manager part
+ m_jobMgrPart = (KParts::ReadOnlyPart *)factory->create( m_kttsmgrw->mainTab, "kttsjobmgr",
+ "KParts::ReadOnlyPart" );
+ if (m_jobMgrPart)
+ {
+ // Add the Job Manager part as a new tab.
+ m_kttsmgrw->mainTab->addTab(m_jobMgrPart->widget(), i18n("&Jobs"));
+ kttsdLoaded = true;
+ }
+ else
+ kdDebug() << "Could not create kttsjobmgr part." << endl;
+ }
+ else kdDebug() << "Could not load libkttsjobmgrpart. Is libkttsjobmgrpart installed?" << endl;
+ }
+ // Check/Uncheck the Enable KTTSD check box.
+ if (kttsdLoaded)
+ {
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(true);
+ // Enable/disable notify Test button.
+ slotNotifyListView_selectionChanged();
+ } else {
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->notifyTestButton->setEnabled(false);
+ }
+}
+
+/**
+* This slot is called whenever KTTSD is about to exit.
+*/
+void KCMKttsMgr::kttsdExiting()
+{
+ // kdDebug() << "KCMKttsMgr::kttsdExiting: Running" << endl;
+ if (m_jobMgrPart)
+ {
+ m_kttsmgrw->mainTab->removePage(m_jobMgrPart->widget());
+ delete m_jobMgrPart;
+ m_jobMgrPart = 0;
+ }
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->notifyTestButton->setEnabled(false);
+}
+
+/**
+* User has requested display of talker configuration dialog.
+*/
+void KCMKttsMgr::slot_configureTalker()
+{
+ // Get highlighted plugin from Talker ListView and load into memory.
+ QListViewItem* talkerItem = m_kttsmgrw->talkersList->selectedItem();
+ if (!talkerItem) return;
+ QString talkerID = talkerItem->text(tlvcTalkerID);
+ QString synthName = talkerItem->text(tlvcSynthName);
+ QString language = talkerItem->text(tlvcLanguage);
+ QString languageCode = m_languagesToCodes[language];
+ QString desktopEntryName = TalkerCode::TalkerNameToDesktopEntryName(synthName);
+ m_loadedTalkerPlugIn = loadTalkerPlugin(desktopEntryName);
+ if (!m_loadedTalkerPlugIn) return;
+ // kdDebug() << "KCMKttsMgr::slot_configureTalker: plugin for " << synthName << " loaded successfully." << endl;
+
+ // Tell plugin to load its configuration.
+ m_config->setGroup(QString("Talker_")+talkerID);
+ m_loadedTalkerPlugIn->setDesiredLanguage(languageCode);
+ // kdDebug() << "KCMKttsMgr::slot_configureTalker: about to call plugin load() method with Talker ID = " << talkerID << endl;
+ m_loadedTalkerPlugIn->load(m_config, QString("Talker_")+talkerID);
+
+ // Display configuration dialog.
+ configureTalker();
+
+ // Did user Cancel?
+ if (!m_loadedTalkerPlugIn)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ return;
+ }
+
+ // Get Talker Code. Note that plugin may return a code different from before.
+ QString talkerCode = m_loadedTalkerPlugIn->getTalkerCode();
+
+ // If plugin was successfully configured, save its configuration.
+ if (!talkerCode.isEmpty())
+ {
+ m_config->setGroup(QString("Talker_")+talkerID);
+ m_loadedTalkerPlugIn->save(m_config, QString("Talker_")+talkerID);
+ m_config->setGroup(QString("Talker_")+talkerID);
+ talkerCode = TalkerCode::normalizeTalkerCode(talkerCode, languageCode);
+ m_config->writeEntry("TalkerCode", talkerCode);
+ m_config->sync();
+
+ // Update display.
+ updateTalkerItem(talkerItem, talkerCode);
+
+ // Inform Control Center that configuration has changed.
+ configChanged();
+ }
+
+ delete m_loadedTalkerPlugIn;
+ m_loadedTalkerPlugIn = 0;
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+}
+
+void KCMKttsMgr::slot_configureNormalFilter()
+{
+ configureFilterItem( false );
+}
+
+void KCMKttsMgr::slot_configureSbdFilter()
+{
+ configureFilterItem( true );
+}
+
+/**
+ * User has requested display of filter configuration dialog.
+ */
+void KCMKttsMgr::configureFilterItem( bool sbd )
+{
+ // Get highlighted plugin from Filter ListView and load into memory.
+ KListView* lView = m_kttsmgrw->filtersList;
+ if (sbd) lView = m_kttsmgrw->sbdsList;
+ QListViewItem* filterItem = lView->selectedItem();
+ if (!filterItem) return;
+ QString filterID = filterItem->text(flvcFilterID);
+ QString filterPlugInName = filterItem->text(flvcPlugInName);
+ QString desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ if (desktopEntryName.isEmpty()) return;
+ m_loadedFilterPlugIn = loadFilterPlugin(desktopEntryName);
+ if (!m_loadedFilterPlugIn) return;
+ // kdDebug() << "KCMKttsMgr::slot_configureFilter: plugin for " << filterPlugInName << " loaded successfully." << endl;
+
+ // Tell plugin to load its configuration.
+ m_config->setGroup(QString("Filter_")+filterID);
+ // kdDebug() << "KCMKttsMgr::slot_configureFilter: about to call plugin load() method with Filter ID = " << filterID << endl;
+ m_loadedFilterPlugIn->load(m_config, QString("Filter_")+filterID);
+
+ // Display configuration dialog.
+ configureFilter();
+
+ // Did user Cancel?
+ if (!m_loadedFilterPlugIn)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ return;
+ }
+
+ // Get user's name for the plugin.
+ QString userFilterName = m_loadedFilterPlugIn->userPlugInName();
+
+ // If user properly configured the plugin, save the configuration.
+ if ( !userFilterName.isEmpty() )
+ {
+
+ // Let plugin save its configuration.
+ m_config->setGroup(QString("Filter_")+filterID);
+ m_loadedFilterPlugIn->save(m_config, QString("Filter_")+filterID);
+
+ // Save configuration.
+ m_config->setGroup("Filter_"+filterID);
+ m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ m_config->writeEntry("UserFilterName", userFilterName);
+ m_config->writeEntry("Enabled", true);
+ m_config->writeEntry("MultiInstance", m_loadedFilterPlugIn->supportsMultiInstance());
+ m_config->writeEntry("IsSBD", sbd);
+
+ m_config->sync();
+
+ // Update display.
+ filterItem->setText(flvcUserName, userFilterName);
+ if (!sbd)
+ dynamic_cast<QCheckListItem*>(filterItem)->setOn(true);
+
+ // Inform Control Center that configuration has changed.
+ configChanged();
+ }
+
+ delete m_loadedFilterPlugIn;
+ m_loadedFilterPlugIn = 0;
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+}
+
+/**
+* Display talker configuration dialog. The plugin is assumed already loaded into
+* memory referenced by m_loadedTalkerPlugIn.
+*/
+void KCMKttsMgr::configureTalker()
+{
+ if (!m_loadedTalkerPlugIn) return;
+ m_configDlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Talker Configuration"),
+ KDialogBase::Help|KDialogBase::Default|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "configureTalker_dlg",
+ true,
+ true);
+ m_configDlg->setInitialSize(QSize(700, 300), false);
+ m_configDlg->setMainWidget(m_loadedTalkerPlugIn);
+ m_configDlg->setHelp("configure-plugin", "kttsd");
+ m_configDlg->enableButtonOK(false);
+ connect(m_loadedTalkerPlugIn, SIGNAL( changed(bool) ), this, SLOT( slotConfigTalkerDlg_ConfigChanged() ));
+ connect(m_configDlg, SIGNAL( defaultClicked() ), this, SLOT( slotConfigTalkerDlg_DefaultClicked() ));
+ connect(m_configDlg, SIGNAL( cancelClicked() ), this, SLOT (slotConfigTalkerDlg_CancelClicked() ));
+ // Create a Player object for the plugin to use for testing.
+ int playerOption = 0;
+ QString sinkName;
+ if (m_kttsmgrw->gstreamerRadioButton->isChecked()) {
+ playerOption = 1;
+ sinkName = m_kttsmgrw->sinkComboBox->currentText();
+ }
+ if (m_kttsmgrw->alsaRadioButton->isChecked()) {
+ playerOption = 2;
+ if (m_kttsmgrw->pcmComboBox->currentText() == "custom")
+ sinkName = m_kttsmgrw->pcmCustom->text();
+ else
+ sinkName = m_kttsmgrw->pcmComboBox->currentText();
+ }
+ if (m_kttsmgrw->akodeRadioButton->isChecked()) {
+ playerOption = 3;
+ sinkName = m_kttsmgrw->akodeComboBox->currentText();
+ }
+ float audioStretchFactor = 1.0/(float(m_kttsmgrw->timeBox->value())/100.0);
+ // kdDebug() << "KCMKttsMgr::configureTalker: playerOption = " << playerOption << " audioStretchFactor = " << audioStretchFactor << " sink name = " << sinkName << endl;
+ TestPlayer* testPlayer = new TestPlayer(this, "ktts_testplayer",
+ playerOption, audioStretchFactor, sinkName);
+ m_loadedTalkerPlugIn->setPlayer(testPlayer);
+ // Display the dialog.
+ m_configDlg->exec();
+ // Done with Player object.
+ if (m_loadedTalkerPlugIn)
+ {
+ delete testPlayer;
+ m_loadedTalkerPlugIn->setPlayer(0);
+ }
+}
+
+/**
+* Display filter configuration dialog. The plugin is assumed already loaded into
+* memory referenced by m_loadedFilterPlugIn.
+*/
+void KCMKttsMgr::configureFilter()
+{
+ if (!m_loadedFilterPlugIn) return;
+ m_configDlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Filter Configuration"),
+ KDialogBase::Help|KDialogBase::Default|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "configureFilter_dlg",
+ true,
+ true);
+ m_configDlg->setInitialSize(QSize(600, 450), false);
+ m_loadedFilterPlugIn->setMinimumSize(m_loadedFilterPlugIn->minimumSizeHint());
+ m_loadedFilterPlugIn->show();
+ m_configDlg->setMainWidget(m_loadedFilterPlugIn);
+ m_configDlg->setHelp("configure-filter", "kttsd");
+ m_configDlg->enableButtonOK(false);
+ connect(m_loadedFilterPlugIn, SIGNAL( changed(bool) ), this, SLOT( slotConfigFilterDlg_ConfigChanged() ));
+ connect(m_configDlg, SIGNAL( defaultClicked() ), this, SLOT( slotConfigFilterDlg_DefaultClicked() ));
+ connect(m_configDlg, SIGNAL( cancelClicked() ), this, SLOT (slotConfigFilterDlg_CancelClicked() ));
+ // Display the dialog.
+ m_configDlg->exec();
+}
+
+/**
+* Count number of configured Filters with the specified plugin name.
+*/
+int KCMKttsMgr::countFilterPlugins(const QString& filterPlugInName)
+{
+ int cnt = 0;
+ QListViewItem* item = m_kttsmgrw->filtersList->firstChild();
+ while (item)
+ {
+ if (item->text(flvcPlugInName) == filterPlugInName) ++cnt;
+ item = item->nextSibling();
+ }
+ item = m_kttsmgrw->sbdsList->firstChild();
+ while (item)
+ {
+ if (item->text(slvcPlugInName) == filterPlugInName) ++cnt;
+ item = item->nextSibling();
+ }
+ return cnt;
+}
+
+void KCMKttsMgr::keepAudioCheckBox_toggled(bool checked)
+{
+ m_kttsmgrw->keepAudioPath->setEnabled(checked);
+ configChanged();
+}
+
+// Basically the slider values are logarithmic (0,...,1000) whereas percent
+// values are linear (50%,...,200%).
+//
+// slider = alpha * (log(percent)-log(50))
+// with alpha = 1000/(log(200)-log(50))
+
+int KCMKttsMgr::percentToSlider(int percentValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor (0.5 + alpha * (log(percentValue)-log(50)));
+}
+
+int KCMKttsMgr::sliderToPercent(int sliderValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor(0.5 + exp (sliderValue/alpha + log(50)));
+}
+
+void KCMKttsMgr::timeBox_valueChanged(int percentValue) {
+ m_kttsmgrw->timeSlider->setValue (percentToSlider (percentValue));
+}
+
+void KCMKttsMgr::timeSlider_valueChanged(int sliderValue) {
+ m_kttsmgrw->timeBox->setValue (sliderToPercent (sliderValue));
+}
+
+void KCMKttsMgr::slotConfigTalkerDlg_ConfigChanged()
+{
+ m_configDlg->enableButtonOK(!m_loadedTalkerPlugIn->getTalkerCode().isEmpty());
+}
+
+void KCMKttsMgr::slotConfigFilterDlg_ConfigChanged()
+{
+ m_configDlg->enableButtonOK( !m_loadedFilterPlugIn->userPlugInName().isEmpty() );
+}
+
+void KCMKttsMgr::slotConfigTalkerDlg_DefaultClicked()
+{
+ m_loadedTalkerPlugIn->defaults();
+}
+
+void KCMKttsMgr::slotConfigFilterDlg_DefaultClicked()
+{
+ m_loadedFilterPlugIn->defaults();
+}
+
+void KCMKttsMgr::slotConfigTalkerDlg_CancelClicked()
+{
+ delete m_loadedTalkerPlugIn;
+ m_loadedTalkerPlugIn = 0;
+}
+
+void KCMKttsMgr::slotConfigFilterDlg_CancelClicked()
+{
+ delete m_loadedFilterPlugIn;
+ m_loadedFilterPlugIn = 0;
+}
+
+/**
+* This slot is called whenever user checks/unchecks item in Filters list.
+*/
+void KCMKttsMgr::slotFiltersList_stateChanged()
+{
+ // kdDebug() << "KCMKttsMgr::slotFiltersList_stateChanged: calling configChanged" << endl;
+ configChanged();
+}
+
+/**
+ * Uses KTrader to convert a translated Filter Plugin Name to DesktopEntryName.
+ * @param name The translated plugin name. From Name= line in .desktop file.
+ * @return DesktopEntryName. The name of the .desktop file (less .desktop).
+ * QString::null if not found.
+ */
+QString KCMKttsMgr::FilterNameToDesktopEntryName(const QString& name)
+{
+ if (name.isEmpty()) return QString::null;
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin");
+ for (uint ndx = 0; ndx < offers.count(); ++ndx)
+ if (offers[ndx]->name() == name) return offers[ndx]->desktopEntryName();
+ return QString::null;
+}
+
+/**
+ * Uses KTrader to convert a DesktopEntryName into a translated Filter Plugin Name.
+ * @param desktopEntryName The DesktopEntryName.
+ * @return The translated Name of the plugin, from Name= line in .desktop file.
+ */
+QString KCMKttsMgr::FilterDesktopEntryNameToName(const QString& desktopEntryName)
+{
+ if (desktopEntryName.isEmpty()) return QString::null;
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin",
+ QString("DesktopEntryName == '%1'").arg(desktopEntryName));
+
+ if (offers.count() == 1)
+ return offers[0]->name();
+ else
+ return QString::null;
+}
+
+/**
+ * Loads notify events from a file. Clearing listview if clear is True.
+ */
+QString KCMKttsMgr::loadNotifyEventsFromFile( const QString& filename, bool clear)
+{
+ // Open existing event list.
+ QFile file( filename );
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ return i18n("Unable to open file.") + filename;
+ }
+ // QDomDocument doc( "http://www.kde.org/share/apps/kttsd/stringreplacer/wordlist.dtd []" );
+ QDomDocument doc( "" );
+ if ( !doc.setContent( &file ) ) {
+ file.close();
+ return i18n("File not in proper XML format.");
+ }
+ // kdDebug() << "StringReplacerConf::load: document successfully parsed." << endl;
+ file.close();
+
+ // Clear list view.
+ if ( clear ) m_kttsmgrw->notifyListView->clear();
+
+ // Event list.
+ QDomNodeList eventList = doc.elementsByTagName("notifyEvent");
+ const int eventListCount = eventList.count();
+ for (int eventIndex = 0; eventIndex < eventListCount; ++eventIndex)
+ {
+ QDomNode eventNode = eventList.item(eventIndex);
+ QDomNodeList propList = eventNode.childNodes();
+ QString eventSrc;
+ QString event;
+ QString actionName;
+ QString message;
+ TalkerCode talkerCode;
+ const int propListCount = propList.count();
+ for (int propIndex = 0; propIndex < propListCount; ++propIndex)
+ {
+ QDomNode propNode = propList.item(propIndex);
+ QDomElement prop = propNode.toElement();
+ if (prop.tagName() == "eventSrc") eventSrc = prop.text();
+ if (prop.tagName() == "event") event = prop.text();
+ if (prop.tagName() == "action") actionName = prop.text();
+ if (prop.tagName() == "message") message = prop.text();
+ if (prop.tagName() == "talker") talkerCode = TalkerCode(prop.text(), false);
+ }
+ addNotifyItem(eventSrc, event, NotifyAction::action( actionName ), message, talkerCode);
+ }
+
+ return QString::null;
+}
+
+/**
+ * Saves notify events to a file.
+ */
+QString KCMKttsMgr::saveNotifyEventsToFile(const QString& filename)
+{
+ QFile file( filename );
+ if ( !file.open( IO_WriteOnly ) )
+ return i18n("Unable to open file ") + filename;
+
+ QDomDocument doc( "" );
+
+ QDomElement root = doc.createElement( "notifyEventList" );
+ doc.appendChild( root );
+
+ // Events.
+ KListView* lv = m_kttsmgrw->notifyListView;
+ QListViewItemIterator it(lv);
+ while ( it.current() )
+ {
+ QListViewItem* item = *it;
+ if ( item->depth() > 0 )
+ {
+ QDomElement wordTag = doc.createElement( "notifyEvent" );
+ root.appendChild( wordTag );
+
+ QDomElement propTag = doc.createElement( "eventSrc" );
+ wordTag.appendChild( propTag);
+ QDomText t = doc.createTextNode( item->text(nlvcEventSrc) );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "event" );
+ wordTag.appendChild( propTag);
+ t = doc.createTextNode( item->text(nlvcEvent) );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "action" );
+ wordTag.appendChild( propTag);
+ t = doc.createTextNode( item->text(nlvcAction) );
+ propTag.appendChild( t );
+
+ if ( item->text(nlvcAction) == NotifyAction::actionName( NotifyAction::SpeakCustom ) )
+ {
+ propTag = doc.createElement( "message" );
+ wordTag.appendChild( propTag);
+ QString msg = item->text(nlvcActionName);
+ int msglen = msg.length();
+ msg = msg.mid( 1, msglen-2 );
+ t = doc.createCDATASection( msg );
+ propTag.appendChild( t );
+ }
+
+ propTag = doc.createElement( "talker" );
+ wordTag.appendChild( propTag);
+ t = doc.createCDATASection( item->text(nlvcTalker) );
+ propTag.appendChild( t );
+ }
+ ++it;
+ }
+
+ // Write it all out.
+ QTextStream ts( &file );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ ts << doc.toString();
+ file.close();
+
+ return QString::null;
+}
+
+void KCMKttsMgr::slotNotifyEnableCheckBox_toggled(bool checked)
+{
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->setEnabled( checked );
+ m_kttsmgrw->notifyGroup->setEnabled( checked );
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyPresentComboBox_activated(int index)
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( !item ) return; // should not happen
+ item->setText( nlvcEvent, NotifyPresent::presentName( index ) );
+ item->setText( nlvcEventName, NotifyPresent::presentDisplayName( index ) );
+ bool enableIt = ( index != NotifyPresent::None);
+ m_kttsmgrw->notifyActionComboBox->setEnabled( enableIt );
+ m_kttsmgrw->notifyTalkerButton->setEnabled( enableIt );
+ if (!enableIt)
+ {
+ m_kttsmgrw->notifyTalkerLineEdit->clear();
+ } else {
+ if ( m_kttsmgrw->notifyTalkerLineEdit->text().isEmpty() )
+ {
+ m_kttsmgrw->notifyTalkerLineEdit->setText( i18n("default") );
+ }
+ }
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyListView_selectionChanged()
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( item )
+ {
+ bool topLevel = ( item->depth() == 0 );
+ if ( topLevel )
+ {
+ m_kttsmgrw->notifyPresentComboBox->setEnabled( false );
+ m_kttsmgrw->notifyActionComboBox->setEnabled( false );
+ m_kttsmgrw->notifyTestButton->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->clear();
+ m_kttsmgrw->notifyTalkerButton->setEnabled( false );
+ m_kttsmgrw->notifyTalkerLineEdit->clear();
+ bool defaultItem = ( item->text(nlvcEventSrc) == "default" );
+ m_kttsmgrw->notifyRemoveButton->setEnabled( !defaultItem );
+ } else {
+ bool defaultItem = ( item->parent()->text(nlvcEventSrc) == "default" );
+ m_kttsmgrw->notifyPresentComboBox->setEnabled( defaultItem );
+ if ( defaultItem )
+ m_kttsmgrw->notifyPresentComboBox->setCurrentItem( NotifyPresent::present( item->text( nlvcEvent ) ) );
+ m_kttsmgrw->notifyActionComboBox->setEnabled( true );
+ int action = NotifyAction::action( item->text( nlvcAction ) );
+ m_kttsmgrw->notifyActionComboBox->setCurrentItem( action );
+ m_kttsmgrw->notifyTalkerButton->setEnabled( true );
+ TalkerCode talkerCode( item->text( nlvcTalker ) );
+ m_kttsmgrw->notifyTalkerLineEdit->setText( talkerCode.getTranslatedDescription() );
+ if ( action == NotifyAction::SpeakCustom )
+ {
+ m_kttsmgrw->notifyMsgLineEdit->setEnabled( true );
+ QString msg = item->text( nlvcActionName );
+ int msglen = msg.length();
+ msg = msg.mid( 1, msglen-2 );
+ m_kttsmgrw->notifyMsgLineEdit->setText( msg );
+ } else {
+ m_kttsmgrw->notifyMsgLineEdit->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->clear();
+ }
+ m_kttsmgrw->notifyRemoveButton->setEnabled( !defaultItem );
+ m_kttsmgrw->notifyTestButton->setEnabled(
+ action != NotifyAction::DoNotSpeak &&
+ m_kttsmgrw->enableKttsdCheckBox->isChecked());
+ }
+ } else {
+ m_kttsmgrw->notifyPresentComboBox->setEnabled( false );
+ m_kttsmgrw->notifyActionComboBox->setEnabled( false );
+ m_kttsmgrw->notifyTestButton->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->clear();
+ m_kttsmgrw->notifyTalkerButton->setEnabled( false );
+ m_kttsmgrw->notifyTalkerLineEdit->clear();
+ m_kttsmgrw->notifyRemoveButton->setEnabled( false );
+ }
+}
+
+void KCMKttsMgr::slotNotifyActionComboBox_activated(int index)
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( item )
+ if ( item->depth() == 0 ) item = 0;
+ if ( !item ) return; // This shouldn't happen.
+ item->setText( nlvcAction, NotifyAction::actionName( index ) );
+ item->setText( nlvcActionName, NotifyAction::actionDisplayName( index ) );
+ if ( index == NotifyAction::SpeakCustom )
+ item->setText( nlvcActionName, "\"" + m_kttsmgrw->notifyMsgLineEdit->text() + "\"" );
+ if ( index == NotifyAction::DoNotSpeak )
+ item->setPixmap( nlvcActionName, SmallIcon( "nospeak" ) );
+ else
+ item->setPixmap( nlvcActionName, SmallIcon( "speak" ) );
+ slotNotifyListView_selectionChanged();
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyMsgLineEdit_textChanged(const QString& text)
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( item )
+ if ( item->depth() == 0 ) item = 0;
+ if ( !item ) return; // This shouldn't happen.
+ if ( m_kttsmgrw->notifyActionComboBox->currentItem() != NotifyAction::SpeakCustom) return;
+ item->setText( nlvcActionName, "\"" + text + "\"" );
+ m_kttsmgrw->notifyTestButton->setEnabled(
+ !text.isEmpty() && m_kttsmgrw->enableKttsdCheckBox->isChecked());
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyTestButton_clicked()
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if (item)
+ {
+ QString msg;
+ int action = NotifyAction::action(item->text(nlvcAction));
+ switch (action)
+ {
+ case NotifyAction::SpeakEventName:
+ msg = item->text(nlvcEventName);
+ break;
+ case NotifyAction::SpeakMsg:
+ msg = i18n("sample notification message");
+ break;
+ case NotifyAction::SpeakCustom:
+ msg = m_kttsmgrw->notifyMsgLineEdit->text();
+ msg.replace("%a", i18n("sample application"));
+ msg.replace("%e", i18n("sample event"));
+ msg.replace("%m", i18n("sample notification message"));
+ break;
+ }
+ if (!msg.isEmpty()) sayMessage(msg, item->text(nlvcTalker));
+ }
+}
+
+void KCMKttsMgr::slotNotifyTalkerButton_clicked()
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( item )
+ if ( item->depth() == 0 ) item = 0;
+ if ( !item ) return; // This shouldn't happen.
+ QString talkerCode = item->text( nlvcTalker );
+ SelectTalkerDlg dlg( m_kttsmgrw, "selecttalkerdialog", i18n("Select Talker"), talkerCode, true );
+ int dlgResult = dlg.exec();
+ if ( dlgResult != KDialogBase::Accepted ) return;
+ item->setText( nlvcTalker, dlg.getSelectedTalkerCode() );
+ QString talkerName = dlg.getSelectedTranslatedDescription();
+ item->setText( nlvcTalkerName, talkerName );
+ m_kttsmgrw->notifyTalkerLineEdit->setText( talkerName );
+ configChanged();
+}
+
+/**
+ * Adds an item to the notify listview.
+ * message is only needed if action = naSpeakCustom.
+ */
+QListViewItem* KCMKttsMgr::addNotifyItem(
+ const QString& eventSrc,
+ const QString& event,
+ int action,
+ const QString& message,
+ TalkerCode& talkerCode)
+{
+ KListView* lv = m_kttsmgrw->notifyListView;
+ QListViewItem* item = 0;
+ QString iconName;
+ QString eventSrcName;
+ if (eventSrc == "default")
+ eventSrcName = i18n("Default (all other events)");
+ else
+ eventSrcName = NotifyEvent::getEventSrcName(eventSrc, iconName);
+ QString eventName;
+ if (eventSrc == "default")
+ eventName = NotifyPresent::presentDisplayName( event );
+ else
+ {
+ if (event == "default")
+ eventName = i18n("All other %1 events").arg(eventSrcName);
+ else
+ eventName = NotifyEvent::getEventName(eventSrc, event);
+ }
+ QString actionName = NotifyAction::actionName( action );
+ QString actionDisplayName = NotifyAction::actionDisplayName( action );
+ if (action == NotifyAction::SpeakCustom) actionDisplayName = "\"" + message + "\"";
+ QString talkerName = talkerCode.getTranslatedDescription();
+ if (!eventSrcName.isEmpty() && !eventName.isEmpty() && !actionName.isEmpty() && !talkerName.isEmpty())
+ {
+ QListViewItem* parentItem = lv->findItem(eventSrcName, nlvcEventSrcName);
+ if (!parentItem)
+ {
+ item = lv->lastItem();
+ if (!item)
+ parentItem = new KListViewItem(lv, eventSrcName, QString::null, QString::null,
+ eventSrc);
+ else
+ parentItem = new KListViewItem(lv, item, eventSrcName, QString::null, QString::null,
+ eventSrc);
+ if ( !iconName.isEmpty() )
+ parentItem->setPixmap( nlvcEventSrcName, SmallIcon( iconName ) );
+ }
+ // No duplicates.
+ item = lv->findItem( event, nlvcEvent );
+ if ( !item || item->parent() != parentItem )
+ item = new KListViewItem(parentItem, eventName, actionDisplayName, talkerName,
+ eventSrc, event, actionName, talkerCode.getTalkerCode());
+ if ( action == NotifyAction::DoNotSpeak )
+ item->setPixmap( nlvcActionName, SmallIcon( "nospeak" ) );
+ else
+ item->setPixmap( nlvcActionName, SmallIcon( "speak" ) );
+ }
+ return item;
+}
+
+void KCMKttsMgr::slotNotifyAddButton_clicked()
+{
+ QListView* lv = m_kttsmgrw->notifyListView;
+ QListViewItem* item = lv->selectedItem();
+ QString eventSrc;
+ if ( item ) eventSrc = item->text( nlvcEventSrc );
+ SelectEvent* selectEventWidget = new SelectEvent( this, "SelectEvent_widget", 0, eventSrc );
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Select Event"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "SelectEvent_dlg",
+ true,
+ true);
+ dlg->setMainWidget( selectEventWidget );
+ dlg->setInitialSize( QSize(500, 400) );
+ // dlg->setHelp("select-plugin", "kttsd");
+ int dlgResult = dlg->exec();
+ eventSrc = selectEventWidget->getEventSrc();
+ QString event = selectEventWidget->getEvent();
+ delete dlg;
+ if ( dlgResult != QDialog::Accepted ) return;
+ if ( eventSrc.isEmpty() || event.isEmpty() ) return;
+ // Use Default action, message, and talker.
+ QString actionName;
+ int action = NotifyAction::DoNotSpeak;
+ QString msg;
+ TalkerCode talkerCode;
+ item = lv->findItem( "default", nlvcEventSrc );
+ if ( item )
+ {
+ if ( item->childCount() > 0 ) item = item->firstChild();
+ if ( item )
+ {
+ actionName = item->text( nlvcAction );
+ action = NotifyAction::action( actionName );
+ talkerCode = TalkerCode( item->text( nlvcTalker ) );
+ if (action == NotifyAction::SpeakCustom )
+ {
+ msg = item->text(nlvcActionName);
+ int msglen = msg.length();
+ msg = msg.mid( 1, msglen-2 );
+ }
+ }
+ }
+ item = addNotifyItem( eventSrc, event, action, msg, talkerCode );
+ lv->ensureItemVisible( item );
+ lv->setSelected( item, true );
+ slotNotifyListView_selectionChanged();
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyClearButton_clicked()
+{
+ m_kttsmgrw->notifyListView->clear();
+ TalkerCode talkerCode( QString::null );
+ QListViewItem* item = addNotifyItem(
+ QString("default"),
+ NotifyPresent::presentName(NotifyPresent::Passive),
+ NotifyAction::SpeakEventName,
+ QString::null,
+ talkerCode );
+ QListView* lv = m_kttsmgrw->notifyListView;
+ lv->ensureItemVisible( item );
+ lv->setSelected( item, true );
+ slotNotifyListView_selectionChanged();
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyRemoveButton_clicked()
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if (!item) return;
+ QListViewItem* parentItem = item->parent();
+ delete item;
+ if (parentItem)
+ {
+ if (parentItem->childCount() == 0) delete parentItem;
+ }
+ slotNotifyListView_selectionChanged();
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyLoadButton_clicked()
+{
+ // QString dataDir = KGlobal::dirs()->resourceDirs("data").last() + "/kttsd/stringreplacer/";
+ QString dataDir = KGlobal::dirs()->findAllResources("data", "kttsd/notify/").last();
+ QString filename = KFileDialog::getOpenFileName(
+ dataDir,
+ "*.xml|" + i18n("file type", "Notification Event List") + " (*.xml)",
+ m_kttsmgrw,
+ "event_loadfile");
+ if ( filename.isEmpty() ) return;
+ QString errMsg = loadNotifyEventsFromFile( filename, true );
+ slotNotifyListView_selectionChanged();
+ if ( !errMsg.isEmpty() )
+ KMessageBox::sorry( m_kttsmgrw, errMsg, i18n("Error Opening File") );
+ else
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifySaveButton_clicked()
+{
+ QString filename = KFileDialog::getSaveFileName(
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/notify/", false ),
+ "*.xml|" + i18n("file type", "Notification Event List") + " (*.xml)",
+ m_kttsmgrw,
+ "event_savefile");
+ if ( filename.isEmpty() ) return;
+ QString errMsg = saveNotifyEventsToFile( filename );
+ slotNotifyListView_selectionChanged();
+ if ( !errMsg.isEmpty() )
+ KMessageBox::sorry( m_kttsmgrw, errMsg, i18n("Error Opening File") );
+}
+
+// ----------------------------------------------------------------------------
+
+KttsCheckListItem::KttsCheckListItem( QListView *parent, QListViewItem *after,
+ const QString &text, Type tt,
+ KCMKttsMgr* kcmkttsmgr ) :
+ QCheckListItem(parent, after, text, tt),
+ m_kcmkttsmgr(kcmkttsmgr) { }
+
+KttsCheckListItem::KttsCheckListItem( QListView *parent,
+ const QString &text, Type tt,
+ KCMKttsMgr* kcmkttsmgr ) :
+ QCheckListItem(parent, text, tt),
+ m_kcmkttsmgr(kcmkttsmgr) { }
+
+/*virtual*/ void KttsCheckListItem::stateChange(bool)
+{
+ if (m_kcmkttsmgr) m_kcmkttsmgr->slotFiltersList_stateChanged();
+}
+
+/*virtual*/ /*void resizeEvent( QResizeEvent ev )
+{
+ dynamic_cast<KCModule>(resizeEvent(ev));
+ updateGeometry();
+}
+*/
diff --git a/kttsd/kcmkttsmgr/kcmkttsmgr.h b/kttsd/kcmkttsmgr/kcmkttsmgr.h
new file mode 100644
index 0000000..39481b9
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsmgr.h
@@ -0,0 +1,530 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KControl module for KTTSD configuration and job management
+ -------------------
+ Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández
+ Copyright : (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ Current Maintainer: 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef KCMKTTSMGR_H
+#define KCMKTTSMGR_H
+
+#include "config.h"
+
+// Qt includes.
+#include <qmap.h>
+#include <qlistview.h>
+
+// KDE includes.
+#include <kcmodule.h>
+#include <ktrader.h>
+#include <kdebug.h>
+#include <kparts/part.h>
+
+// KTTS includes.
+#include "addtalker.h"
+#include "kcmkttsmgrwidget.h"
+#include "kspeech_stub.h"
+#include "kspeechsink.h"
+
+class PlugInConf;
+class KttsFilterConf;
+class KListViewItem;
+class KAboutData;
+class KConfig;
+class QPopupMenu;
+
+/**
+* @author José Pablo Ezequiel "Pupeno" Fernández
+* @author Gary Cramblitt
+*/
+
+class KCMKttsMgr :
+ public KCModule,
+ public KSpeech_stub,
+ virtual public KSpeechSink
+{
+ Q_OBJECT
+
+ public:
+ KCMKttsMgr(QWidget *parent, const char *name, const QStringList &);
+
+ ~KCMKttsMgr();
+
+ /**
+ * This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. NOTE that this is not called after the modules is loaded,
+ * so you probably want to call this method in the constructor.
+ */
+ void load();
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok".
+ */
+ void save();
+
+ /**
+ * This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file.
+ */
+ void defaults();
+
+ /**
+ * This is a static method which gets called to realize the modules settings
+ * durign the startup of KDE. NOTE that most modules do not implement this
+ * method, but modules like the keyboard and mouse modules, which directly
+ * interact with the X-server, need this method. As this method is static,
+ * it can avoid to create an instance of the user interface, which is often
+ * not needed in this case.
+ */
+ static void init();
+
+ /**
+ * The control center calls this function to decide which buttons should
+ * be displayed. For example, it does not make sense to display an "Apply"
+ * button for one of the information modules. The value returned can be set by
+ * modules using setButtons.
+ */
+ int buttons();
+
+ /**
+ * This function returns the small quickhelp.
+ * That is displayed in the sidebar in the KControl
+ */
+ QString quickHelp() const;
+
+ /**
+ * Return the about information for this module
+ */
+ const KAboutData* aboutData() const;
+
+ public slots:
+ /**
+ * This slot is used to emit the signal changed when any widget changes the configuration
+ */
+ void configChanged()
+ {
+ if (!m_suppressConfigChanged)
+ {
+ // kdDebug() << "KCMKttsMgr::configChanged: Running"<< endl;
+ m_changed = true;
+ emit changed(true);
+ }
+ };
+ /**
+ * This slot is called whenever user checks/unchecks item in Filters list.
+ */
+ void slotFiltersList_stateChanged();
+
+ protected:
+ /** DCOP Methods connected to DCOP Signals emitted by KTTSD. */
+ /** Most of these are not used */
+
+ /**
+ * This signal is emitted when KTTSD starts or restarts after a call to reinit.
+ */
+ virtual void kttsdStarted();
+ /**
+ * This signal is emitted just before KTTSD exits.
+ */
+ virtual void kttsdExiting();
+
+ // virtual void resizeEvent( QResizeEvent ev );
+
+ private:
+ enum widgetPages
+ {
+ wpGeneral = 0, // General tab.
+ wpTalkers = 1, // Talkers tab.
+ wpNotify = 2, // Notify tab.
+ wpFilters = 3, // Filters tab.
+ wpInterruption = 4, // Interruption tab.
+ wpAudio = 5, // Audio tab.
+ wpJobs = 6 // Jobs tab.
+ };
+
+ enum NotifyListViewColumn
+ {
+ nlvcEventSrcName = 0,
+ nlvcEventName = 0,
+ nlvcActionName = 1,
+ nlvcTalkerName = 2,
+ nlvcEventSrc = 3, // hidden
+ nlvcEvent = 4, // hidden
+ nlvcAction = 5, // hidden
+ nlvcTalker = 6 // hidden
+ };
+
+ enum TalkerListViewColumn
+ {
+ tlvcTalkerID,
+ tlvcLanguage,
+ tlvcSynthName,
+ tlvcVoice,
+ tlvcGender,
+ tlvcVolume,
+ tlvcRate
+ };
+
+ enum FilterListViewColumn
+ {
+ flvcUserName, // Name of filter as set by user and displayed.
+ flvcFilterID, // Internal ID assigned to the filter (hidden).
+ flvcPlugInName, // Name of the filter plugin (from .desktop file, hidden).
+ flvcMultiInstance // True if multiple instances of this plugin are possible. (hidden)
+ };
+
+ enum SbdListViewColumn
+ {
+ slvcUserName, // Name of filter as set by user and displayed.
+ slvcFilterID, // Internal ID assigned to the filter (hidden).
+ slvcPlugInName, // Name of the filter plugin (from .desktop file, hidden).
+ slvcMultiInstance // True if multiple instances of this plugin are possible. (hidden)
+ };
+
+ enum SbdButtonIDs
+ {
+ sbdBtnEdit = 1,
+ sbdBtnUp = 2,
+ sbdBtnDown = 3,
+ sbdBtnAdd = 4,
+ sbdBtnRemove = 5
+ };
+
+ /**
+ * Conversion functions for percent boxes to/from sliders.
+ */
+ int percentToSlider(int percentValue);
+ int sliderToPercent(int sliderValue);
+
+ /**
+ * Given a language code and plugin name, returns a normalized default talker code.
+ * @param languageCode Language code.
+ * @param plugInName Name of the plugin.
+ * @return Full normalized talker code.
+ *
+ * Example returned from defaultTalkerCode("en", "Festival")
+ * <voice lang="en" name="fixed" gender="neutral"/>
+ * <prosody volume="medium" rate="medium"/>
+ * <kttsd synthesizer="Festival" />
+ */
+ QString defaultTalkerCode(const QString &languageCode, const QString &plugInName);
+
+ /**
+ * Given an item in the talker listview and a talker code, sets the columns of the item.
+ * @param talkerItem QListViewItem.
+ * @param talkerCode Talker Code.
+ */
+ void updateTalkerItem(QListViewItem* talkerItem, const QString &talkerCode);
+
+ /**
+ * Loads the configuration plugin for a named Talker plugin.
+ * @param name DesktopEntryName of the Synthesizer.
+ * @return Pointer to the configuration plugin for the Talker.
+ */
+ PlugInConf* loadTalkerPlugin(const QString& name);
+
+ /**
+ * Loads the configuration plugin for a named Filter plugin.
+ * @param plugInName DesktopEntryName of the plugin.
+ * @return Pointer to the configuration plugin for the Filter.
+ */
+ KttsFilterConf* loadFilterPlugin(const QString& plugInName);
+
+ /**
+ * Display the Talker Configuration Dialog.
+ */
+ void configureTalker();
+
+ /**
+ * Display the Filter Configuration Dialog.
+ */
+ void configureFilterItem( bool sbd );
+ void configureFilter();
+
+ /**
+ * Add a filter.
+ */
+ void addFilter( bool sbd );
+
+ /**
+ * Remove a filter.
+ */
+ void removeFilter( bool sbd );
+
+ /**
+ * Move an item in a KListView up or down.
+ */
+ void lowerItemPriority( KListView* lView );
+ void higherItemPriority( KListView* lView );
+
+ /**
+ * Count number of configured Filters with the specified plugin name.
+ */
+ int countFilterPlugins(const QString& filterPlugInName);
+
+ /**
+ * Uses KTrader to convert a translated Filter Plugin Name to DesktopEntryName.
+ * @param name The translated plugin name. From Name= line in .desktop file.
+ * @return DesktopEntryName. The name of the .desktop file (less .desktop).
+ * QString::null if not found.
+ */
+ QString FilterNameToDesktopEntryName(const QString& name);
+
+ /**
+ * Uses KTrader to convert a DesktopEntryName into a translated Filter Plugin Name.
+ * @param desktopEntryName The DesktopEntryName.
+ * @return The translated Name of the plugin, from Name= line in .desktop file.
+ */
+ QString FilterDesktopEntryNameToName(const QString& desktopEntryName);
+
+ /**
+ * Loads notify events from a file. Clearing listview if clear is True.
+ */
+ QString loadNotifyEventsFromFile( const QString& filename, bool clear);
+
+ /**
+ * Saves notify events to a file.
+ */
+ QString saveNotifyEventsToFile(const QString& filename);
+
+ /**
+ * Adds an item to the notify listview.
+ * message is only needed if action = nactSpeakCustom.
+ */
+ QListViewItem* addNotifyItem(
+ const QString& eventSrc,
+ const QString& event,
+ int action,
+ const QString& message,
+ TalkerCode& talkerCode);
+
+ /**
+ * Main widget
+ */
+ KCMKttsMgrWidget *m_kttsmgrw;
+
+ /**
+ * Object holding all the configuration
+ */
+ KConfig *m_config;
+
+ /**
+ * KTTS Job Manager.
+ */
+ KParts::ReadOnlyPart *m_jobMgrPart;
+
+ /**
+ * Plugin configuration dialog.
+ */
+ KDialogBase* m_configDlg;
+
+ /**
+ * Sentence Boundary Detector button popup menu.
+ */
+ QPopupMenu* m_sbdPopmenu;
+
+ /**
+ * Talker(synth) Plugin currently loaded into configuration dialog.
+ */
+ PlugInConf *m_loadedTalkerPlugIn;
+
+ /**
+ * Filter Plugin currently loaded into configuration dialog.
+ */
+ KttsFilterConf *m_loadedFilterPlugIn;
+
+ /**
+ * Last talker ID. Used to generate a new ID.
+ */
+ int m_lastTalkerID;
+
+ /**
+ * Last filter ID. Used to generate a new ID.
+ */
+ int m_lastFilterID;
+
+ /**
+ * Last SBD filter ID. Used to generate to new ID.
+ */
+ int m_lastSbdID;
+
+ /**
+ * True if the configuration has been changed.
+ */
+ bool m_changed;
+
+ /**
+ * When True, suppresses emission of changed() signal. Used to suppress this
+ * signal while loading configuration.
+ */
+ bool m_suppressConfigChanged;
+
+ /**
+ * Dictionary mapping language names to codes.
+ */
+ QMap<QString, QString> m_languagesToCodes;
+
+ /**
+ * A QMap of languages codes indexed by synthesizer that supports them.
+ */
+ SynthToLangMap m_synthToLangMap;
+
+ /**
+ * Default Talker Code for notifications.
+ */
+ QString m_defaultNotifyTalkerCode;
+
+ private slots:
+ /**
+ * Add a talker/filter.
+ * This is a wrapper function that takes the parameters for the real talker from the
+ * widgets to later call it.
+ */
+ void slot_addTalker();
+ void slot_addNormalFilter();
+ void slot_addSbdFilter();
+
+ /**
+ * Remove talker/filter.
+ * This is a wrapper function that takes the parameters for the real removeTalker from the
+ * widgets to later call it.
+ */
+ void slot_removeTalker();
+ void slot_removeNormalFilter();
+ void slot_removeSbdFilter();
+
+ /**
+ * This slot is called whenever user clicks the higher*Priority button (up).
+ */
+ void slot_higherTalkerPriority();
+ void slot_higherNormalFilterPriority();
+ void slot_higherSbdFilterPriority();
+
+ /**
+ * This slot is called whenever user clicks the lower*Priority button (down).
+ */
+ void slot_lowerTalkerPriority();
+ void slot_lowerNormalFilterPriority();
+ void slot_lowerSbdFilterPriority();
+
+ /**
+ * Update the status of the Talker/Filter buttons.
+ */
+ void updateTalkerButtons();
+ void updateFilterButtons();
+ void updateSbdButtons();
+
+ /**
+ * This signal is emitted whenever user checks/unchecks the Enable TTS System check box.
+ */
+ void enableKttsdToggled(bool checked);
+
+ /**
+ * This signal is emitted whenever user checks/unchecks the GStreamer radio button.
+ */
+ void slotGstreamerRadioButton_toggled(bool state);
+
+ /**
+ * This signal is emitted whenever user checks/unchecks the ALSA radio button.
+ */
+ void slotAlsaRadioButton_toggled(bool state);
+
+ /**
+ * This is emitted whenever user activates the ALSA pcm combobox.
+ */
+ void slotPcmComboBox_activated();
+
+ /**
+ * This signal is emitted whenever user checks/unchecks the aKode radio button.
+ */
+ void slotAkodeRadioButton_toggled(bool state);
+
+ /**
+ * User has requested to display the Talker/Filter Configuration Dialog.
+ */
+ void slot_configureTalker();
+ void slot_configureNormalFilter();
+ void slot_configureSbdFilter();
+
+ /**
+ * Slots for the Talker/Filter Configuration dialogs.
+ */
+ void slotConfigTalkerDlg_ConfigChanged();
+ void slotConfigFilterDlg_ConfigChanged();
+ void slotConfigTalkerDlg_DefaultClicked();
+ void slotConfigFilterDlg_DefaultClicked();
+ void slotConfigTalkerDlg_CancelClicked();
+ void slotConfigFilterDlg_CancelClicked();
+
+ /**
+ * Slots for Speed setting.
+ */
+ void timeBox_valueChanged(int percentValue);
+ void timeSlider_valueChanged(int sliderValue);
+
+ /**
+ * Keep Audio CheckBox slot.
+ */
+ void keepAudioCheckBox_toggled(bool checked);
+
+ /**
+ * Notify tab slots.
+ */
+ void slotNotifyEnableCheckBox_toggled(bool checked);
+ void slotNotifyAddButton_clicked();
+ void slotNotifyRemoveButton_clicked();
+ void slotNotifyClearButton_clicked();
+ void slotNotifyLoadButton_clicked();
+ void slotNotifySaveButton_clicked();
+ void slotNotifyListView_selectionChanged();
+ void slotNotifyPresentComboBox_activated(int index);
+ void slotNotifyActionComboBox_activated(int index);
+ void slotNotifyTestButton_clicked();
+ void slotNotifyMsgLineEdit_textChanged(const QString& text);
+ void slotNotifyTalkerButton_clicked();
+
+ /**
+ * Other slots.
+ */
+ void slotTabChanged();
+};
+
+/// This is a small helper class to detect when user checks/unchecks a Filter in Filters tab
+/// and emit changed() signal.
+class KttsCheckListItem : public QCheckListItem
+{
+ public:
+ KttsCheckListItem( QListView *parent,
+ const QString &text, Type tt = RadioButtonController,
+ KCMKttsMgr* kcmkttsmgr = 0);
+ KttsCheckListItem( QListView *parent, QListViewItem *after,
+ const QString &text, Type tt = RadioButtonController,
+ KCMKttsMgr* kcmkttsmgr = 0);
+
+ protected:
+ virtual void stateChange(bool);
+
+ private:
+ KCMKttsMgr* m_kcmkttsmgr;
+};
+
+#endif
diff --git a/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui b/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui
new file mode 100644
index 0000000..36942a3
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui
@@ -0,0 +1,1928 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KCMKttsMgrWidget</class>
+<author>Gary Cramblitt</author>
+<widget class="KCModule">
+ <property name="name">
+ <cstring>KCMKttsMgrWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>638</width>
+ <height>382</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>mainTab</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>enableKttsdCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Enable Text-to-Speech System (KTTSD)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check to start the KTTS Deamon and enable Text-to-Speech.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>embedInSysTrayCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Always em&amp;bed Text-to-Speech Manager in system tray</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, KTTSMgr displays an icon in the system tray, and clicking OK or Cancel buttons does not stop KTTSMgr. Use system tray context menu to quit KTTSMgr. This setting takes effect when KTTSMgr is next started. This setting has no effect when running in the KDE Control Center.</string>
+ </property>
+ </widget>
+ <spacer row="6" column="1">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>showMainWindowOnStartupCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Show &amp;main window on startup</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, the KTTSMgr window is displayed when KTTSMgr starts. When unchecked, click on the icon in the system tray to display the KTTSMgr window.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="5" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout5_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>autoexitMgrCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;xit when speaking is finished</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, and KTTSMgr was automatically started when speech began, automatically exits when speech has finished. Does not automatically exit if KTTSMgr was started manually or started from the Control Center.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>autostartMgrCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Sta&amp;rt minimized in system tray when speaking</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, if KTTSMgr is not already running and speech begins, starts KTTSMgr and displays an icon in the system tray. &lt;em&gt;Note&lt;em&gt;: KTTSMgr only automatically starts for text jobs having 5 sentences or more.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Talkers</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>ID</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Language</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Speech Synthesizer</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Voice</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Gender</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Volume</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Rate</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>talkersList</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of all the configured Talkers. A Talker is a speech synthesizer that has been configured with a language, voice, gender, speaking rate, and volume. Talkers higher in the list have higher priority. The topmost Talker will be used when no talker attributes have been specified by an application.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addTalkerButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to add and configure a new Talker (speech synthesizer).</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>higherTalkerPriorityButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>U&amp;p</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>lowerTalkerPriorityButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Do&amp;wn</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>configureTalkerButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Edit...</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to configure options for the highlighted Talker.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>removeTalkerButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to remove the highlighted Talker.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer11</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Notifications</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>notifyGroup</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KListView" row="1" column="0">
+ <column>
+ <property name="text">
+ <string>Application/Event</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Action</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Talker</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>notifyListView</cstring>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of configured application events and actions to be taken when received. The "default" event governs all events not specifically configured.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>notifyPresentLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Notifications to speak:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>notifyWhatComboBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Applies only to the default event. Does not affect application-specific events. Only events that display in the manner which you select will be spoken.</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>notifyPresentComboBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Applies only to the default event. Does not affect application-specific events. Only events that display in the manner which you select will be spoken.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout28</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifyAddButton</cstring>
+ </property>
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to configure notification for a specific application event.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifyRemoveButton</cstring>
+ </property>
+ <property name="text">
+ <string>Re&amp;move</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to remove a specific notification event from the list. You cannot remove the default event.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer16</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>152</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifyClearButton</cstring>
+ </property>
+ <property name="text">
+ <string>Cl&amp;ear</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Removes all the application specific events. The default event remains.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifyLoadButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Load...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to read configured notification events from a file.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifySaveButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Save...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to write all the configured application events to a file.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0">
+ <property name="name">
+ <cstring>notifyExceptionActionLayout</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>notifyTestButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Click to test notification</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click this button to test the notification. A sample message will be spoken. Note: The Text-to-Speech system must be enabled.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>notifyActionLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ac&amp;tion:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>notifyActionComboBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Specifies how KTTS should speak the event when received. If you select "Speak custom text", enter the text in the box. You may use the following substitution strings in the text:&lt;dl&gt;&lt;dt&gt;%e&lt;/dt&gt;&lt;dd&gt;Name of the event&lt;/dd&gt;&lt;dt&gt;%a&lt;/dt&gt;&lt;dd&gt;Application that sent the event&lt;/dd&gt;&lt;dt&gt;%m&lt;/dt&gt;&lt;dd&gt;The message sent by the application&lt;/dd&gt;&lt;/dl&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="3">
+ <property name="name">
+ <cstring>notifyMsgLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Specifies how KTTS should speak the event when received. If you select "Speak custom text", enter the text in the box. You may use the following substitution strings in the text:&lt;dl&gt;&lt;dt&gt;%e&lt;/dt&gt;&lt;dd&gt;Name of the event&lt;/dd&gt;&lt;dt&gt;%a&lt;/dt&gt;&lt;dd&gt;Application that sent the event&lt;/dd&gt;&lt;dt&gt;%m&lt;/dt&gt;&lt;dd&gt;The message sent by the application&lt;/dd&gt;&lt;/dl&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>notifyActionComboBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Specifies how KTTS should speak the event when received. If you select "Speak custom text", enter the text in the box. You may use the following substitution strings in the text:&lt;dl&gt;&lt;dt&gt;%e&lt;/dt&gt;&lt;dd&gt;Name of the event&lt;/dd&gt;&lt;dt&gt;%a&lt;/dt&gt;&lt;dd&gt;Application that sent the event&lt;/dd&gt;&lt;dt&gt;%m&lt;/dt&gt;&lt;dd&gt;The message sent by the application&lt;/dd&gt;&lt;/dl&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="4" column="0">
+ <property name="name">
+ <cstring>layout19_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>notifyTalkerLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Talke&amp;r:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>notifyTalkerLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The Talker that will speak the notification. The "default" Talker is the topmost talker listed on the Talkers tab.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>notifyTalkerLineEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="paletteForegroundColor">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The Talker that will speak the notification. The "default" Talker is the topmost talker listed on the Talkers tab.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>notifyTalkerButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to select the Talker to speak the notification.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout17</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>notifyEnableCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Speak notifications (&amp;KNotify)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked and KTTS is enabled, notification events from applications sent via KNotify will be spoken according to the options you set on this tab.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>notifyExcludeEventsWithSoundCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;xclude notifications with a sound</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, notification events that have a sound will not be spoken.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Filters</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Filter</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>filtersList</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of all the configured Filters. Filters higher in the list are applied first. Filters modify text before it is spoken. They can be used to substitute for mispronounced words, transform XML from one form to another, or change the default Talker to be used for speech output.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9_2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addFilterButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to add and configure a new Filter.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>higherFilterPriorityButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>U&amp;p</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to move selected filter up in the list. Filters higher in the list are applied first.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>lowerFilterPriorityButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Do&amp;wn</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to move a filter down in the list. Filters lower in the list are applied last.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>configureFilterButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Edit...</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to configure options for the highlighted Filter.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>removeFilterButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to remove the highlighted Filter.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer11_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout18</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Sentence Boundary Detector</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>sbdsList</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of all the configured Sentence Boundary Detector (SBD) Filters. SBDs break long text jobs up into sentences, which reduces the time before a job begins speaking, and permits you to advance or rewind through a job. SBDs are applied in the order listed (top to bottom) after all the normal filters at the top of this screen have been applied. Filtering stops when the first SBD modifies the text.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout16</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>sbdButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Co&amp;nfigure</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click this button to edit the Sentence Boundary Detector (SBD) configuration or add additional SBD filters.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer11_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>11</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Interruption</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>textPreSnd</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Pre-sound box and choose a Pre-sound audio file, which will sound when a text job is interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>textPostMsg</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Post-message box and enter a Post-message, which will be spoken when a text job resumes after being interrupted by another message.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>textPostMsgCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Post-&amp;message:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Post-message box and enter a Post-message, which will be spoken when a text job resumes after being interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>textPreSndCheck</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Pre-sou&amp;nd:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Pre-sound box and choose a Pre-sound audio file, which will sound when a text job is interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>textPreMsgCheck</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Pre-message:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Pre-message box and enter a Pre-message, which will be spoken whenever a text job is interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="3" column="1">
+ <property name="name">
+ <cstring>textPostSnd</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Post-sound and choose a Post-sound audio file, which will sound before a text job resumes after being interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0">
+ <property name="name">
+ <cstring>textPostSndCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Post-s&amp;ound:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Post-sound and choose a Post-sound audio file, which will sound before a text job resumes after being interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>textPreMsg</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Pre-message box and enter a Pre-message, which will be spoken whenever a text job is interrupted by another message.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>180</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>A&amp;udio</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>keepAudioCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Keep audio files:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this if you want to keep the generated audio (wav) files. You will find them in the indicated directory.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>keepAudioPath</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Specify the directory in which the audio files will be copied.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>timeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Speed:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>timeSlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>90</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>audioButtonGroup</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Out&amp;put Using</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Select the audio output method desired. If you select &lt;b&gt;GStreamer&lt;/b&gt;, you must also select a &lt;b&gt;Sink&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: You must have GStreamer &gt;= 0.87 to use GStreamer.&lt;/p&gt;</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>sinkLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Sink:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sound sink to be used for GStreamer output.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>sinkComboBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sound sink to be used for GStreamer output.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="1">
+ <property name="name">
+ <cstring>layout8_2_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>akodeSinkLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Sink:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sound sink to be used for aKode output.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>akodeComboBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sink to be used for aKode output. Select "auto" to let aKode pick the best output method.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>gstreamerRadioButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>GStrea&amp;mer</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Check to use the GStreamer audio output system. You must also select a &lt;b&gt;Sink&lt;/b&gt; plugin.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>artsRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string>a&amp;Rts</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check to use the KDE aRts system for audio output.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>akodeRadioButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>aKode</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Check to use aKode for audio output. You must also select a &lt;b&gt;Sink&lt;/b&gt;.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>alsaRadioButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>ALSA</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>-1</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check to use Advanced Linux Sound Architecture (ALSA) for audio output.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>pcmLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Device:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sound sink to be used for GStreamer output.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>pcmComboBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the PCM device to be used for ALSA output. Select "default" to use the default ALSA device.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>pcmCustom</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>enableKttsdCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>embedInSysTrayCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>showMainWindowOnStartupCheckBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>embedInSysTrayCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>showMainWindowOnStartupCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>artsRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>gstreamerRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>sinkComboBox</sender>
+ <signal>activated(int)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>autostartMgrCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>autoexitMgrCheckBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>autostartMgrCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>autoexitMgrCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>pcmComboBox</sender>
+ <signal>activated(int)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>alsaRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>akodeRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>akodeComboBox</sender>
+ <signal>activated(int)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPreMsg</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPreMsgCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textPreMsg</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>textPreMsgCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPreSndCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textPreSnd</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>textPreSndCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPreSnd</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPostMsgCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textPostMsg</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>textPostMsgCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPostMsg</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPostSndCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textPostSnd</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>textPostSndCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPostSnd</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>pcmCustom</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>mainTab</tabstop>
+ <tabstop>enableKttsdCheckBox</tabstop>
+ <tabstop>embedInSysTrayCheckBox</tabstop>
+ <tabstop>showMainWindowOnStartupCheckBox</tabstop>
+ <tabstop>autostartMgrCheckBox</tabstop>
+ <tabstop>autoexitMgrCheckBox</tabstop>
+ <tabstop>talkersList</tabstop>
+ <tabstop>addTalkerButton</tabstop>
+ <tabstop>higherTalkerPriorityButton</tabstop>
+ <tabstop>lowerTalkerPriorityButton</tabstop>
+ <tabstop>configureTalkerButton</tabstop>
+ <tabstop>removeTalkerButton</tabstop>
+ <tabstop>notifyEnableCheckBox</tabstop>
+ <tabstop>notifyExcludeEventsWithSoundCheckBox</tabstop>
+ <tabstop>notifyAddButton</tabstop>
+ <tabstop>notifyRemoveButton</tabstop>
+ <tabstop>notifyClearButton</tabstop>
+ <tabstop>notifyLoadButton</tabstop>
+ <tabstop>notifySaveButton</tabstop>
+ <tabstop>notifyListView</tabstop>
+ <tabstop>notifyPresentComboBox</tabstop>
+ <tabstop>notifyActionComboBox</tabstop>
+ <tabstop>notifyTestButton</tabstop>
+ <tabstop>notifyMsgLineEdit</tabstop>
+ <tabstop>notifyTalkerLineEdit</tabstop>
+ <tabstop>notifyTalkerButton</tabstop>
+ <tabstop>filtersList</tabstop>
+ <tabstop>addFilterButton</tabstop>
+ <tabstop>higherFilterPriorityButton</tabstop>
+ <tabstop>lowerFilterPriorityButton</tabstop>
+ <tabstop>configureFilterButton</tabstop>
+ <tabstop>removeFilterButton</tabstop>
+ <tabstop>sbdsList</tabstop>
+ <tabstop>sbdButton</tabstop>
+ <tabstop>textPreMsgCheck</tabstop>
+ <tabstop>textPreMsg</tabstop>
+ <tabstop>textPreSndCheck</tabstop>
+ <tabstop>textPreSnd</tabstop>
+ <tabstop>textPostMsgCheck</tabstop>
+ <tabstop>textPostMsg</tabstop>
+ <tabstop>textPostSndCheck</tabstop>
+ <tabstop>textPostSnd</tabstop>
+ <tabstop>artsRadioButton</tabstop>
+ <tabstop>sinkComboBox</tabstop>
+ <tabstop>pcmComboBox</tabstop>
+ <tabstop>akodeComboBox</tabstop>
+ <tabstop>timeBox</tabstop>
+ <tabstop>keepAudioCheckBox</tabstop>
+ <tabstop>keepAudioPath</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">klocale.h</include>
+ <include location="global" impldecl="in implementation">klocale.h</include>
+ <include location="global" impldecl="in implementation">kdebug.h</include>
+</includes>
+<signals>
+ <signal>configChanged()</signal>
+</signals>
+<slots>
+ <slot access="private">slotConfigChanged()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="6"/>
+<includehints>
+ <includehint>kcmodule.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui.h b/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui.h
new file mode 100644
index 0000000..206524a
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui.h
@@ -0,0 +1,16 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void KCMKttsMgrWidget::slotConfigChanged(){
+ // kdDebug() << "Running: KCMKttsMgrWidget:slotConfigChanged():" << endl;
+ emit configChanged();
+}
+
+
+
diff --git a/kttsd/kcmkttsmgr/selectevent.cpp b/kttsd/kcmkttsmgr/selectevent.cpp
new file mode 100644
index 0000000..dc65fa4
--- /dev/null
+++ b/kttsd/kcmkttsmgr/selectevent.cpp
@@ -0,0 +1,149 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Dialog to allow user to select a KNotify application and event.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qcombobox.h>
+
+// KDE includes
+#include <kstandarddirs.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <klistview.h>
+#include <kiconloader.h>
+
+// KTTS includes
+#include "utils.h"
+#include "selectevent.h"
+
+SelectEvent::SelectEvent(QWidget* parent, const char* name, WFlags fl, const QString& initEventSrc)
+ : SelectEventWidget(parent,name,fl)
+{
+ // Load list of event sources (applications).
+ QStringList fullpaths =
+ KGlobal::dirs()->findAllResources("data", "*/eventsrc", false, true );
+ QStringList::ConstIterator it = fullpaths.begin();
+ QStringList relativePaths;
+ for ( ; it != fullpaths.end(); ++it)
+ {
+ QString relativePath = *it;
+ if ( relativePath.at(0) == '/' && KStandardDirs::exists( relativePath ) )
+ {
+ relativePath = makeRelative( relativePath );
+ relativePaths.append(relativePath);
+ }
+ }
+ relativePaths.sort();
+ it = relativePaths.begin();
+ for ( ; it != relativePaths.end(); ++it)
+ {
+ QString relativePath = *it;
+ if ( !relativePath.isEmpty() )
+ {
+ KConfig* config = new KConfig(relativePath, true, false, "data");
+ config->setGroup( QString::fromLatin1("!Global!") );
+ QString icon = config->readEntry(QString::fromLatin1("IconName"),
+ QString::fromLatin1("misc"));
+ QString description = config->readEntry( QString::fromLatin1("Comment"),
+ i18n("No description available") );
+ delete config;
+ int index = relativePath.find( '/' );
+ QString appname;
+ if ( index >= 0 )
+ appname = relativePath.left( index );
+ else
+ kdDebug() << "Cannot determine application name from path: " << relativePath << endl;
+ eventSrcComboBox->insertItem( SmallIcon( icon ), description );
+ m_eventSrcNames.append( appname );
+ if ( appname == initEventSrc ) KttsUtils::setCbItemFromText(eventSrcComboBox, description);
+ }
+ }
+ slotEventSrcComboBox_activated(eventSrcComboBox->currentItem());
+ connect (eventSrcComboBox, SIGNAL(activated(int)), this, SLOT(slotEventSrcComboBox_activated(int)));
+}
+
+SelectEvent::~SelectEvent() { }
+
+void SelectEvent::slotEventSrcComboBox_activated(int index)
+{
+ eventsListView->clear();
+ QListViewItem* item = 0;
+ QString eventSrc = m_eventSrcNames[index];
+ QString configFilename = eventSrc + QString::fromLatin1( "/eventsrc" );
+ KConfig* config = new KConfig( configFilename, true, false, "data" );
+ QStringList eventNames = config->groupList();
+ uint eventNamesCount = eventNames.count();
+ for (uint ndx = 0; ndx < eventNamesCount; ++ndx)
+ {
+ QString eventName = eventNames[ndx];
+ if ( eventName != "!Global!" )
+ {
+ config->setGroup( eventName );
+ QString eventDesc = config->readEntry( QString::fromLatin1( "Comment" ),
+ config->readEntry( QString::fromLatin1( "Name" )));
+ if ( !item )
+ item = new KListViewItem( eventsListView, eventDesc, eventName );
+ else
+ item = new KListViewItem( eventsListView, item, eventDesc, eventName );
+ }
+ }
+ delete config;
+ eventsListView->sort();
+ item = eventsListView->lastChild();
+ QString eventDesc = i18n("All other %1 events").arg(eventSrcComboBox->currentText());
+ if ( !item )
+ item = new KListViewItem( eventsListView, eventDesc, "default" );
+ else
+ item = new KListViewItem( eventsListView, item, eventDesc, "default" );
+
+}
+
+QString SelectEvent::getEventSrc()
+{
+ return m_eventSrcNames[eventSrcComboBox->currentItem()];
+}
+
+QString SelectEvent::getEvent()
+{
+ QListViewItem* item = eventsListView->currentItem();
+ if ( item )
+ return item->text(1);
+ else
+ return QString::null;
+}
+
+// returns e.g. "kwin/eventsrc" from a given path
+// "/opt/kde3/share/apps/kwin/eventsrc"
+QString SelectEvent::makeRelative( const QString& fullPath )
+{
+ int slash = fullPath.findRev( '/' ) - 1;
+ slash = fullPath.findRev( '/', slash );
+
+ if ( slash < 0 )
+ return QString::null;
+
+ return fullPath.mid( slash+1 );
+}
+
+
+#include "selectevent.moc"
diff --git a/kttsd/kcmkttsmgr/selectevent.h b/kttsd/kcmkttsmgr/selectevent.h
new file mode 100644
index 0000000..1ca4e21
--- /dev/null
+++ b/kttsd/kcmkttsmgr/selectevent.h
@@ -0,0 +1,69 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Dialog to allow user to select a KNotify application and event.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _SELECTEVENT_H_
+#define _SELECTEVENT_H_
+
+#include "selecteventwidget.h"
+
+class SelectEvent : public SelectEventWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ * @param parent Inherited KDialog parameter.
+ * @param name Inherited KDialog parameter.
+ * @param initEventSrc Event source to start with.
+ */
+ SelectEvent(QWidget* parent = 0, const char* name = 0, WFlags fl = 0,
+ const QString& initEventSrc = QString::null );
+
+ /**
+ * Destructor.
+ */
+ ~SelectEvent();
+
+ /**
+ * Returns the chosen event source (app name).
+ */
+ QString getEventSrc();
+
+ /**
+ * Returns the chosen event.
+ */
+ QString getEvent();
+
+private slots:
+ void slotEventSrcComboBox_activated(int index);
+
+private:
+ // returns e.g. "kwin/eventsrc" from a given path
+ // "/opt/kde3/share/apps/kwin/eventsrc"
+ QString makeRelative( const QString& fullPath );
+
+ QStringList m_eventSrcNames;
+};
+
+#endif // _SELECTEVENT_H_
diff --git a/kttsd/kcmkttsmgr/selecteventwidget.ui b/kttsd/kcmkttsmgr/selecteventwidget.ui
new file mode 100644
index 0000000..13b91f1
--- /dev/null
+++ b/kttsd/kcmkttsmgr/selecteventwidget.ui
@@ -0,0 +1,62 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>SelectEventWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SelectEventWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>472</width>
+ <height>326</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>eventSrcLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Event source:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>eventSrcComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>eventSrcComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="KListView" row="1" column="0" rowspan="1" colspan="2">
+ <column>
+ <property name="text">
+ <string>Events</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>eventsListView</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/kttsd.lsm b/kttsd/kttsd.lsm
new file mode 100644
index 0000000..8c5679c
--- /dev/null
+++ b/kttsd/kttsd.lsm
@@ -0,0 +1,27 @@
+Begin4
+Title: KTTS - the KDE Text-to-Speech system
+Version: 0.3.0
+Entered-date: 2005/02/26
+Description: KTTS -- KDE Text-to-Speech -- is a subsystem within the KDE
+ desktop for conversion of text to audible speech. KTTS is
+ currently under development and aims to become the standard
+ subsystem for all KDE applications to provide speech output.
+Keywords: KDE accessibility kdeaccessibility TTS Text-to-Speech KTTSD
+ kttsmgr festival flite hadifix MBROLA freetts epos SSML
+Author: pupeno@pupeno.com (José Pablo Ezequiel Fernández)
+ garycramblitt@comcast.net (Gary Cramblitt)
+ gunnar@schmi-dt.de (Gunnar Schmi Dt)
+ ojschmidt@kde.org (Olaf Schmidt)
+ ceruleanblaze@gmail.com (Paul Giannaros)
+Maintained-by: garycramblitt@comcast.net (Gary Cramblitt)
+Home-page: http://accessibility.kde.org/developer/kttsd/
+Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/KDE3.x/
+ 1.7K kttsd.lsm
+ 3.5M kttsd-0.3.0.src.tar.bz2
+ 4M kttsd_0.3.0-1_i386.deb
+ 28K kttsd-gstreamer_0.3.0-1_i386.deb
+Alternate-site:
+Original-site:
+Platforms: KDE 3.2 or greater
+Copying-policy: GPL
+End
diff --git a/kttsd/kttsd/Makefile.am b/kttsd/kttsd/Makefile.am
new file mode 100644
index 0000000..a553636
--- /dev/null
+++ b/kttsd/kttsd/Makefile.am
@@ -0,0 +1,51 @@
+# Include paths. INCLUDES is maintained by KDevelop, AM_CPPFLAGS is the preferred variable,
+# so keep them synchronized.
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd \
+ -I$(kde_includes)/arts \
+ $(KTTS_KSPEECH_INCLUDE) \
+ $(all_includes)
+
+# Let am_edit/unsermake handle all of the metasource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# APPLICATION SECTION
+#########################################################################
+# This is the program that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+bin_PROGRAMS = kttsd
+
+kspeech_DIR = $(KTTS_KSPEECH_DIR)
+kspeechsink_DIR = $(KTTS_KSPEECH_DIR)
+
+# The source, library search path, and link libraries.
+# Note: .skel files cause DCOPIDL compiler to generate _skel.cpp file and compile it.
+kttsd_SOURCES = \
+ kspeech.skel kspeechsink.stub\
+ main.cpp \
+ kttsd.cpp \
+ speaker.cpp \
+ speechdata.cpp \
+ kttsd.skel \
+ threadedplugin.cpp \
+ ssmlconvert.cpp \
+ filtermgr.cpp \
+ talkermgr.cpp
+
+kttsd_LDFLAGS = -avoid-version -module $(all_libraries) $(KDE_RPATH)
+kttsd_LDADD = \
+ $(top_builddir)/kttsd/libkttsd/libkttsd.la \
+ $(LIB_KDECORE) \
+ $(LIB_KIO) \
+ $(LIB_KUTILS)
+
+# Install desktop file to standard services directory.
+kde_services_DATA = kttsd.desktop
+
+# Install data.
+kttsddatadir = $(kde_datadir)/kttsd/xslt/
+kttsddata_DATA = SSMLtoPlainText.xsl
+
+noinst_HEADERS = threadedplugin.h ssmlconvert.h
+
diff --git a/kttsd/kttsd/SSMLtoPlainText.xsl b/kttsd/kttsd/SSMLtoPlainText.xsl
new file mode 100644
index 0000000..c1c087d
--- /dev/null
+++ b/kttsd/kttsd/SSMLtoPlainText.xsl
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text" encoding="ISO-8859-1" indent="no"/>
+
+<xsl:template match="speak">
+<xsl:value-of select="."/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/kttsd/kttsd/filtermgr.cpp b/kttsd/kttsd/filtermgr.cpp
new file mode 100644
index 0000000..3b0474b
--- /dev/null
+++ b/kttsd/kttsd/filtermgr.cpp
@@ -0,0 +1,405 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Description:
+ Filters text, applying each configured Filter in turn.
+ Runs asynchronously, emitting Finished() signal when all Filters have run.
+
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// KDE includes.
+#include <kdebug.h>
+#include <kconfig.h>
+#include <ktrader.h>
+#include <kparts/componentfactory.h>
+#include <klocale.h>
+
+// FilterMgr includes.
+#include "filtermgr.h"
+#include "filtermgr.moc"
+
+/**
+ * Constructor.
+ */
+FilterMgr::FilterMgr( QObject *parent, const char *name) :
+ KttsFilterProc(parent, name)
+{
+ // kdDebug() << "FilterMgr::FilterMgr: Running" << endl;
+ m_state = fsIdle;
+ m_noSBD = false;
+ m_supportsHTML = false;
+ m_talkerCode = 0;
+}
+
+/**
+ * Destructor.
+ */
+FilterMgr::~FilterMgr()
+{
+ // kdDebug() << "FilterMgr::~FilterMgr: Running" << endl;
+ if ( m_state == fsFiltering )
+ stopFiltering();
+ m_filterList.setAutoDelete( TRUE );
+ m_filterList.clear();
+}
+
+/**
+ * Loads and initializes the filters.
+ * @param config Settings object.
+ * @return False if FilterMgr is not ready to filter.
+ */
+bool FilterMgr::init(KConfig *config, const QString& /*configGroup*/)
+{
+ // Load each of the filters and initialize.
+ config->setGroup("General");
+ QStringList filterIDsList = config->readListEntry("FilterIDs", ',');
+ // kdDebug() << "FilterMgr::init: FilterIDs = " << filterIDsList << endl;
+ // If no filters have been configured, automatically configure the standard SBD.
+ if (filterIDsList.isEmpty())
+ {
+ config->setGroup("Filter_1");
+ config->writeEntry("DesktopEntryName", "kttsd_sbdplugin");
+ config->writeEntry("Enabled", true);
+ config->writeEntry("IsSBD", true);
+ config->writeEntry("MultiInstance", true);
+ config->writeEntry("SentenceBoundary", "\\1\\t");
+ config->writeEntry("SentenceDelimiterRegExp", "([\\.\\?\\!\\:\\;])(\\s|$|(\\n *\\n))");
+ config->writeEntry("UserFilterName", i18n("Standard Sentence Boundary Detector"));
+ config->setGroup("General");
+ config->writeEntry("FilterIDs", "1");
+ filterIDsList = config->readListEntry("FilterIDs", ',');
+ }
+ if ( !filterIDsList.isEmpty() )
+ {
+ QStringList::ConstIterator itEnd = filterIDsList.constEnd();
+ for (QStringList::ConstIterator it = filterIDsList.constBegin(); it != itEnd; ++it)
+ {
+ QString filterID = *it;
+ QString groupName = "Filter_" + filterID;
+ config->setGroup( groupName );
+ QString desktopEntryName = config->readEntry( "DesktopEntryName" );
+ // If a DesktopEntryName is not in the config file, it was configured before
+ // we started using them, when we stored translated plugin names instead.
+ // Try to convert the translated plugin name to a DesktopEntryName.
+ // DesktopEntryNames are better because user can change their desktop language
+ // and DesktopEntryName won't change.
+ if (desktopEntryName.isEmpty())
+ {
+ QString filterPlugInName = config->readEntry("PlugInName", QString::null);
+ // See if the translated name will untranslate. If not, well, sorry.
+ desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ // Record the DesktopEntryName from now on.
+ if (!desktopEntryName.isEmpty()) config->writeEntry("DesktopEntryName", desktopEntryName);
+ }
+ if (config->readBoolEntry("Enabled") || config->readBoolEntry("IsSBD"))
+ {
+ // kdDebug() << "FilterMgr::init: filterID = " << filterID << endl;
+ KttsFilterProc* filterProc = loadFilterPlugin( desktopEntryName );
+ if ( filterProc )
+ {
+ filterProc->init( config, groupName );
+ m_filterList.append( filterProc );
+ }
+ if (config->readEntry("DocType").contains("html") ||
+ config->readEntry("RootElement").contains("html"))
+ m_supportsHTML = true;
+ }
+ }
+ }
+ return true;
+}
+
+/**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * If so, the filter should implement @ref setSbRegExp() .
+ * @return True if this filter is a SBD.
+ */
+/*virtual*/ bool FilterMgr::isSBD() { return true; }
+
+/**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+/*virtual*/ bool FilterMgr::supportsAsync() { return true; }
+
+/**
+ * Synchronously convert text.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ * @return Converted text.
+ */
+QString FilterMgr::convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId)
+{
+ m_text = inputText;
+ m_talkerCode = talkerCode;
+ m_appId = appId;
+ m_filterIndex = -1;
+ m_filterProc = 0;
+ m_state = fsFiltering;
+ m_async = false;
+ while ( m_state == fsFiltering )
+ nextFilter();
+ return m_text;
+}
+
+/**
+ * Aynchronously convert input.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ *
+ * When the input text has been converted, filteringFinished signal will be emitted
+ * and caller can retrieve using getOutput();
+*/
+bool FilterMgr::asyncConvert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId)
+{
+ m_text = inputText;
+ m_talkerCode = talkerCode;
+ m_appId = appId;
+ m_filterIndex = -1;
+ m_filterProc = 0;
+ m_state = fsFiltering;
+ m_async = true;
+ nextFilter();
+ return true;
+}
+
+// Finishes up with current filter (if any) and goes on to the next filter.
+void FilterMgr::nextFilter()
+{
+ if ( m_filterProc )
+ {
+ if ( m_filterProc->supportsAsync() )
+ {
+ m_text = m_filterProc->getOutput();
+ m_filterProc->ackFinished();
+ disconnect( m_filterProc, SIGNAL(filteringFinished()), this, SLOT(slotFilteringFinished()) );
+ }
+ // if ( m_filterProc->wasModified() )
+ // kdDebug() << "FilterMgr::nextFilter: Filter# " << m_filterIndex << " modified the text." << endl;
+ if ( m_filterProc->wasModified() && m_filterProc->isSBD() )
+ {
+ m_state = fsFinished;
+ // Post an event which will be later emitted as a signal.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 301);
+ QApplication::postEvent(this, ev);
+ return;
+ }
+ }
+ ++m_filterIndex;
+ if ( m_filterIndex == static_cast<int>(m_filterList.count()) )
+ {
+ m_state = fsFinished;
+ // Post an event which will be later emitted as a signal.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 301);
+ QApplication::postEvent(this, ev);
+ return;
+ }
+ m_filterProc = m_filterList.at(m_filterIndex);
+ if ( m_noSBD && m_filterProc->isSBD() )
+ {
+ m_state = fsFinished;
+ // Post an event which will be later emitted as a signal.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 301);
+ QApplication::postEvent(this, ev);
+ return;
+ }
+ m_filterProc->setSbRegExp( m_re );
+ if ( m_async )
+ {
+ if ( m_filterProc->supportsAsync() )
+ {
+ // kdDebug() << "FilterMgr::nextFilter: calling asyncConvert on filter " << m_filterIndex << endl;
+ connect( m_filterProc, SIGNAL(filteringFinished()), this, SLOT(slotFilteringFinished()) );
+ if ( !m_filterProc->asyncConvert( m_text, m_talkerCode, m_appId ) )
+ {
+ disconnect( m_filterProc, SIGNAL(filteringFinished()), this, SLOT(slotFilteringFinished()) );
+ m_filterProc = 0;
+ nextFilter();
+ }
+ } else {
+ m_text = m_filterProc->convert( m_text, m_talkerCode, m_appId );
+ nextFilter();
+ }
+ } else
+ m_text = m_filterProc->convert( m_text, m_talkerCode, m_appId );
+}
+
+// Received when each filter finishes.
+void FilterMgr::slotFilteringFinished()
+{
+ // kdDebug() << "FilterMgr::slotFilteringFinished: received signal from filter " << m_filterIndex << endl;
+ nextFilter();
+}
+
+bool FilterMgr::event ( QEvent * e )
+{
+ if ( e->type() == (QEvent::User + 301) )
+ {
+ // kdDebug() << "FilterMgr::event: emitting filteringFinished signal." << endl;
+ emit filteringFinished();
+ return true;
+ }
+ if ( e->type() == (QEvent::User + 302) )
+ {
+ // kdDebug() << "FilterMgr::event: emitting filteringStopped signal." << endl;
+ emit filteringStopped();
+ return true;
+ }
+ else return false;
+}
+
+/**
+ * Waits for filtering to finish.
+ */
+void FilterMgr::waitForFinished()
+{
+ if ( m_state != fsFiltering ) return;
+ disconnect(m_filterProc, SIGNAL(filteringFinished()), this, SLOT(slotFilteringFinished()) );
+ m_async = false;
+ m_filterProc->waitForFinished();
+ while ( m_state == fsFiltering )
+ nextFilter();
+}
+
+/**
+ * Returns the state of the FilterMgr.
+ */
+int FilterMgr::getState() { return m_state; }
+
+/**
+ * Returns the filtered output.
+ */
+QString FilterMgr::getOutput()
+{
+ return m_text;
+}
+
+/**
+ * Acknowledges the finished filtering.
+ */
+void FilterMgr::ackFinished()
+{
+ m_state = fsIdle;
+ m_text = QString::null;
+}
+
+/**
+ * Stops filtering. The filteringStopped signal will emit when filtering
+ * has in fact stopped.
+ */
+void FilterMgr::stopFiltering()
+{
+ if ( m_state != fsFiltering ) return;
+ if ( m_async )
+ disconnect( m_filterProc, SIGNAL(filteringFinished()), this, SLOT(slotFilteringFinished()) );
+ m_filterProc->stopFiltering();
+ m_state = fsIdle;
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 302);
+ QApplication::postEvent(this, ev);
+}
+
+/**
+ * Set Sentence Boundary Regular Expression.
+ * This method will only be called if the application overrode the default.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+/*virtual*/ void FilterMgr::setSbRegExp(const QString& re)
+{
+ m_re = re;
+}
+
+/**
+ * Do not call SBD filters.
+ */
+void FilterMgr::setNoSBD(bool noSBD) { m_noSBD = noSBD; }
+bool FilterMgr::noSBD() { return m_noSBD; }
+
+// Loads the processing plug in for a filter plug in given its DesktopEntryName.
+KttsFilterProc* FilterMgr::loadFilterPlugin(const QString& desktopEntryName)
+{
+ // kdDebug() << "FilterMgr::loadFilterPlugin: Running"<< endl;
+
+ // Find the plugin.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin",
+ QString("DesktopEntryName == '%1'").arg(desktopEntryName));
+
+ if (offers.count() == 1)
+ {
+ // When the entry is found, load the plug in
+ // First create a factory for the library
+ KLibFactory *factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if(factory){
+ // If the factory is created successfully, instantiate the KttsFilterConf class for the
+ // specific plug in to get the plug in configuration object.
+ int errorNo;
+ KttsFilterProc *plugIn =
+ KParts::ComponentFactory::createInstanceFromLibrary<KttsFilterProc>(
+ offers[0]->library().latin1(), NULL, offers[0]->library().latin1(),
+ QStringList(), &errorNo);
+ if(plugIn){
+ // If everything went ok, return the plug in pointer.
+ return plugIn;
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "FilterMgr::loadFilterPlugin: Unable to instantiate KttsFilterProc class for plugin " << desktopEntryName << " error: " << errorNo << endl;
+ return NULL;
+ }
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "FilterMgr::loadFilterPlugin: Unable to create Factory object for plugin "
+ << desktopEntryName << endl;
+ return NULL;
+ }
+ }
+ // The plug in was not found (unexpected behaviour, returns null).
+ kdDebug() << "FilterMgr::loadFilterPlugin: KTrader did not return an offer for plugin "
+ << desktopEntryName << endl;
+ return NULL;
+}
+
+/**
+ * Uses KTrader to convert a translated Filter Plugin Name to DesktopEntryName.
+ * @param name The translated plugin name. From Name= line in .desktop file.
+ * @return DesktopEntryName. The name of the .desktop file (less .desktop).
+ * QString::null if not found.
+ */
+QString FilterMgr::FilterNameToDesktopEntryName(const QString& name)
+{
+ if (name.isEmpty()) return QString::null;
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin");
+ for (uint ndx = 0; ndx < offers.count(); ++ndx)
+ if (offers[ndx]->name() == name) return offers[ndx]->desktopEntryName();
+ return QString::null;
+}
+
diff --git a/kttsd/kttsd/filtermgr.h b/kttsd/kttsd/filtermgr.h
new file mode 100644
index 0000000..d909128
--- /dev/null
+++ b/kttsd/kttsd/filtermgr.h
@@ -0,0 +1,199 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Description:
+ Filters text, applying each configured Filter in turn.
+ Runs asynchronously, emitting Finished() signal when all Filters have run.
+
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _FILTERMGR_H_
+#define _FILTERMGR_H_
+
+// Qt includes.
+#include <qptrlist.h>
+
+// KTTS includes.
+#include "filterproc.h"
+
+class KConfig;
+class TalkerCode;
+
+typedef QPtrList<KttsFilterProc> FilterList;
+
+class FilterMgr : public KttsFilterProc
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor.
+ */
+ FilterMgr(QObject *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor.
+ */
+ ~FilterMgr();
+
+ /**
+ * Initialize the filters.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * If so, the filter should implement @ref setSbRegExp() .
+ * @return True if this filter is a SBD.
+ */
+ virtual bool isSBD();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Synchronously convert text.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ * @return Converted text.
+ */
+ virtual QString convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+ /**
+ * Asynchronously convert input.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ *
+ * When the input text has been converted, filteringFinished signal will be emitted
+ * and caller can retrieve using getOutput();
+ */
+ virtual bool asyncConvert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+ /**
+ * Waits for filtering to finish.
+ */
+ virtual void waitForFinished();
+
+ /**
+ * Returns the state of the FilterMgr.
+ */
+ virtual int getState();
+
+ /**
+ * Returns the filtered output.
+ */
+ virtual QString getOutput();
+
+ /**
+ * Acknowledges the finished filtering.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Stops filtering. The filteringStopped signal will emit when filtering
+ * has in fact stopped.
+ */
+ virtual void stopFiltering();
+
+ /**
+ * Set Sentence Boundary Regular Expression.
+ * This method will only be called if the application overrode the default.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+ virtual void setSbRegExp(const QString& re);
+
+ /**
+ * Do not call SBD filters.
+ */
+ void setNoSBD(bool noSBD);
+ bool noSBD();
+
+ /**
+ * True if there is at least one XML Transformer filter for html.
+ */
+ bool supportsHTML() { return m_supportsHTML; }
+
+ protected:
+ bool event ( QEvent * e );
+
+ private slots:
+ void slotFilteringFinished();
+
+ private:
+ // Loads the processing plug in for a named filter plug in.
+ KttsFilterProc* loadFilterPlugin(const QString& plugInName);
+ // Finishes up with current filter (if any) and goes on to the next filter.
+ void nextFilter();
+ // Uses KTrader to convert a translated Filter Plugin Name to DesktopEntryName.
+ // @param name The translated plugin name. From Name= line in .desktop file.
+ // @return DesktopEntryName. The name of the .desktop file (less .desktop).
+ // QString::null if not found.
+ QString FilterNameToDesktopEntryName(const QString& name);
+
+ // List of filters.
+ FilterList m_filterList;
+ // Text being filtered.
+ QString m_text;
+ // Index to list of filters.
+ int m_filterIndex;
+ // Current filter.
+ KttsFilterProc* m_filterProc;
+ // True if calling filters asynchronously.
+ bool m_async;
+ // Talker Code.
+ TalkerCode* m_talkerCode;
+ // AppId.
+ QCString m_appId;
+ // Sentence Boundary regular expression (if app overrode the default).
+ QString m_re;
+ // True if any of the filters modified the text.
+ bool m_wasModified;
+ // FilterMgr state.
+ int m_state;
+ // True if SBD Filters should not be called.
+ bool m_noSBD;
+ // True if at least one XML Transformer for html is enabled.
+ bool m_supportsHTML;
+};
+
+#endif // _FILTERMGR_H_
diff --git a/kttsd/kttsd/kttsd.cpp b/kttsd/kttsd/kttsd.cpp
new file mode 100644
index 0000000..9ee841f
--- /dev/null
+++ b/kttsd/kttsd/kttsd.cpp
@@ -0,0 +1,1183 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KTTSD main class
+ -------------------
+ Copyright:
+ (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qcstring.h>
+#include <qclipboard.h>
+#include <qtextstream.h>
+#include <qtextcodec.h>
+#include <qfile.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <dcopclient.h>
+#include <knotifyclient.h>
+#include <krun.h>
+#include <kaboutdata.h>
+
+// KTTS includes.
+#include "notify.h"
+#include "kttsd.h"
+
+/**
+* This is the "main" module of KTTSD. It performs the following functions:
+* - Creates and destroys SpeechData and Speaker objects.
+* - Receives DCOP calls and dispatches them to SpeechData and Speaker.
+* - Receives signals from SpeechData and Speaker and converts them to DCOP signals.
+*
+* Note that most of the real tts work occurs in Speaker.
+*/
+
+KTTSD::KTTSD(const QCString& objId, QObject *parent, const char *name) :
+ DCOPObject(objId),
+ QObject(parent, name)
+{
+ // kdDebug() << "KTTSD::KTTSD Running" << endl;
+ m_speaker = 0;
+ m_talkerMgr = 0;
+ m_speechData = 0;
+ ready();
+}
+
+/*
+* Create and initialize the SpeechData object.
+*/
+bool KTTSD::initializeSpeechData()
+{
+ // Create speechData object.
+ if (!m_speechData)
+ {
+ m_speechData = new SpeechData();
+ connect (m_speechData, SIGNAL(textSet(const QCString&, const uint)),
+ this, SLOT(slotTextSet(const QCString&, const uint)));
+ connect (m_speechData, SIGNAL(textAppended(const QCString&, const uint, const int)),
+ this, SLOT(slotTextAppended(const QCString&, const uint, const int)));
+ connect (m_speechData, SIGNAL(textRemoved(const QCString&, const uint)),
+ this, SLOT(slotTextRemoved(const QCString&, const uint)));
+
+ // Hook KNotify signal.
+ if (!connectDCOPSignal(0, 0,
+ "notifySignal(QString,QString,QString,QString,QString,int,int,int,int)",
+ "notificationSignal(QString,QString,QString,QString,QString,int,int,int,int)",
+ false)) kdDebug() << "KTTSD:initializeSpeechData: connectDCOPSignal for knotify failed" << endl;
+ }
+ // Load configuration.
+ m_speechData->readConfig();
+
+ return true;
+}
+
+/*
+* Create and initialize the TalkerMgr object.
+*/
+bool KTTSD::initializeTalkerMgr()
+{
+ if (!m_talkerMgr)
+ {
+ if (!m_speechData) initializeSpeechData();
+
+ m_talkerMgr = new TalkerMgr(this, "kttsdtalkermgr");
+ int load = m_talkerMgr->loadPlugIns(m_speechData->config);
+ // If no Talkers configured, try to autoconfigure one, first in the user's
+ // desktop language, but if that fails, fallback to English.
+ if (load < 0)
+ {
+ QString languageCode = KGlobal::locale()->language();
+ if (m_talkerMgr->autoconfigureTalker(languageCode, m_speechData->config))
+ load = m_talkerMgr->loadPlugIns(m_speechData->config);
+ else
+ {
+ if (m_talkerMgr->autoconfigureTalker("en", m_speechData->config))
+ load = m_talkerMgr->loadPlugIns(m_speechData->config);
+ }
+ }
+ if (load < 0)
+ {
+ // TODO: Would really like to eliminate ALL GUI stuff from kttsd. Find
+ // a better way to do this.
+ delete m_speaker;
+ m_speaker = 0;
+ delete m_talkerMgr;
+ m_talkerMgr = 0;
+ delete m_speechData;
+ m_speechData = 0;
+ kdDebug() << "KTTSD::initializeTalkerMgr: no Talkers have been configured." << endl;
+ // Ask if user would like to run configuration dialog, but don't bug user unnecessarily.
+ QString dontAskConfigureKTTS = "DontAskConfigureKTTS";
+ KMessageBox::ButtonCode msgResult;
+ if (KMessageBox::shouldBeShownYesNo(dontAskConfigureKTTS, msgResult))
+ {
+ if (KMessageBox::questionYesNo(
+ 0,
+ i18n("KTTS has not yet been configured. At least one Talker must be configured. "
+ "Would you like to configure it now?"),
+ i18n("KTTS Not Configured"),
+ i18n("Configure"),
+ i18n("Do Not Configure"),
+ dontAskConfigureKTTS) == KMessageBox::Yes) msgResult = KMessageBox::Yes;
+ }
+ if (msgResult == KMessageBox::Yes) showDialog();
+ return false;
+ }
+ }
+ m_speechData->setTalkerMgr(m_talkerMgr);
+ return true;
+}
+
+/*
+* Create and initialize the Speaker object.
+*/
+bool KTTSD::initializeSpeaker()
+{
+ // kdDebug() << "KTTSD::initializeSpeaker: Instantiating Speaker" << endl;
+
+ if (!m_talkerMgr) initializeTalkerMgr();
+
+ // Create speaker object and load plug ins, checking for the return
+ m_speaker = new Speaker(m_speechData, m_talkerMgr);
+ connect (m_speaker, SIGNAL(textStarted(const QCString&, const uint)),
+ this, SLOT(slotTextStarted(const QCString&, const uint)));
+ connect (m_speaker, SIGNAL(textFinished(const QCString&, const uint)),
+ this, SLOT(slotTextFinished(const QCString&, const uint)));
+ connect (m_speaker, SIGNAL(textResumed(const QCString&, const uint)),
+ this, SLOT(slotTextResumed(const QCString&, const uint)));
+ connect (m_speaker, SIGNAL(sentenceStarted(QString, QString, const QCString&, const uint, const uint)),
+ this, SLOT(slotSentenceStarted(QString, QString, const QCString&, const uint, const uint)));
+ connect (m_speaker, SIGNAL(sentenceFinished(const QCString&, const uint, const uint)), this,
+ SLOT(slotSentenceFinished(const QCString&, const uint, const uint)));
+ connect (m_speaker, SIGNAL(textStopped(const QCString&, const uint)),
+ this, SLOT(slotTextStopped(const QCString&, const uint)));
+ connect (m_speaker, SIGNAL(textPaused(const QCString&, const uint)),
+ this, SLOT(slotTextPaused(const QCString&, const uint)));
+
+ return true;
+}
+
+/**
+ * Destructor
+ * Terminate speaker thread
+ */
+KTTSD::~KTTSD(){
+ kdDebug() << "KTTSD::~KTTSD:: Stopping KTTSD service" << endl;
+ if (m_speaker) m_speaker->requestExit();
+ delete m_speaker;
+ delete m_talkerMgr;
+ delete m_speechData;
+ kdDebug() << "KTTSD::~KTTSD: Emitting DCOP signal kttsdExiting()" << endl;
+ kttsdExiting();
+}
+
+/***** DCOP exported functions *****/
+
+/**
+* Determine whether the currently-configured speech plugin supports a speech markup language.
+* @param talker Code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* @param markupType The kttsd code for the desired speech markup language.
+* @return True if the plugin currently configured for the indicated
+* talker supports the indicated speech markup language.
+* @see kttsdMarkupType
+*/
+bool KTTSD::supportsMarkup(const QString& talker /*=NULL*/, const uint markupType /*=0*/) const
+{
+ if (markupType == KSpeech::mtHtml)
+ {
+ if (!m_speechData) return false;
+ return m_speechData->supportsHTML;
+ }
+ if (markupType != KSpeech::mtSsml) return false;
+ if (!m_talkerMgr) return false;
+ return m_talkerMgr->supportsMarkup(fixNullString(talker), markupType);
+}
+
+/**
+* Determine whether the currently-configured speech plugin supports markers in speech markup.
+* @param talker Code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* @return True if the plugin currently configured for the indicated
+* talker supports markers.
+* TODO: Waiting on plugin API.
+*/
+bool KTTSD::supportsMarkers(const QString& /*talker=NULL*/) const { return false; }
+
+/**
+* Say a message as soon as possible, interrupting any other speech in progress.
+* IMPORTANT: This method is reserved for use by Screen Readers and should not be used
+* by any other applications.
+* @param msg The message to be spoken.
+* @param talker Code for the to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* If no plugin has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+*
+* If an existing Screen Reader output is in progress, it is stopped and discarded and
+* replaced with this new message.
+*/
+void KTTSD::sayScreenReaderOutput(const QString &msg, const QString &talker /*=NULL*/)
+{
+ if (!m_speaker) return;
+ m_speechData->setScreenReaderOutput(msg, fixNullString(talker), getAppId());
+ m_speaker->doUtterances();
+}
+
+/**
+* Say a warning. The warning will be spoken when the current sentence
+* stops speaking and takes precedence over Messages and regular text. Warnings should only
+* be used for high-priority messages requiring immediate user attention, such as
+* "WARNING. CPU is overheating."
+* @param warning The warning to be spoken.
+* @param talker Code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* If no plugin has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+*/
+void KTTSD::sayWarning(const QString &warning, const QString &talker /*=NULL*/){
+ // kdDebug() << "KTTSD::sayWarning: Running" << endl;
+ if (!m_speaker) return;
+ kdDebug() << "KTTSD::sayWarning: Adding '" << warning << "' to warning queue." << endl;
+ m_speechData->enqueueWarning(warning, fixNullString(talker), getAppId());
+ m_speaker->doUtterances();
+}
+
+/**
+* Say a message. The message will be spoken when the current sentence stops speaking
+* but after any warnings have been spoken.
+* Messages should be used for one-shot messages that can't wait for
+* normal text messages to stop speaking, such as "You have mail.".
+* @param message The message to be spoken.
+* @param talker Code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* If no talker has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+*/
+void KTTSD::sayMessage(const QString &message, const QString &talker /*=NULL*/)
+{
+ // kdDebug() << "KTTSD::sayMessage: Running" << endl;
+ if (!m_speaker) return;
+ kdDebug() << "KTTSD::sayMessage: Adding '" << message << "' to message queue." << endl;
+ m_speechData->enqueueMessage(message, fixNullString(talker), getAppId());
+ m_speaker->doUtterances();
+}
+
+/**
+* Sets the GREP pattern that will be used as the sentence delimiter.
+* @param delimiter A valid GREP pattern.
+*
+* The default sentence delimiter is
+ @verbatim
+ ([\\.\\?\\!\\:\\;])\\s
+ @endverbatim
+*
+* Note that backward slashes must be escaped.
+*
+* Changing the sentence delimiter does not affect other applications.
+* @see sentenceparsing
+*/
+void KTTSD::setSentenceDelimiter(const QString &delimiter)
+{
+ if (!m_speaker) return;
+ m_speechData->setSentenceDelimiter(fixNullString(delimiter), getAppId());
+}
+
+/**
+* Queue a text job. Does not start speaking the text.
+* @param text The message to be spoken.
+* @param talker Code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default plugin.
+* If no plugin has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+* @return Job number.
+*
+* Plain text is parsed into individual sentences using the current sentence delimiter.
+* Call @ref setSentenceDelimiter to change the sentence delimiter prior to calling setText.
+* Call @ref getTextCount to retrieve the sentence count after calling setText.
+*
+* The text may contain speech mark language, such as Sable, JSML, or SMML,
+* provided that the speech plugin/engine support it. In this case,
+* sentence parsing follows the semantics of the markup language.
+*
+* Call @ref startText to mark the job as speakable and if the
+* job is the first speakable job in the queue, speaking will begin.
+* @see getTextCount
+* @see startText
+*/
+uint KTTSD::setText(const QString &text, const QString &talker /*=NULL*/)
+{
+ // kdDebug() << "KTTSD::setText: Running" << endl;
+ if (!m_speaker) return 0;
+ // kdDebug() << "KTTSD::setText: Setting text: '" << text << "'" << endl;
+ uint jobNum = m_speechData->setText(text, fixNullString(talker), getAppId());
+ return jobNum;
+}
+
+/**
+* Say a plain text job. This is a convenience method that
+* combines @ref setText and @ref startText into a single call.
+* @param text The message to be spoken.
+* @param talker Code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default plugin.
+* If no plugin has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+* @return Job number.
+*
+* Plain text is parsed into individual sentences using the current sentence delimiter.
+* Call @ref setSentenceDelimiter to change the sentence delimiter prior to
+* calling setText.
+* Call @ref getTextCount to retrieve the sentence count after calling setText.
+*
+* The text may contain speech mark language, such as Sable, JSML, or SSML,
+* provided that the speech plugin/engine support it. In this case,
+* sentence parsing follows the semantics of the markup language.
+*
+* The job is marked speakable.
+* If there are other speakable jobs preceeding this one in the queue,
+* those jobs continue speaking and when finished, this job will begin speaking.
+* If there are no other speakable jobs preceeding this one, it begins speaking.
+*
+* @see getTextCount
+*
+* @since KDE 3.5
+*/
+uint KTTSD::sayText(const QString &text, const QString &talker)
+{
+ uint jobNum = setText(text, talker);
+ if (jobNum) startText(jobNum);
+ return jobNum;
+}
+
+/**
+* Adds another part to a text job. Does not start speaking the text.
+* (thread safe)
+* @param text The message to be spoken.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application,
+* but if no such job, applies to the last job queued by any application.
+* @return Part number for the added part. Parts are numbered starting at 1.
+*
+* The text is parsed into individual sentences. Call getTextCount to retrieve
+* the sentence count. Call startText to mark the job as speakable and if the
+* job is the first speakable job in the queue, speaking will begin.
+* @see setText.
+* @see startText.
+*/
+int KTTSD::appendText(const QString &text, const uint jobNum /*=0*/)
+{
+ if (!m_speaker) return 0;
+ return m_speechData->appendText(text, applyDefaultJobNum(jobNum), getAppId());
+}
+
+/**
+* Queue a text job from the contents of a file. Does not start speaking the text.
+* @param filename Full path to the file to be spoken. May be a URL.
+* @param talker Code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* If no plugin has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+* @param encoding Name of the encoding to use when reading the file. If
+* NULL or Empty, uses default stream encoding.
+* @return Job number. 0 if an error occurs.
+*
+* Plain text is parsed into individual sentences using the current sentence delimiter.
+* Call @ref setSentenceDelimiter to change the sentence delimiter prior to calling setText.
+* Call @ref getTextCount to retrieve the sentence count after calling setText.
+*
+* The text may contain speech mark language, such as Sable, JSML, or SMML,
+* provided that the speech plugin/engine support it. In this case,
+* sentence parsing follows the semantics of the markup language.
+*
+* Call @ref startText to mark the job as speakable and if the
+* job is the first speakable job in the queue, speaking will begin.
+* @see getTextCount
+* @see startText
+*/
+uint KTTSD::setFile(const QString &filename, const QString &talker /*=NULL*/,
+ const QString &encoding /*=NULL*/)
+{
+ // kdDebug() << "KTTSD::setFile: Running" << endl;
+ if (!m_speaker) return 0;
+ QFile file(filename);
+ uint jobNum = 0;
+ if ( file.open(IO_ReadOnly) )
+ {
+ QTextStream stream(&file);
+ QString enc = fixNullString(encoding);
+ if (!enc.isEmpty())
+ {
+ QTextCodec* codec = QTextCodec::codecForName(enc.latin1());
+ if (codec) stream.setCodec(codec);
+ }
+ jobNum = m_speechData->setText(stream.read(), fixNullString(talker), getAppId());
+ file.close();
+ }
+ return jobNum;
+}
+
+/**
+* Get the number of sentences in a text job.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+* @return The number of sentences in the job. -1 if no such job.
+*
+* The sentences of a job are given sequence numbers from 1 to the number returned by this
+* method. The sequence numbers are emitted in the @ref sentenceStarted and
+* @ref sentenceFinished signals.
+*/
+int KTTSD::getTextCount(const uint jobNum /*=0*/)
+{
+ if (!m_speaker) return -1;
+ return m_speechData->getTextCount(applyDefaultJobNum(jobNum));
+}
+
+/**
+* Get the job number of the current text job.
+* @return Job number of the current text job. 0 if no jobs.
+*
+* Note that the current job may not be speaking. See @ref isSpeakingText.
+* @see getTextJobState.
+* @see isSpeakingText
+*/
+uint KTTSD::getCurrentTextJob()
+{
+ if (!m_speaker) return 0;
+ return m_speaker->getCurrentTextJob();
+}
+
+/**
+* Get the number of jobs in the text job queue.
+* @return Number of text jobs in the queue. 0 if none.
+*/
+uint KTTSD::getTextJobCount()
+{
+ if (!m_speaker) return 0;
+ return m_speechData->getTextJobCount();
+}
+
+/**
+* Get a comma-separated list of text job numbers in the queue.
+* @return Comma-separated list of text job numbers in the queue.
+*/
+QString KTTSD::getTextJobNumbers()
+{
+ if (!m_speaker) return QString::null;
+ return m_speechData->getTextJobNumbers();
+}
+
+/**
+* Get the state of a text job.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+* @return State of the job. -1 if invalid job number.
+*
+* @see kttsdJobState
+*/
+int KTTSD::getTextJobState(const uint jobNum /*=0*/)
+{
+ if (!m_speaker) return -1;
+ return m_speechData->getTextJobState(applyDefaultJobNum(jobNum));
+}
+
+/**
+* Get information about a text job.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+* @return A QDataStream containing information about the job.
+* Blank if no such job.
+*
+* The stream contains the following elements:
+* - int state Job state.
+* - QCString appId DCOP senderId of the application that requested the speech job.
+* - QString talker Language code in which to speak the text.
+* - int seq Current sentence being spoken. Sentences are numbered starting at 1.
+* - int sentenceCount Total number of sentences in the job.
+*
+* The following sample code will decode the stream:
+ @verbatim
+ QByteArray jobInfo = getTextJobInfo(jobNum);
+ QDataStream stream(jobInfo, IO_ReadOnly);
+ int state;
+ QCString appId;
+ QString talker;
+ int seq;
+ int sentenceCount;
+ stream >> state;
+ stream >> appId;
+ stream >> talker;
+ stream >> seq;
+ stream >> sentenceCount;
+ @endverbatim
+*/
+QByteArray KTTSD::getTextJobInfo(const uint jobNum /*=0*/)
+{
+ return m_speechData->getTextJobInfo(applyDefaultJobNum(jobNum));
+}
+
+/**
+* Given a Talker Code, returns the Talker ID of the talker that would speak
+* a text job with that Talker Code.
+* @param talkerCode Talker Code.
+* @return Talker ID of the talker that would speak the text job.
+*/
+QString KTTSD::talkerCodeToTalkerId(const QString& talkerCode)
+{
+ if (!m_talkerMgr) return QString::null;
+ return m_talkerMgr->talkerCodeToTalkerId(fixNullString(talkerCode));
+}
+
+/**
+* Return a sentence of a job.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+* @param seq Sequence number of the sentence.
+* @return The specified sentence in the specified job. If no such
+* job or sentence, returns "".
+*/
+QString KTTSD::getTextJobSentence(const uint jobNum /*=0*/, const uint seq /*=1*/)
+{
+ return m_speechData->getTextJobSentence(applyDefaultJobNum(jobNum), seq);
+}
+
+/**
+* Determine if kttsd is currently speaking any text jobs.
+* @return True if currently speaking any text jobs.
+*/
+bool KTTSD::isSpeakingText() const
+{
+ if (!m_speaker) return false;
+ return m_speaker->isSpeakingText();
+}
+
+/**
+* Remove a text job from the queue.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+*
+* The job is deleted from the queue and the @ref textRemoved signal is emitted.
+*
+* If there is another job in the text queue, and it is marked speakable,
+* that job begins speaking.
+*/
+void KTTSD::removeText(const uint jobNum /*=0*/)
+{
+ kdDebug() << "KTTSD::removeText: Running" << endl;
+ if (!m_speaker) return;
+ m_speaker->removeText(applyDefaultJobNum(jobNum));
+}
+
+/**
+* Start a text job at the beginning.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+*
+* Rewinds the job to the beginning.
+*
+* The job is marked speakable.
+* If there are other speakable jobs preceeding this one in the queue,
+* those jobs continue speaking and when finished, this job will begin speaking.
+* If there are no other speakable jobs preceeding this one, it begins speaking.
+*
+* The @ref textStarted signal is emitted when the text job begins speaking.
+* When all the sentences of the job have been spoken, the job is marked for deletion from
+* the text queue and the @ref textFinished signal is emitted.
+*/
+void KTTSD::startText(const uint jobNum /*=0*/)
+{
+ kdDebug() << "KTTSD::startText: Running" << endl;
+ if (!m_speaker) return;
+ // Determine if we are starting speech.
+ bool startingSpeech = !isSpeakingText();
+ uint jNum = applyDefaultJobNum(jobNum);
+ m_speaker->startText(jNum);
+ // If this has started speech output, determine whether to autostart KTTSMgr.
+ if (startingSpeech)
+ {
+ if (m_speechData->autoStartManager)
+ {
+ // Do not start KTTSMgr unless at least 5 sentences are queued.
+ if (getTextCount(jNum) > 4)
+ {
+ QString cmd = "kttsmgr --systray";
+ if (m_speechData->autoExitManager) cmd.append(" --autoexit");
+ // Notice this fails if KTTSMgr is already running, which is what we want.
+ KRun::runCommand(cmd);
+ }
+ }
+ }
+}
+
+/**
+* Stop a text job and rewind to the beginning.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+*
+* The job is marked not speakable and will not be speakable until @ref startText or @ref resumeText
+* is called.
+*
+* If there are speaking jobs preceeding this one in the queue, they continue speaking.
+* If the job is currently speaking, the @ref textStopped signal is emitted and the job stops speaking.
+* Depending upon the speech engine and plugin used, speeking may not stop immediately
+* (it might finish the current sentence).
+*/
+void KTTSD::stopText(const uint jobNum /*=0*/)
+{
+ kdDebug() << "KTTSD::stopText: Running" << endl;
+ if (!m_speaker) return;
+ m_speaker->stopText(applyDefaultJobNum(jobNum));
+}
+
+/**
+* Pause a text job.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+*
+* The job is marked as paused and will not be speakable until @ref resumeText or
+* @ref startText is called.
+*
+* If there are speaking jobs preceeding this one in the queue, they continue speaking.
+* If the job is currently speaking, the @ref textPaused signal is emitted and the job stops speaking.
+* Depending upon the speech engine and plugin used, speeking may not stop immediately
+* (it might finish the current sentence).
+* @see resumeText
+*/
+void KTTSD::pauseText(const uint jobNum /*=0*/)
+{
+ kdDebug() << "KTTSD::pauseText: Running" << endl;
+ if (!m_speaker) return;
+ m_speaker->pauseText(applyDefaultJobNum(jobNum));
+}
+
+/**
+* Start or resume a text job where it was paused.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+*
+* The job is marked speakable.
+*
+* If the job is currently speaking, or is waiting to be spoken (speakable
+* state), the resumeText() call is ignored.
+*
+* If the job is currently queued, or is finished, it is the same as calling
+* @ref startText .
+*
+* If there are speaking jobs preceeding this one in the queue, those jobs continue speaking and,
+* when finished this job will begin speaking where it left off.
+*
+* The @ref textResumed signal is emitted when the job resumes.
+* @see pauseText
+*/
+void KTTSD::resumeText(const uint jobNum /*=0*/)
+{
+ kdDebug() << "KTTSD::resumeText: Running" << endl;
+ if (!m_speaker) return;
+ m_speaker->resumeText(applyDefaultJobNum(jobNum));
+}
+
+/**
+* Get a list of the talkers configured in KTTS.
+* @return A QStringList of fully-specified talker codes, one
+* for each talker user has configured.
+*
+* @see talkers
+*/
+QStringList KTTSD::getTalkers()
+{
+ if (!m_talkerMgr) return QStringList();
+ return m_talkerMgr->getTalkers();
+}
+
+/**
+* Change the talker for a text job.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+* @param talker New code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* If no plugin has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+*/
+void KTTSD::changeTextTalker(const QString &talker, uint jobNum)
+{
+ m_speechData->changeTextTalker(fixNullString(talker), applyDefaultJobNum(jobNum));
+}
+
+/**
+* Get the user's default talker.
+* @return A fully-specified talker code.
+*
+* @see talkers
+* @see getTalkers
+*/
+QString KTTSD::userDefaultTalker()
+{
+ if (!m_talkerMgr) return QString::null;
+ return m_talkerMgr->userDefaultTalker();
+}
+
+/**
+* Move a text job down in the queue so that it is spoken later.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application.
+*
+* If the job is currently speaking, it is paused.
+* If the next job in the queue is speakable, it begins speaking.
+*/
+void KTTSD::moveTextLater(const uint jobNum /*=0*/)
+{
+ if (!m_speaker) return;
+ m_speaker->moveTextLater(applyDefaultJobNum(jobNum));
+}
+
+/**
+* Jump to the first sentence of a specified part of a text job.
+* @param partNum Part number of the part to jump to. Parts are numbered starting at 1.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application,
+* but if no such job, applies to the last job queued by any application.
+* @return Part number of the part actually jumped to.
+*
+* If partNum is greater than the number of parts in the job, jumps to last part.
+* If partNum is 0, does nothing and returns the current part number.
+* If no such job, does nothing and returns 0.
+* Does not affect the current speaking/not-speaking state of the job.
+*/
+int KTTSD::jumpToTextPart(const int partNum, const uint jobNum /*=0*/)
+{
+ if (!m_speaker) return 0;
+ return m_speaker->jumpToTextPart(partNum, applyDefaultJobNum(jobNum));
+}
+
+/**
+* Advance or rewind N sentences in a text job.
+* @param n Number of sentences to advance (positive) or rewind (negative) in the job.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application,
+* but if no such job, applies to the last job queued by any application.
+* @return Sequence number of the sentence actually moved to. Sequence numbers
+* are numbered starting at 1.
+*
+* If no such job, does nothing and returns 0.
+* If n is zero, returns the current sequence number of the job.
+* Does not affect the current speaking/not-speaking state of the job.
+*/
+uint KTTSD::moveRelTextSentence(const int n, const uint jobNum /*=0*/)
+{
+ if (!m_speaker) return 0;
+ return m_speaker->moveRelTextSentence(n, applyDefaultJobNum(jobNum));
+}
+
+/**
+* Add the clipboard contents to the text queue and begin speaking it.
+*/
+void KTTSD::speakClipboard()
+{
+ // Get the clipboard object.
+ QClipboard *cb = kapp->clipboard();
+
+ // Copy text from the clipboard.
+ QString text = cb->text();
+
+ // Speak it.
+ if ( !text.isNull() )
+ {
+ setText(text);
+ startText();
+ }
+}
+
+/**
+* Displays the %KTTS Manager dialog. In this dialog, the user may backup or skip forward in
+* any text job by sentence or paragraph, rewind jobs, pause or resume jobs, or
+* delete jobs.
+*/
+void KTTSD::showDialog()
+{
+ KRun::runCommand("kttsmgr");
+}
+
+/**
+* Stop the service.
+*/
+void KTTSD::kttsdExit()
+{
+ stopText();
+ kdDebug() << "KTTSD::kttsdExit: Emitting DCOP signal kttsdExiting()" << endl;
+ kttsdExiting();
+ kapp->quit();
+}
+
+/**
+* Re-start %KTTSD.
+*/
+void KTTSD::reinit()
+{
+ // Restart ourself.
+ kdDebug() << "KTTSD::reinit: Running" << endl;
+ if (m_speaker)
+ {
+ kdDebug() << "KTTSD::reinit: Stopping KTTSD service" << endl;
+ if (m_speaker->isSpeakingText()) pauseText();
+ m_speaker->requestExit();
+ }
+ delete m_speaker;
+ m_speaker = 0;
+ delete m_talkerMgr;
+ m_talkerMgr = 0;
+ ready();
+}
+
+/**
+* Return KTTSD daemon version number.
+*/
+QString KTTSD::version() { return kapp->aboutData()->version(); }
+
+/*
+* Checks if KTTSD is ready to speak and at least one talker is configured.
+* If not, user is prompted to display the configuration dialog.
+*/
+bool KTTSD::ready()
+{
+ if (m_speaker) return true;
+ kdDebug() << "KTTSD::ready: Starting KTTSD service" << endl;
+ if (!initializeSpeechData()) return false;
+ if (!initializeTalkerMgr()) return false;
+ if (!initializeSpeaker()) return false;
+ m_speaker->doUtterances();
+ kdDebug() << "KTTSD::ready: Emitting DCOP signal kttsdStarted()" << endl;
+ kttsdStarted();
+ return true;
+}
+
+void KTTSD::configCommitted() {
+ if (m_speaker) reinit();
+}
+
+/**
+* This signal is emitted by KNotify when a notification event occurs.
+* ds << event << fromApp << text << sound << file << present << level
+* << winId << eventId;
+* default_presentation contains these ORed events: None=0, Sound=1, Messagebox=2, Logfile=4, Stderr=8,
+* PassivePopup=16, Execute=32, Taskbar=64
+*/
+void KTTSD::notificationSignal( const QString& event, const QString& fromApp,
+ const QString &text, const QString& sound, const QString& /*file*/,
+ const int present, const int /*level*/, const int /*windId*/, const int /*eventId*/)
+{
+ if (!m_speaker) return;
+ // kdDebug() << "KTTSD:notificationSignal: event: " << event << " fromApp: " << fromApp <<
+ // " text: " << text << " sound: " << sound << " file: " << file << " present: " << present <<
+ // " level: " << level << " windId: " << windId << " eventId: " << eventId << endl;
+ if ( m_speechData->notify )
+ if ( !m_speechData->notifyExcludeEventsWithSound || sound.isEmpty() )
+ {
+ bool found = false;
+ NotifyOptions notifyOptions;
+ QString msg;
+ QString talker;
+ // Check for app-specific action.
+ if ( m_speechData->notifyAppMap.contains( fromApp ) )
+ {
+ NotifyEventMap notifyEventMap = m_speechData->notifyAppMap[ fromApp ];
+ if ( notifyEventMap.contains( event ) )
+ {
+ found = true;
+ notifyOptions = notifyEventMap[ event ];
+ } else {
+ // Check for app-specific default.
+ if ( notifyEventMap.contains( "default" ) )
+ {
+ found = true;
+ notifyOptions = notifyEventMap[ "default" ];
+ notifyOptions.eventName = QString::null;
+ }
+ }
+ }
+ // If no app-specific action, try default.
+ if ( !found )
+ {
+ switch ( m_speechData->notifyDefaultPresent )
+ {
+ case NotifyPresent::None:
+ found = false;
+ break;
+ case NotifyPresent::Dialog:
+ found = (
+ (present & KNotifyClient::Messagebox)
+ &&
+ !(present & KNotifyClient::PassivePopup)
+ );
+ break;
+ case NotifyPresent::Passive:
+ found = (
+ !(present & KNotifyClient::Messagebox)
+ &&
+ (present & KNotifyClient::PassivePopup)
+ );
+ break;
+ case NotifyPresent::DialogAndPassive:
+ found = (
+ (present & KNotifyClient::Messagebox)
+ &&
+ (present & KNotifyClient::PassivePopup)
+ );
+ break;
+ case NotifyPresent::All:
+ found = true;
+ break;
+ }
+ if ( found )
+ notifyOptions = m_speechData->notifyDefaultOptions;
+ }
+ if ( found )
+ {
+ int action = notifyOptions.action;
+ talker = notifyOptions.talker;
+ switch ( action )
+ {
+ case NotifyAction::DoNotSpeak:
+ break;
+ case NotifyAction::SpeakEventName:
+ if (notifyOptions.eventName.isEmpty())
+ msg = NotifyEvent::getEventName( fromApp, event );
+ else
+ msg = notifyOptions.eventName;
+ break;
+ case NotifyAction::SpeakMsg:
+ msg = text;
+ break;
+ case NotifyAction::SpeakCustom:
+ msg = notifyOptions.customMsg;
+ msg.replace( "%a", fromApp );
+ msg.replace( "%m", text );
+ if ( msg.contains( "%e" ) )
+ {
+ if ( notifyOptions.eventName.isEmpty() )
+ msg.replace( "%e", NotifyEvent::getEventName( fromApp, event ) );
+ else
+ msg.replace( "%e", notifyOptions.eventName );
+ }
+ break;
+ }
+ }
+ // Queue msg if we should speak something.
+ if ( !msg.isEmpty() )
+ {
+ QString fromApps = fromApp + ",knotify";
+ m_speechData->enqueueMessage( msg, talker, fromApps.utf8() );
+ m_speaker->doUtterances();
+ }
+ }
+}
+
+// Slots for the speaker object
+void KTTSD::slotSentenceStarted(QString, QString, const QCString& appId,
+ const uint jobNum, const uint seq) {
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotSentenceStarted: Emitting DCOP signal sentenceStarted with appId " << appId << " job number " << jobNum << " seq number " << seq << endl;
+ sentenceStarted(appId, jobNum, seq);
+}
+
+void KTTSD::slotSentenceFinished(const QCString& appId, const uint jobNum, const uint seq){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotSentenceFinished: Emitting DCOP signal sentenceFinished with appId " << appId << " job number " << jobNum << " seq number " << seq << endl;
+ sentenceFinished(appId, jobNum, seq);
+}
+
+// Slots for the speechData and speaker objects.
+void KTTSD::slotTextStarted(const QCString& appId, const uint jobNum){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotTextStarted: Emitting DCOP signal textStarted with appId " << appId << " job number " << jobNum << endl;
+ textStarted(appId, jobNum);
+}
+
+void KTTSD::slotTextFinished(const QCString& appId, const uint jobNum){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotTextFinished: Emitting DCOP signal textFinished with appId " << appId << " job number " << jobNum << endl;
+ textFinished(appId, jobNum);
+}
+
+void KTTSD::slotTextStopped(const QCString& appId, const uint jobNum){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotTextStopped: Emitting DCOP signal textStopped with appId " << appId << " job number " << jobNum << endl;
+ textStopped(appId, jobNum);
+}
+
+void KTTSD::slotTextPaused(const QCString& appId, const uint jobNum){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotTextPaused: Emitting DCOP signal textPaused with appId " << appId << " job number " << jobNum << endl;
+ textPaused(appId, jobNum);
+}
+
+void KTTSD::slotTextResumed(const QCString& appId, const uint jobNum){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotTextResumed: Emitting DCOP signal textResumed with appId " << appId << " job number " << jobNum << endl;
+ textResumed(appId, jobNum);
+}
+
+//void KTTSD::slotTextSet(const QCString& appId, const uint jobNum){
+void KTTSD::slotTextSet(const QCString& appId, const uint jobNum){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotTextSet: Emitting DCOP signal textSet with appId " << appId << " job number " << jobNum << endl;
+ textSet(appId, jobNum);
+}
+
+void KTTSD::slotTextAppended(const QCString& appId, const uint jobNum, const int partNum){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotTextAppended: Emitting DCOP signal textAppended with appId " <<
+ appId << " job number " << jobNum << " part number " << partNum << endl;
+ textAppended(appId, jobNum, partNum);
+}
+
+void KTTSD::slotTextRemoved(const QCString& appId, const uint jobNum){
+ // Emit DCOP signal.
+ kdDebug() << "KTTSD::slotTextRemoved: Emitting DCOP signal textRemoved with appId " << appId << " job number " << jobNum << endl;
+ textRemoved(appId, jobNum);
+}
+
+/**
+ * Returns the senderId (appId) of the DCOP application that called us.
+ * @return The DCOP sendId of calling application.
+ */
+const QCString KTTSD::getAppId()
+{
+ DCOPClient* client = callingDcopClient();
+ QCString appId;
+ if (client) appId = client->senderId();
+ return appId;
+}
+
+/**
+* If a job number is 0, returns the default job number for a command.
+* Returns the job number of the last job queued by the application, or if
+* no such job, the current job number.
+* @return Default job number. 0 if no such job.
+*/
+uint KTTSD::applyDefaultJobNum(const uint jobNum)
+{
+ uint jNum = jobNum;
+ if (!jNum)
+ {
+ jNum = m_speechData->findAJobNumByAppId(getAppId());
+ if (!jNum) jNum = getCurrentTextJob();
+ if (!jNum) jNum = m_speechData->findAJobNumByAppId(0);
+ }
+ return jNum;
+}
+
+/*
+* Fixes a string argument passed in via dcop.
+* If NULL or "0" return QString::null.
+*/
+QString KTTSD::fixNullString(const QString &talker) const
+{
+ if (!talker) return QString::null;
+ if (talker == "0") return QString::null;
+ return talker;
+}
+
+// kspeech is obsolete. Applications should use KSpeech instead.
+
+// Constructor.
+kspeech::kspeech(const QCString& objId, QObject *parent, const char *name) :
+ DCOPObject(objId),
+ QObject(parent, name),
+ m_kttsd("KSpeech")
+{
+}
+
+// Destructor.
+kspeech::~kspeech() { }
+
+// Delegate all DCOP methods to KTTSD object.
+/*virtual*/ bool kspeech::supportsMarkup(const QString &talker, uint markupType) const
+ { return m_kttsd.supportsMarkup(talker, markupType); }
+/*virtual*/ bool kspeech::supportsMarkers(const QString &talker) const
+ { return m_kttsd.supportsMarkers(talker); }
+/*virtual*/ ASYNC kspeech::sayScreenReaderOutput(const QString &msg, const QString &talker)
+ { m_kttsd.sayScreenReaderOutput(msg, talker); }
+/*virtual*/ ASYNC kspeech::sayWarning(const QString &warning, const QString &talker)
+ { m_kttsd.sayWarning(warning, talker); }
+/*virtual*/ ASYNC kspeech::sayMessage(const QString &message, const QString &talker)
+ { m_kttsd.sayMessage(message, talker); }
+/*virtual*/ ASYNC kspeech::setSentenceDelimiter(const QString &delimiter)
+ { m_kttsd.setSentenceDelimiter(delimiter); }
+/*virtual*/ uint kspeech::setText(const QString &text, const QString &talker)
+ { return m_kttsd.setText(text, talker); }
+/*virtual*/ uint kspeech::sayText(const QString &text, const QString &talker)
+ { return m_kttsd.sayText(text, talker); }
+/*virtual*/ int kspeech::appendText(const QString &text, uint jobNum)
+ { return m_kttsd.appendText(text, jobNum); }
+/*virtual*/ uint kspeech::setFile(const QString &filename, const QString &talker,
+ const QString& encoding)
+ { return m_kttsd.setFile(filename, talker, encoding); }
+/*virtual*/ int kspeech::getTextCount(uint jobNum)
+ { return m_kttsd.getTextCount(jobNum); }
+/*virtual*/ uint kspeech::getCurrentTextJob()
+ { return m_kttsd.getCurrentTextJob(); }
+/*virtual*/ uint kspeech::getTextJobCount()
+ { return m_kttsd.getTextJobCount(); }
+/*virtual*/ QString kspeech::getTextJobNumbers()
+ { return m_kttsd.getTextJobNumbers(); }
+/*virtual*/ int kspeech::getTextJobState(uint jobNum)
+ { return m_kttsd.getTextJobState(jobNum); }
+/*virtual*/ QByteArray kspeech::getTextJobInfo(uint jobNum)
+ { return m_kttsd.getTextJobInfo(jobNum); }
+/*virtual*/ QString kspeech::talkerCodeToTalkerId(const QString& talkerCode)
+ { return m_kttsd.talkerCodeToTalkerId(talkerCode); }
+/*virtual*/ QString kspeech::getTextJobSentence(uint jobNum, uint seq)
+ { return m_kttsd.getTextJobSentence(jobNum, seq); }
+/*virtual*/ bool kspeech::isSpeakingText() const
+ { return m_kttsd.isSpeakingText(); }
+/*virtual*/ ASYNC kspeech::removeText(uint jobNum)
+ { m_kttsd.removeText(jobNum); }
+/*virtual*/ ASYNC kspeech::startText(uint jobNum)
+ { m_kttsd.startText(jobNum); }
+/*virtual*/ ASYNC kspeech::stopText(uint jobNum)
+ { m_kttsd.stopText(jobNum); }
+/*virtual*/ ASYNC kspeech::pauseText(uint jobNum)
+ { m_kttsd.pauseText(jobNum); }
+/*virtual*/ ASYNC kspeech::resumeText(uint jobNum)
+ { m_kttsd.resumeText(jobNum); }
+/*virtual*/ QStringList kspeech::getTalkers()
+ { return m_kttsd.getTalkers(); }
+/*virtual*/ ASYNC kspeech::changeTextTalker(const QString &talker, uint jobNum )
+ { m_kttsd.changeTextTalker(talker, jobNum); }
+/*virtual*/ QString kspeech::userDefaultTalker()
+ { return m_kttsd.userDefaultTalker(); }
+/*virtual*/ ASYNC kspeech::moveTextLater(uint jobNum)
+ { m_kttsd.moveTextLater(jobNum); }
+/*virtual*/ int kspeech::jumpToTextPart(int partNum, uint jobNum)
+ { return m_kttsd.jumpToTextPart(partNum, jobNum); }
+/*virtual*/ uint kspeech::moveRelTextSentence(int n, uint jobNum)
+ { return m_kttsd.moveRelTextSentence(n, jobNum); }
+/*virtual*/ ASYNC kspeech::speakClipboard()
+ { m_kttsd.speakClipboard(); }
+/*virtual*/ void kspeech::showDialog()
+ { m_kttsd.showDialog(); }
+/*virtual*/ void kspeech::kttsdExit()
+ { m_kttsd.kttsdExit(); }
+/*virtual*/ void kspeech::reinit()
+ { m_kttsd.reinit(); }
+/*virtual*/ QString kspeech::version()
+ { return m_kttsd.version(); }
+
+#include "kttsd.moc"
+
diff --git a/kttsd/kttsd/kttsd.desktop b/kttsd/kttsd/kttsd.desktop
new file mode 100644
index 0000000..27c216e
--- /dev/null
+++ b/kttsd/kttsd/kttsd.desktop
@@ -0,0 +1,56 @@
+[Desktop Entry]
+Type=Service
+Exec=kttsd
+Icon=kttsd
+ServiceTypes=DCOP/Text-to-Speech
+X-DCOP-ServiceType=Unique
+X-DCOP-ServiceName=kttsd
+X-KDE-StartupNotify=false
+Name=KTTSD
+Name[zh_TW]=KTTSd
+Comment=KDE Text To Speech Daemon
+Comment[bg]=Демон за управление на модула за синтез на глас
+Comment[bs]=KDE Demon za izgovaranje teksta
+Comment[ca]=Dimoni de text a veu de KDE
+Comment[cs]=Démon hlasové syntézy KDE
+Comment[da]=KDE's Tekst til tale-dæmon
+Comment[de]=KDE Sprachausgabedienst
+Comment[el]=KDE δαίμονας κειμένου-σε-ομιλία
+Comment[es]=Demonio de KDE para la sí­ntesis de texto a voz
+Comment[et]=KDE teksti kõneks muutmise deemon
+Comment[eu]=KDE-ren testutik hizketarako deabrua
+Comment[fa]=شبح متن به گفتار KDE
+Comment[fi]=KDE Teksti puheeksi -palvelinohjelma
+Comment[fr]=Démon de synthèse vocale pour KDE
+Comment[ga]=Deamhan Téacs-Go-Caint KDE
+Comment[gl]=Servizo Texto-para-Fala de KDE
+Comment[he]=שירות הטקסט לדיבור של KDE
+Comment[hu]=KDE szövegfelolvasó szolgáltatás
+Comment[is]=KDE texti-í-tal púki
+Comment[it]=Demone di pronuncia di KDE
+Comment[ja]=KDE テキスト読み上げデーモン
+Comment[ka]=KDE ტექსტის გახმოვანების დემონი
+Comment[km]=ដេមិន​អត្ថបទ​ដែល​ត្រូវ​និយាយ​របស់ KDE
+Comment[mk]=Даемон на KDE за текст-во-говор
+Comment[ms]=Daemon Teks Ke Tutur KDE
+Comment[nb]=KDE tekst-til-tale-nisse
+Comment[nds]=Vörlees-Dämoon vun KDE
+Comment[ne]=केडीई पाठ वाचक डेइमन
+Comment[nl]=KDE Tekst-tot-spraak-daemon
+Comment[pa]=KDE ਪਾਠ ਤੋਂ ਬੋਲੀ ਡਾਈਮੋਨ
+Comment[pl]=Usługa odczytywania tekstu dla KDE
+Comment[pt]=Servidor do Texto para Fala do KDE
+Comment[pt_BR]=Serviço de Conversão de Texto para Fala do KDE
+Comment[ru]=Служба синтеза речи
+Comment[sk]=Démon KDE text-na-reč
+Comment[sl]=Demon KDE za besedilo v govor
+Comment[sr]=KDE-ов демон за текст-у-говор
+Comment[sr@Latn]=KDE-ov demon za tekst-u-govor
+Comment[sv]=KDE:s text-till-tal demon
+Comment[ta]=கேடியி உரையில் இருந்து பேச்சு டெமான்
+Comment[tg]=Демон таҳлили овоз
+Comment[tr]=KDE Metinden Konuşmaya Artalan Süreci
+Comment[uk]=Демон KDE синтезу мовлення з тексту
+Comment[vi]=Trình nền Văn bản sang Tiếng nói KDE
+Comment[zh_TW]=KDE 文字轉語音的常駐精靈
+
diff --git a/kttsd/kttsd/kttsd.h b/kttsd/kttsd/kttsd.h
new file mode 100644
index 0000000..bdbd756
--- /dev/null
+++ b/kttsd/kttsd/kttsd.h
@@ -0,0 +1,686 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KTTSD main class
+ -------------------
+ Copyright:
+ (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _KTTSD_H_
+#define _KTTSD_H_
+
+#include "speechdata.h"
+#include "talkermgr.h"
+#include "speaker.h"
+#include "kspeech.h"
+
+/**
+* KTTSD - the KDE Text-to-speech Deamon.
+*
+* Provides the capability for applications to speak text.
+* Applications may speak text by sending DCOP messages to application "kttsd" object "KSpeech".
+*
+* @author José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+* @author Olaf Schmidt <ojschmidt@kde.org>
+* @author Gary Cramblitt <garycramblitt@comcast.net>
+*/
+
+class KTTSD : public QObject, virtual public KSpeech
+{
+ Q_OBJECT
+ K_DCOP
+
+ public:
+ /**
+ * Constructor.
+ *
+ * Create objects, speechData and speaker.
+ * Start thread
+ */
+ KTTSD(const QCString& objId, QObject *parent=0, const char *name=0);
+
+ /**
+ * Destructor.
+ *
+ * Terminate speaker thread.
+ */
+ ~KTTSD();
+
+ /** DCOP exported functions for kspeech interface **/
+
+ /**
+ * Determine whether the currently-configured speech plugin supports a speech markup language.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * @param markupType The kttsd code for the desired speech markup language.
+ * @return True if the plugin currently configured for the indicated
+ * talker supports the indicated speech markup language.
+ * @see kttsdMarkupType
+ */
+ virtual bool supportsMarkup(const QString &talker=NULL, const uint markupType = 0) const;
+
+ /**
+ * Determine whether the currently-configured speech plugin supports markers in speech markup.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * @return True if the plugin currently configured for the indicated
+ * talker supports markers.
+ */
+ virtual bool supportsMarkers(const QString &talker=NULL) const;
+
+ /**
+ * Say a message as soon as possible, interrupting any other speech in progress.
+ * IMPORTANT: This method is reserved for use by Screen Readers and should not be used
+ * by any other applications.
+ * @param msg The message to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ *
+ * If an existing Screen Reader output is in progress, it is stopped and discarded and
+ * replaced with this new message.
+ */
+ virtual ASYNC sayScreenReaderOutput(const QString &msg, const QString &talker=NULL);
+
+ /**
+ * Say a warning. The warning will be spoken when the current sentence
+ * stops speaking and takes precedence over Messages and regular text. Warnings should only
+ * be used for high-priority messages requiring immediate user attention, such as
+ * "WARNING. CPU is overheating."
+ * @param warning The warning to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ */
+ virtual ASYNC sayWarning(const QString &warning, const QString &talker=NULL);
+
+ /**
+ * Say a message. The message will be spoken when the current sentence stops speaking
+ * but after any warnings have been spoken.
+ * Messages should be used for one-shot messages that can't wait for
+ * normal text messages to stop speaking, such as "You have mail.".
+ * @param message The message to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no talker has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ */
+ virtual ASYNC sayMessage(const QString &message, const QString &talker=NULL);
+
+ /**
+ * Sets the GREP pattern that will be used as the sentence delimiter.
+ * @param delimiter A valid GREP pattern.
+ *
+ * The default sentence delimiter is
+ @verbatim
+ ([\\.\\?\\!\\:\\;])\\s
+ @endverbatim
+ *
+ * Note that backward slashes must be escaped.
+ *
+ * Changing the sentence delimiter does not affect other applications.
+ * @see sentenceparsing
+ */
+ virtual ASYNC setSentenceDelimiter(const QString &delimiter);
+
+ /**
+ * Queue a text job. Does not start speaking the text.
+ * @param text The message to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default plugin.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ * @return Job number.
+ *
+ * Plain text is parsed into individual sentences using the current sentence delimiter.
+ * Call @ref setSentenceDelimiter to change the sentence delimiter prior to calling setText.
+ * Call @ref getTextCount to retrieve the sentence count after calling setText.
+ *
+ * The text may contain speech mark language, such as Sable, JSML, or SMML,
+ * provided that the speech plugin/engine support it. In this case,
+ * sentence parsing follows the semantics of the markup language.
+ *
+ * Call @ref startText to mark the job as speakable and if the
+ * job is the first speakable job in the queue, speaking will begin.
+ * @see getTextCount
+ * @see startText
+ */
+ virtual uint setText(const QString &text, const QString &talker=NULL);
+
+ /**
+ * Say a plain text job. This is a convenience method that
+ * combines @ref setText and @ref startText into a single call.
+ * @param text The message to be spoken.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default plugin.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ * @return Job number.
+ *
+ * Plain text is parsed into individual sentences using the current sentence delimiter.
+ * Call @ref setSentenceDelimiter to change the sentence delimiter prior to
+ * calling setText.
+ * Call @ref getTextCount to retrieve the sentence count after calling setText.
+ *
+ * The text may contain speech mark language, such as Sable, JSML, or SSML,
+ * provided that the speech plugin/engine support it. In this case,
+ * sentence parsing follows the semantics of the markup language.
+ *
+ * The job is marked speakable.
+ * If there are other speakable jobs preceeding this one in the queue,
+ * those jobs continue speaking and when finished, this job will begin speaking.
+ * If there are no other speakable jobs preceeding this one, it begins speaking.
+ *
+ * @see getTextCount
+ *
+ * @since KDE 3.5
+ */
+ virtual uint sayText(const QString &text, const QString &talker);
+
+ /**
+ * Adds another part to a text job. Does not start speaking the text.
+ * (thread safe)
+ * @param text The message to be spoken.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return Part number for the added part. Parts are numbered starting at 1.
+ *
+ * The text is parsed into individual sentences. Call getTextCount to retrieve
+ * the sentence count. Call startText to mark the job as speakable and if the
+ * job is the first speakable job in the queue, speaking will begin.
+ * @see setText.
+ * @see startText.
+ */
+ int appendText(const QString &text, const uint jobNum=0);
+
+ /**
+ * Queue a text job from the contents of a file. Does not start speaking the text.
+ * @param filename Full path to the file to be spoken. May be a URL.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ * @param encoding Name of the encoding to use when reading the file. If
+ * NULL or Empty, uses default stream encoding.
+ * @return Job number. 0 if an error occurs.
+ *
+ * Plain text is parsed into individual sentences using the current sentence delimiter.
+ * Call @ref setSentenceDelimiter to change the sentence delimiter prior to calling setText.
+ * Call @ref getTextCount to retrieve the sentence count after calling setText.
+ *
+ * The text may contain speech mark language, such as Sable, JSML, or SMML,
+ * provided that the speech plugin/engine support it. In this case,
+ * sentence parsing follows the semantics of the markup language.
+ *
+ * Call @ref startText to mark the job as speakable and if the
+ * job is the first speakable job in the queue, speaking will begin.
+ * @see getTextCount
+ * @see startText
+ */
+ virtual uint setFile(const QString &filename, const QString &talker=NULL,
+ const QString& encoding=NULL);
+
+ /**
+ * Get the number of sentences in a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return The number of sentences in the job. -1 if no such job.
+ *
+ * The sentences of a job are given sequence numbers from 1 to the number returned by this
+ * method. The sequence numbers are emitted in the @ref sentenceStarted and
+ * @ref sentenceFinished signals.
+ */
+ virtual int getTextCount(const uint jobNum=0);
+
+ /**
+ * Get the job number of the current text job.
+ * @return Job number of the current text job. 0 if no jobs.
+ *
+ * Note that the current job may not be speaking. See @ref isSpeakingText.
+ * @see getTextJobState.
+ * @see isSpeakingText
+ */
+ virtual uint getCurrentTextJob();
+
+ /**
+ * Get the number of jobs in the text job queue.
+ * @return Number of text jobs in the queue. 0 if none.
+ */
+ virtual uint getTextJobCount();
+
+ /**
+ * Get a comma-separated list of text job numbers in the queue.
+ * @return Comma-separated list of text job numbers in the queue.
+ */
+ virtual QString getTextJobNumbers();
+
+ /**
+ * Get the state of a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return State of the job. -1 if invalid job number.
+ *
+ * @see kttsdJobState
+ */
+ virtual int getTextJobState(const uint jobNum=0);
+
+ /**
+ * Get information about a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return A QDataStream containing information about the job.
+ * Blank if no such job.
+ *
+ * The stream contains the following elements:
+ * - int state Job state.
+ * - QCString appId DCOP senderId of the application that requested the speech job.
+ * - QString talker Language code in which to speak the text.
+ * - int seq Current sentence being spoken. Sentences are numbered starting at 1.
+ * - int sentenceCount Total number of sentences in the job.
+ * - int partNum Current part of the job begin spoken. Parts are numbered starting at 1.
+ * - int partCount Total number of parts in the job.
+ *
+ * Note that sequence numbers apply to the entire job. They do not start from 1 at the beginning of
+ * each part.
+ *
+ * The following sample code will decode the stream:
+ @verbatim
+ QByteArray jobInfo = getTextJobInfo(jobNum);
+ QDataStream stream(jobInfo, IO_ReadOnly);
+ int state;
+ QCString appId;
+ QString talker;
+ int seq;
+ int sentenceCount;
+ int partNum;
+ int partCount;
+ stream >> state;
+ stream >> appId;
+ stream >> talker;
+ stream >> seq;
+ stream >> sentenceCount;
+ stream >> partNum;
+ stream >> partCount;
+ @endverbatim
+ */
+ virtual QByteArray getTextJobInfo(const uint jobNum=0);
+
+ /**
+ * Given a Talker Code, returns the Talker ID of the talker that would speak
+ * a text job with that Talker Code.
+ * @param talkerCode Talker Code.
+ * @return Talker ID of the talker that would speak the text job.
+ */
+ virtual QString talkerCodeToTalkerId(const QString& talkerCode);
+
+ /**
+ * Return a sentence of a job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @param seq Sequence number of the sentence.
+ * @return The specified sentence in the specified job. If not such
+ * job or sentence, returns "".
+ */
+ virtual QString getTextJobSentence(const uint jobNum=0, const uint seq=1);
+
+ /**
+ * Determine if kttsd is currently speaking any text jobs.
+ * @return True if currently speaking any text jobs.
+ */
+ virtual bool isSpeakingText() const;
+
+ /**
+ * Remove a text job from the queue.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * The job is deleted from the queue and the @ref textRemoved signal is emitted.
+ *
+ * If there is another job in the text queue, and it is marked speakable,
+ * that job begins speaking.
+ */
+ virtual ASYNC removeText(const uint jobNum=0);
+
+ /**
+ * Start a text job at the beginning.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * Rewinds the job to the beginning.
+ *
+ * The job is marked speakable.
+ * If there are other speakable jobs preceeding this one in the queue,
+ * those jobs continue speaking and when finished, this job will begin speaking.
+ * If there are no other speakable jobs preceeding this one, it begins speaking.
+ *
+ * The @ref textStarted signal is emitted when the text job begins speaking.
+ * When all the sentences of the job have been spoken, the job is marked for deletion from
+ * the text queue and the @ref textFinished signal is emitted.
+ */
+ virtual ASYNC startText(const uint jobNum=0);
+
+ /**
+ * Stop a text job and rewind to the beginning.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * The job is marked not speakable and will not be speakable until @ref startText or @ref resumeText
+ * is called.
+ *
+ * If there are speaking jobs preceeding this one in the queue, they continue speaking.
+ * If the job is currently speaking, the @ref textStopped signal is emitted and the job stops speaking.
+ * Depending upon the speech engine and plugin used, speeking may not stop immediately
+ * (it might finish the current sentence).
+ */
+ virtual ASYNC stopText(const uint jobNum=0);
+
+ /**
+ * Pause a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * The job is marked as paused and will not be speakable until @ref resumeText or
+ * @ref startText is called.
+ *
+ * If there are speaking jobs preceeding this one in the queue, they continue speaking.
+ * If the job is currently speaking, the @ref textPaused signal is emitted and the job stops speaking.
+ * Depending upon the speech engine and plugin used, speeking may not stop immediately
+ * (it might finish the current sentence).
+ * @see resumeText
+ */
+ virtual ASYNC pauseText(const uint jobNum=0);
+
+ /**
+ * Start or resume a text job where it was paused.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * The job is marked speakable.
+ *
+ * If the job is currently speaking, or is waiting to be spoken (speakable
+ * state), the resumeText() call is ignored.
+ *
+ * If the job is currently queued, or is finished, it is the same as calling
+ * @ref startText .
+ *
+ * If there are speaking jobs preceeding this one in the queue, those jobs continue speaking and,
+ * when finished this job will begin speaking where it left off.
+ *
+ * The @ref textResumed signal is emitted when the job resumes.
+ * @see pauseText
+ */
+ virtual ASYNC resumeText(const uint jobNum=0);
+
+ /**
+ * Get a list of the talkers configured in KTTS.
+ * @return A QStringList of fully-specified talker codes, one
+ * for each talker user has configured.
+ *
+ * @see talkers
+ */
+ virtual QStringList getTalkers();
+
+ /**
+ * Change the talker for a text job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @param talker New code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ */
+ virtual ASYNC changeTextTalker(const QString &talker, uint jobNum=0);
+
+ /**
+ * Get the user's default talker.
+ * @return A fully-specified talker code.
+ *
+ * @see talkers
+ * @see getTalkers
+ */
+ virtual QString userDefaultTalker();
+
+ /**
+ * Move a text job down in the queue so that it is spoken later.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ *
+ * If the job is currently speaking, it is paused.
+ * If the next job in the queue is speakable, it begins speaking.
+ */
+ virtual ASYNC moveTextLater(const uint jobNum=0);
+
+ /**
+ * Jump to the first sentence of a specified part of a text job.
+ * @param partNum Part number of the part to jump to. Parts are numbered starting at 1.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return Part number of the part actually jumped to.
+ *
+ * If partNum is greater than the number of parts in the job, jumps to last part.
+ * If partNum is 0, does nothing and returns the current part number.
+ * If no such job, does nothing and returns 0.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+ int jumpToTextPart(const int partNum, const uint jobNum=0);
+
+ /**
+ * Advance or rewind N sentences in a text job.
+ * @param n Number of sentences to advance (positive) or rewind (negative) in the job.
+ * @param jobNum Job number of the text job.
+ * If zero, applies to the last job queued by the application,
+ * but if no such job, applies to the current job (if any).
+ * @return Sequence number of the sentence actually moved to. Sequence numbers
+ * are numbered starting at 1.
+ *
+ * If no such job, does nothing and returns 0.
+ * If n is zero, returns the current sequence number of the job.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+ uint moveRelTextSentence(const int n, const uint jobNum=0);
+
+ /**
+ * Add the clipboard contents to the text queue and begin speaking it.
+ */
+ virtual ASYNC speakClipboard();
+
+ /**
+ * Displays the %KTTS Manager dialog. In this dialog, the user may backup or skip forward in
+ * any text job by sentence or paragraph, rewind jobs, pause or resume jobs, or
+ * delete jobs.
+ */
+ virtual void showDialog();
+
+ /**
+ * Stop the service.
+ */
+ virtual void kttsdExit();
+
+ /**
+ * Re-start %KTTSD.
+ */
+ virtual void reinit();
+
+ /**
+ * Return the KTTSD deamon version number.
+ * @since KDE 3.5
+ */
+ virtual QString version();
+
+ protected:
+
+ k_dcop:
+ /**
+ * This signal is emitted by KNotify when a notification event occurs.
+ */
+ void notificationSignal(const QString &event, const QString &fromApp,
+ const QString &text, const QString &sound, const QString &file,
+ const int present, const int level, const int winId, const int eventId );
+
+ private slots:
+ /*
+ * These functions are called whenever
+ * the status of the speaker object has changed
+ */
+ void slotSentenceStarted(QString text, QString language,
+ const QCString& appId, const uint jobNum, const uint seq);
+ void slotSentenceFinished(const QCString& appId, const uint jobNum, const uint seq);
+
+ /*
+ * These functions are called whenever
+ * the status of the speechData object has changed
+ */
+ void slotTextSet(const QCString& appId, const uint jobNum);
+ void slotTextAppended(const QCString& appId, const uint jobNum, const int partNum);
+ void slotTextStarted(const QCString& appId, const uint jobNum);
+ void slotTextFinished(const QCString& appId, const uint jobNum);
+ void slotTextStopped(const QCString& appId, const uint jobNum);
+ void slotTextPaused(const QCString& appId, const uint jobNum);
+ void slotTextResumed(const QCString& appId, const uint jobNum);
+ void slotTextRemoved(const QCString& appId, const uint jobNum);
+
+ /*
+ * Fires whenever user clicks Apply or OK buttons in Settings dialog.
+ */
+ void configCommitted();
+
+ private:
+ /*
+ * Checks if KTTSD is ready to speak and at least one talker is configured.
+ * If not, user is prompted to display the configuration dialog.
+ */
+ bool ready();
+
+ /*
+ * Create and initialize the SpeechData object.
+ */
+ bool initializeSpeechData();
+
+ /*
+ * Create and initialize the TalkerMgr object.
+ */
+ bool initializeTalkerMgr();
+
+ /*
+ * Create and initialize the speaker.
+ */
+ bool initializeSpeaker();
+
+ /*
+ * Returns the senderId (appId) of the DCOP application that called us.
+ * @return appId The DCOP sendId of calling application. NULL if called internally by kttsd itself.
+ */
+ const QCString getAppId();
+
+ /*
+ * If a job number is 0, returns the default job number for a command.
+ * Returns the job number of the last job queued by the application, or if
+ * no such job, the current job number.
+ * @return Default job number. 0 if no such job.
+ */
+ uint applyDefaultJobNum(const uint jobNum);
+
+ /*
+ * Fixes a talker argument passed in via dcop.
+ * If NULL or "0" return QString::null.
+ */
+ QString fixNullString(const QString &talker) const;
+
+ /*
+ * SpeechData containing all the data and the manipulating methods for all KTTSD
+ */
+ SpeechData* m_speechData;
+
+ /*
+ * TalkerMgr keeps a list of all the Talkers (synth plugins).
+ */
+ TalkerMgr* m_talkerMgr;
+
+ /*
+ * Speaker that will be run as another thread, actually saying the messages, warnings, and texts
+ */
+ Speaker* m_speaker;
+};
+
+// kspeech is obsolete. Applications should use KSpeech instead.
+class kspeech : public QObject, virtual public KSpeech
+{
+ Q_OBJECT
+ K_DCOP
+
+ public:
+ // Constructor.
+ kspeech(const QCString& objId, QObject *parent=0, const char *name=0);
+
+ // Destructor.
+ ~kspeech();
+
+ // Delegate all DCOP methods to KTTSD object.
+ virtual bool supportsMarkup(const QString &talker, uint markupType = 0) const;
+ virtual bool supportsMarkers(const QString &talker) const;
+ virtual ASYNC sayScreenReaderOutput(const QString &msg, const QString &talker);
+ virtual ASYNC sayWarning(const QString &warning, const QString &talker);
+ virtual ASYNC sayMessage(const QString &message, const QString &talker);
+ virtual ASYNC setSentenceDelimiter(const QString &delimiter);
+ virtual uint setText(const QString &text, const QString &talker);
+ virtual uint sayText(const QString &text, const QString &talker);
+ virtual int appendText(const QString &text, uint jobNum=0);
+ virtual uint setFile(const QString &filename, const QString &talker,
+ const QString& encoding);
+ virtual int getTextCount(uint jobNum=0);
+ virtual uint getCurrentTextJob();
+ virtual uint getTextJobCount();
+ virtual QString getTextJobNumbers();
+ virtual int getTextJobState(uint jobNum=0);
+ virtual QByteArray getTextJobInfo(uint jobNum=0);
+ virtual QString talkerCodeToTalkerId(const QString& talkerCode);
+ virtual QString getTextJobSentence(uint jobNum=0, uint seq=0);
+ virtual bool isSpeakingText() const;
+ virtual ASYNC removeText(uint jobNum=0);
+ virtual ASYNC startText(uint jobNum=0);
+ virtual ASYNC stopText(uint jobNum=0);
+ virtual ASYNC pauseText(uint jobNum=0);
+ virtual ASYNC resumeText(uint jobNum=0);
+ virtual QStringList getTalkers();
+ virtual ASYNC changeTextTalker(const QString &talker, uint jobNum=0 );
+ virtual QString userDefaultTalker();
+ virtual ASYNC moveTextLater(uint jobNum=0);
+ virtual int jumpToTextPart(int partNum, uint jobNum=0);
+ virtual uint moveRelTextSentence(int n, uint jobNum=0);
+ virtual ASYNC speakClipboard();
+ virtual void showDialog();
+ virtual void kttsdExit();
+ virtual void reinit();
+ virtual QString version();
+
+ private:
+ KTTSD m_kttsd;
+};
+
+#endif // _KTTSD_H_
diff --git a/kttsd/kttsd/main.cpp b/kttsd/kttsd/main.cpp
new file mode 100644
index 0000000..3c47df4
--- /dev/null
+++ b/kttsd/kttsd/main.cpp
@@ -0,0 +1,68 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Where the main function for KTTSD resides.
+ -------------------
+ Copyright:
+ (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kuniqueapplication.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <dcopclient.h>
+
+#include "kttsd.h"
+
+int main (int argc, char *argv[]){
+ KLocale::setMainCatalogue("kttsd");
+ KAboutData aboutdata("kttsd", I18N_NOOP("kttsd"),
+ "0.3.5.2", I18N_NOOP("Text-to-speech synthesis deamon"),
+ KAboutData::License_GPL, "(C) 2002, José Pablo Ezequiel Fernández");
+ aboutdata.addAuthor("José Pablo Ezequiel Fernández",I18N_NOOP("Original Author"),"pupeno@pupeno.com");
+ aboutdata.addAuthor("Gary Cramblitt", I18N_NOOP("Maintainer"),"garycramblitt@comcast.net");
+ aboutdata.addAuthor("Gunnar Schmi Dt", I18N_NOOP("Contributor"),"gunnar@schmi-dt.de");
+ aboutdata.addAuthor("Olaf Schmidt", I18N_NOOP("Contributor"),"ojschmidt@kde.org");
+ aboutdata.addAuthor("Paul Giannaros", I18N_NOOP("Contributor"), "ceruleanblaze@gmail.com");
+ aboutdata.addCredit("Jorge Luis Arzola", I18N_NOOP("Testing"), "arzolacub@hotmail.com");
+ aboutdata.addCredit("David Powell", I18N_NOOP("Testing"), "achiestdragon@gmail.com");
+
+ KCmdLineArgs::init( argc, argv, &aboutdata );
+ // KCmdLineArgs::addCmdLineOptions( options );
+ KUniqueApplication::addCmdLineOptions();
+
+ if(!KUniqueApplication::start()){
+ kdDebug() << "KTTSD is already running" << endl;
+ return (0);
+ }
+
+ KUniqueApplication app;
+ // This app is started automatically, no need for session management
+ app.disableSessionManagement();
+ // TODO: kspeech is obsolete. Use KSpeech instead. For backwards compatibility,
+ // kspeech creates the "real" KSpeech object (KTTSD). At some point in the future,
+ // change following statement to
+ // KTTSD *service = new KTTSD("KSpeech");
+ kspeech *service = new kspeech("kspeech");
+
+ // kdDebug() << "Entering event loop." << endl;
+ return app.exec();
+ delete service;
+}
diff --git a/kttsd/kttsd/speaker.cpp b/kttsd/kttsd/speaker.cpp
new file mode 100644
index 0000000..b965a9e
--- /dev/null
+++ b/kttsd/kttsd/speaker.cpp
@@ -0,0 +1,1701 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Speaker class.
+ This class is in charge of getting the messages, warnings and text from
+ the queue and call the plug ins function to actually speak the texts.
+ -------------------
+ Copyright:
+ (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández
+ ******************************************************************************/
+
+/******************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License. *
+ * *
+ ******************************************************************************/
+
+// Qt includes.
+#include <qfile.h>
+#include <qtimer.h>
+#include <qdir.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <klocale.h>
+#include <kparts/componentfactory.h>
+#include <ktrader.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+//#include <kio/job.h>
+
+// KTTSD includes.
+#include "player.h"
+#include "speaker.h"
+#include "speaker.moc"
+#include "talkermgr.h"
+#include "utils.h"
+
+/**
+* The Speaker class takes sentences from the text queue, messages from the
+* messages queue, warnings from the warnings queue, and Screen Reader
+* output and places them into an internal "utterance queue". It then
+* loops through this queue, farming the work off to the plugins.
+* It tries to optimize processing so as to keep the plugins busy as
+* much as possible, while ensuring that only one stream of audio is
+* heard at any one time.
+*
+* The message queues are maintained in the SpeechData class.
+*
+* Text jobs in the text queue each have a state (queued, speakable,
+* speaking, paused, finished). Each plugin has a state (idle, saying, synthing,
+* or finished). And finally, each utterance has a state (waiting, saying,
+* synthing, playing, finished). It can be confusing if you are not aware
+* of all these states.
+*
+* Speaker takes some pains to ensure speech is spoken in the correct order,
+* namely Screen Reader Output has the highest priority, Warnings are next,
+* Messages are next, and finally regular text jobs. Since Screen Reader
+* Output, Warnings, and Messages can be queued in the middle of a text
+* job, Speaker must be prepared to reorder utterances in its queue.
+*
+* At the same time, it must issue the signals to inform programs
+* what is happening.
+*
+* Finally, users can pause, restart, delete, advance, or rewind text jobs
+* and Speaker must respond to these commands. In some cases, utterances that
+* have already been synthesized and are ready for audio output must be
+* discarded in response to these commands.
+*
+* Some general guidelines for programmers modifying this code:
+* - Avoid blocking at all cost. If a plugin won't stopText, keep going.
+* You might have to wait for the plugin to complete before asking it
+* to perform the next operation, but in the meantime, there might be
+* other useful work that can be performed.
+* - In no case allow the main thread Qt event loop to block.
+* - Plugins that do not have asynchronous support are wrapped in the
+* ThreadedPlugin class, which attempts to make them as asynchronous as
+* it can, but there are limits.
+* - doUtterances is the main worker method. If in doubt, call doUtterances.
+* - Because Speaker controls the ordering of utterances, most sequence-related
+* signals must be emitted by Speaker; not SpeechData. Only the add
+* and delete job-related signals eminate from SpeechData.
+* - The states of the 3 types of objects mentioned above (jobs, utterances,
+* and plugins) can interact in subtle ways. Test fully. For example, while
+* a text job might be in a paused state, the plugin could be synthesizing
+* in anticipation of resume, or sythesizing a Warning, Message, or
+* Screen Reader Output. Meanwhile, while one of the utterances might
+* have a paused state, others from the same job could be synthing, waiting,
+* or finished.
+* - There can be more than one Audio Player object in existence at one time, although
+* there must never be more than one actually playing at one time. For
+* example, an Audio Player playing an utterance from a text job can be
+* in a paused state, while another Audio Player is playing a Screen Reader
+* Output utterance. Finally, since some plugins do their own audio, it
+* might be that none of the Audio Player objects are playing.
+*/
+
+/* Public Methods ==========================================================*/
+
+/**
+* Constructor.
+* Loads plugins.
+*/
+Speaker::Speaker( SpeechData*speechData, TalkerMgr* talkerMgr,
+ QObject *parent, const char *name) :
+ QObject(parent, name),
+ m_speechData(speechData),
+ m_talkerMgr(talkerMgr)
+{
+ // kdDebug() << "Running: Speaker::Speaker()" << endl;
+ m_exitRequested = false;
+ m_textInterrupted = false;
+ m_currentJobNum = 0;
+ m_lastAppId = 0;
+ m_lastJobNum = 0;
+ m_lastSeq = 0;
+ m_timer = new QTimer(this, "kttsdAudioTimer");
+ m_speechData->config->setGroup("General");
+ m_playerOption = m_speechData->config->readNumEntry("AudioOutputMethod", 0); // default to aRts.
+ // Map 50% to 100% onto 2.0 to 0.5.
+ m_audioStretchFactor = 1.0/(float(m_speechData->config->readNumEntry("AudioStretchFactor", 100))/100.0);
+ switch (m_playerOption)
+ {
+ case 0: break;
+ case 1:
+ m_speechData->config->setGroup("GStreamerPlayer");
+ m_sinkName = m_speechData->config->readEntry("SinkName", "osssink");
+ m_periodSize = m_speechData->config->readNumEntry("PeriodSize", 128);
+ m_periods = m_speechData->config->readNumEntry("Periods", 8);
+ m_playerDebugLevel = m_speechData->config->readNumEntry("DebugLevel", 1);
+ break;
+ case 2:
+ m_speechData->config->setGroup("ALSAPlayer");
+ m_sinkName = m_speechData->config->readEntry("PcmName", "default");
+ if ("custom" == m_sinkName)
+ m_sinkName = m_speechData->config->readEntry("CustomPcmName", "default");
+ m_periodSize = m_speechData->config->readNumEntry("PeriodSize", 128);
+ m_periods = m_speechData->config->readNumEntry("Periods", 8);
+ m_playerDebugLevel = m_speechData->config->readNumEntry("DebugLevel", 1);
+ break;
+ case 3:
+ m_speechData->config->setGroup("aKodePlayer");
+ m_sinkName = m_speechData->config->readEntry("SinkName", "auto");
+ m_periodSize = m_speechData->config->readNumEntry("PeriodSize", 128);
+ m_periods = m_speechData->config->readNumEntry("Periods", 8);
+ m_playerDebugLevel = m_speechData->config->readNumEntry("DebugLevel", 1);
+ break;
+ }
+ // Connect timer timeout signal.
+ connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
+
+ // Connect plugins to slots.
+ QPtrList<PlugInProc> plugins = m_talkerMgr->getLoadedPlugIns();
+ const int pluginsCount = plugins.count();
+ for (int ndx = 0; ndx < pluginsCount; ++ndx)
+ {
+ PlugInProc* speech = plugins.at(ndx);
+ connect(speech, SIGNAL(synthFinished()),
+ this, SLOT(slotSynthFinished()));
+ connect(speech, SIGNAL(sayFinished()),
+ this, SLOT(slotSayFinished()));
+ connect(speech, SIGNAL(stopped()),
+ this, SLOT(slotStopped()));
+ connect(speech, SIGNAL(error(bool, const QString&)),
+ this, SLOT(slotError(bool, const QString&)));
+ }
+}
+
+/**
+* Destructor.
+*/
+Speaker::~Speaker(){
+ // kdDebug() << "Running: Speaker::~Speaker()" << endl;
+ m_timer->stop();
+ delete m_timer;
+ if (!m_uttQueue.isEmpty())
+ {
+ uttIterator it;
+ for (it = m_uttQueue.begin(); it != m_uttQueue.end(); )
+ it = deleteUtterance(it);
+ }
+}
+
+/**
+ * Tells the speaker it is requested to exit.
+ * TODO: I don't think this actually accomplishes anything.
+ */
+void Speaker::requestExit(){
+ // kdDebug() << "Speaker::requestExit: Running" << endl;
+ m_exitRequested = true;
+}
+
+/**
+ * Main processing loop. Dequeues utterances and sends them to the
+ * plugins and/or Audio Player.
+ */
+void Speaker::doUtterances()
+{
+ // kdDebug() << "Running: Speaker::doUtterances()" << endl;
+
+ // Used to prevent exiting prematurely.
+ m_again = true;
+
+ while(m_again && !m_exitRequested)
+ {
+ m_again = false;
+
+ if (m_exitRequested)
+ {
+ // kdDebug() << "Speaker::run: exiting due to request 1." << endl;
+ return;
+ }
+
+ uttIterator it;
+ uttIterator itBegin;
+ uttIterator itEnd = 0; // Init to zero to avoid compiler warning.
+
+ // If Screen Reader Output is waiting, we need to process it ASAP.
+ if (m_speechData->screenReaderOutputReady())
+ {
+ m_again = getNextUtterance();
+ }
+// kdDebug() << "Speaker::doUtterances: queue dump:" << endl;
+// for (it = m_uttQueue.begin(); it != m_uttQueue.end(); ++it)
+// {
+// QString pluginState = "no plugin";
+// if (it->plugin) pluginState = pluginStateToStr(it->plugin->getState());
+// QString jobState =
+// jobStateToStr(m_speechData->getTextJobState(it->sentence->jobNum));
+// kdDebug() <<
+// " State: " << uttStateToStr(it->state) <<
+// "," << pluginState <<
+// "," << jobState <<
+// " Type: " << uttTypeToStr(it->utType) <<
+// " Text: " << it->sentence->text << endl;
+// }
+
+ if (!m_uttQueue.isEmpty())
+ {
+ // Delete utterances that are finished.
+ it = m_uttQueue.begin();
+ while (it != m_uttQueue.end())
+ {
+ if (it->state == usFinished)
+ it = deleteUtterance(it);
+ else
+ ++it;
+ }
+ // Loop through utterance queue.
+ int waitingCnt = 0;
+ int waitingMsgCnt = 0;
+ int transformingCnt = 0;
+ bool playing = false;
+ int synthingCnt = 0;
+ itEnd = m_uttQueue.end();
+ itBegin = m_uttQueue.begin();
+ for (it = itBegin; it != itEnd; ++it)
+ {
+ uttState utState = it->state;
+ uttType utType = it->utType;
+ switch (utState)
+ {
+ case usNone:
+ {
+ setInitialUtteranceState(*it);
+ m_again = true;
+ break;
+ }
+ case usWaitingTransform:
+ {
+ // Create an XSLT transformer and transform the text.
+ it->transformer = new SSMLConvert();
+ connect(it->transformer, SIGNAL(transformFinished()),
+ this, SLOT(slotTransformFinished()));
+ if (it->transformer->transform(it->sentence->text,
+ it->plugin->getSsmlXsltFilename()))
+ {
+ it->state = usTransforming;
+ ++transformingCnt;
+ }
+ else
+ {
+ // If an error occurs transforming, skip it.
+ it->state = usTransforming;
+ setInitialUtteranceState(*it);
+ }
+ m_again = true;
+ break;
+ }
+ case usTransforming:
+ {
+ // See if transformer is finished.
+ if (it->transformer->getState() == SSMLConvert::tsFinished)
+ {
+ // Get the transformed text.
+ it->sentence->text = it->transformer->getOutput();
+ // Set next state (usWaitingSynth or usWaitingSay)
+ setInitialUtteranceState(*it);
+ m_again = true;
+ --transformingCnt;
+ }
+ break;
+ }
+ case usWaitingSignal:
+ {
+ // If first in queue, emit signal.
+ if (it == itBegin)
+ {
+ if (utType == utStartOfJob)
+ {
+ m_speechData->setTextJobState(
+ it->sentence->jobNum, KSpeech::jsSpeaking);
+ if (it->sentence->seq == 0)
+ emit textStarted(it->sentence->appId,
+ it->sentence->jobNum);
+ else
+ emit textResumed(it->sentence->appId,
+ it->sentence->jobNum);
+ } else {
+ m_speechData->setTextJobState(
+ it->sentence->jobNum, KSpeech::jsFinished);
+ emit textFinished(it->sentence->appId, it->sentence->jobNum);
+ }
+ it->state = usFinished;
+ m_again = true;
+ }
+ break;
+ }
+ case usSynthed:
+ {
+ // Don't bother stretching if factor is 1.0.
+ // Don't bother stretching if SSML.
+ // TODO: This is because sox mangles SSML pitch settings. Would be nice
+ // to figure out how to avoid this.
+ if (m_audioStretchFactor == 1.0 || it->isSSML)
+ {
+ it->state = usStretched;
+ m_again = true;
+ }
+ else
+ {
+ it->audioStretcher = new Stretcher();
+ connect(it->audioStretcher, SIGNAL(stretchFinished()),
+ this, SLOT(slotStretchFinished()));
+ if (it->audioStretcher->stretch(it->audioUrl, makeSuggestedFilename(),
+ m_audioStretchFactor))
+ {
+ it->state = usStretching;
+ m_again = true; // Is this needed?
+ }
+ else
+ {
+ // If stretch failed, it is most likely caused by sox not being
+ // installed. Just skip it.
+ it->state = usStretched;
+ m_again = true;
+ delete it->audioStretcher;
+ it->audioStretcher= 0;
+ }
+ }
+ break;
+ }
+ case usStretching:
+ {
+ // See if Stretcher is finished.
+ if (it->audioStretcher->getState() == Stretcher::ssFinished)
+ {
+ QFile::remove(it->audioUrl);
+ it->audioUrl = it->audioStretcher->getOutFilename();
+ it->state = usStretched;
+ delete it->audioStretcher;
+ it->audioStretcher = 0;
+ m_again = true;
+ }
+ break;
+ }
+ case usStretched:
+ {
+ // If first in queue, start playback.
+ if (it == itBegin)
+ {
+ if (startPlayingUtterance(it))
+ {
+ playing = true;
+ m_again = true;
+ } else {
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ }
+ } else {
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ }
+ break;
+ }
+ case usPlaying:
+ {
+ playing = true;
+ break;
+ }
+ case usPaused:
+ case usPreempted:
+ {
+ if (!playing)
+ {
+ if (startPlayingUtterance(it))
+ {
+ playing = true;
+ m_again = true;
+ } else {
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ }
+ } else {
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ }
+ break;
+ }
+ case usWaitingSay:
+ {
+ // If first in queue, start it.
+ if (it == itBegin)
+ {
+ int jobState =
+ m_speechData->getTextJobState(it->sentence->jobNum);
+ if ((jobState == KSpeech::jsSpeaking) ||
+ (jobState == KSpeech::jsSpeakable))
+ {
+ if (it->plugin->getState() == psIdle)
+ {
+ // Set job to speaking state and set sequence number.
+ mlText* sentence = it->sentence;
+ m_currentJobNum = sentence->jobNum;
+ m_speechData->setTextJobState(m_currentJobNum, KSpeech::jsSpeaking);
+ m_speechData->setJobSequenceNum(m_currentJobNum, sentence->seq);
+ prePlaySignals(it);
+ // kdDebug() << "Async synthesis and audibilizing." << endl;
+ it->state = usSaying;
+ playing = true;
+ it->plugin->sayText(it->sentence->text);
+ m_again = true;
+ } else {
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ }
+ } else {
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ }
+ } else {
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ }
+ break;
+ }
+ case usWaitingSynth:
+ {
+ // TODO: If the synth is busy and the waiting text is screen
+ // reader output, it would be nice to call the synth's
+ // stopText() method. However, some of the current plugins
+ // have horrible startup times, so we won't do that for now.
+ if (it->plugin->getState() == psIdle)
+ {
+ // kdDebug() << "Async synthesis." << endl;
+ it->state = usSynthing;
+ ++synthingCnt;
+ it->plugin->synthText(it->sentence->text,
+ makeSuggestedFilename());
+ m_again = true;
+ }
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ break;
+ }
+ case usSaying:
+ {
+ // See if synthesis and audibilizing is finished.
+ if (it->plugin->getState() == psFinished)
+ {
+ it->plugin->ackFinished();
+ it->state = usFinished;
+ m_again = true;
+ } else {
+ playing = true;
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ }
+ break;
+ }
+ case usSynthing:
+ {
+ // See if synthesis is completed.
+ if (it->plugin->getState() == psFinished)
+ {
+ it->audioUrl = KStandardDirs::realFilePath(it->plugin->getFilename());
+ // kdDebug() << "Speaker::doUtterances: synthesized filename: " << it->audioUrl << endl;
+ it->plugin->ackFinished();
+ it->state = usSynthed;
+ m_again = true;
+ } else ++synthingCnt;
+ ++waitingCnt;
+ if (utType == utWarning || utType == utMessage) ++waitingMsgCnt;
+ break;
+ }
+ case usFinished: break;
+ }
+ }
+ // See if there are any messages or warnings to process.
+ // We keep up to 2 such utterances in the queue.
+ if ((waitingMsgCnt < 2) && (transformingCnt < 3))
+ {
+ if (m_speechData->warningInQueue() || m_speechData->messageInQueue())
+ {
+ getNextUtterance();
+ m_again = true;
+ }
+ }
+ // Try to keep at least two utterances in the queue waiting to be played,
+ // and no more than 3 transforming at one time.
+ if ((waitingCnt < 2) && (transformingCnt < 3))
+ if (getNextUtterance()) m_again = true;
+ } else {
+ // See if another utterance is ready to be worked on.
+ // If so, loop again since we've got work to do.
+ m_again = getNextUtterance();
+ }
+ }
+ // kdDebug() << "Speaker::doUtterances: exiting." << endl;
+}
+
+/**
+ * Determine if kttsd is currently speaking any text jobs.
+ * @return True if currently speaking any text jobs.
+ */
+bool Speaker::isSpeakingText()
+{
+ return (m_speechData->getTextJobState(m_currentJobNum) == KSpeech::jsSpeaking);
+}
+
+/**
+ * Get the job number of the current text job.
+ * @return Job number of the current text job. 0 if no jobs.
+ *
+ * Note that the current job may not be speaking. See @ref isSpeakingText.
+ */
+uint Speaker::getCurrentTextJob() { return m_currentJobNum; }
+
+/**
+ * Remove a text job from the queue.
+ * @param jobNum Job number of the text job.
+ *
+ * The job is deleted from the queue and the @ref textRemoved signal is emitted.
+ *
+ * If there is another job in the text queue, and it is marked speakable,
+ * that job begins speaking.
+ */
+void Speaker::removeText(const uint jobNum)
+{
+ deleteUtteranceByJobNum(jobNum);
+ m_speechData->removeText(jobNum);
+ doUtterances();
+}
+
+/**
+ * Start a text job at the beginning.
+ * @param jobNum Job number of the text job.
+ *
+ * Rewinds the job to the beginning.
+ *
+ * The job is marked speakable.
+ * If there are other speakable jobs preceeding this one in the queue,
+ * those jobs continue speaking and when finished, this job will begin speaking.
+ * If there are no other speakable jobs preceeding this one, it begins speaking.
+ *
+ * The @ref textStarted signal is emitted when the text job begins speaking.
+ * When all the sentences of the job have been spoken, the job is marked for deletion from
+ * the text queue and the @ref textFinished signal is emitted.
+ */
+void Speaker::startText(const uint jobNum)
+{
+ deleteUtteranceByJobNum(jobNum);
+ m_speechData->setJobSequenceNum(jobNum, 1);
+ m_speechData->setTextJobState(jobNum, KSpeech::jsSpeakable);
+ if (m_lastJobNum == jobNum)
+ {
+ // kdDebug() << "Speaker::startText: startText called on speaking job " << jobNum << endl;
+ m_lastJobNum = 0;
+ m_lastAppId = 0;
+ m_lastSeq = 0;
+ }
+ doUtterances();
+}
+
+/**
+ * Stop a text job and rewind to the beginning.
+ * @param jobNum Job number of the text job.
+ *
+ * The job is marked not speakable and will not be speakable until @ref startText or @ref resumeText
+ * is called.
+ *
+ * If there are speaking jobs preceeding this one in the queue, they continue speaking.
+ * If the job is currently speaking, the @ref textStopped signal is emitted and the job stops speaking.
+ * Depending upon the speech engine and plugin used, speeking may not stop immediately
+ * (it might finish the current sentence).
+ */
+void Speaker::stopText(const uint jobNum)
+{
+ bool emitSignal = (m_speechData->getTextJobState(jobNum) == KSpeech::jsSpeaking);
+ deleteUtteranceByJobNum(jobNum);
+ m_speechData->setJobSequenceNum(jobNum, 1);
+ m_speechData->setTextJobState(jobNum, KSpeech::jsQueued);
+ if (emitSignal) textStopped(m_speechData->getAppIdByJobNum(jobNum), jobNum);
+ // Call doUtterances to process other jobs.
+ doUtterances();
+}
+
+/**
+ * Pause a text job.
+ * @param jobNum Job number of the text job.
+ *
+ * The job is marked as paused and will not be speakable until @ref resumeText or
+ * @ref startText is called.
+ *
+ * If there are speaking jobs preceeding this one in the queue, they continue speaking.
+ * If the job is currently speaking, the @ref textPaused signal is emitted and the job stops speaking.
+ * Depending upon the speech engine and plugin used, speeking may not stop immediately
+ * (it might finish the current sentence).
+ * @see resumeText
+ */
+void Speaker::pauseText(const uint jobNum)
+{
+ bool emitSignal = (m_speechData->getTextJobState(jobNum) == KSpeech::jsSpeaking);
+ pauseUtteranceByJobNum(jobNum);
+ kdDebug() << "Speaker::pauseText: setting Job State of job " << jobNum << " to jsPaused" << endl;
+ m_speechData->setTextJobState(jobNum, KSpeech::jsPaused);
+ if (emitSignal) textPaused(m_speechData->getAppIdByJobNum(jobNum),jobNum);
+}
+
+/**
+ * Start or resume a text job where it was paused.
+ * @param jobNum Job number of the text job.
+ *
+ * The job is marked speakable.
+ *
+ * If the job is currently speaking, or is waiting to be spoken (speakable
+ * state), the resumeText() call is ignored.
+ *
+ * If the job is currently queued, or is finished, it is the same as calling
+ * @ref startText .
+ *
+ * If there are speaking jobs preceeding this one in the queue, those jobs continue speaking and,
+ * when finished this job will begin speaking where it left off.
+ *
+ * The @ref textResumed signal is emitted when the job resumes.
+ * @see pauseText
+ */
+void Speaker::resumeText(const uint jobNum)
+{
+ int state = m_speechData->getTextJobState(jobNum);
+ switch (state)
+ {
+ case KSpeech::jsQueued:
+ case KSpeech::jsFinished:
+ startText(jobNum);
+ break;
+ case KSpeech::jsSpeakable:
+ case KSpeech::jsSpeaking:
+ doUtterances();
+ break;
+ case KSpeech::jsPaused:
+ if (jobNum == m_currentJobNum)
+ m_speechData->setTextJobState(jobNum, KSpeech::jsSpeaking);
+ else
+ m_speechData->setTextJobState(jobNum, KSpeech::jsSpeakable);
+ doUtterances();
+ break;
+ }
+}
+
+/**
+ * Move a text job down in the queue so that it is spoken later.
+ * @param jobNum Job number of the text job.
+ *
+ * If the job is currently speaking, it is paused.
+ * If the next job in the queue is speakable, it begins speaking.
+ */
+void Speaker::moveTextLater(const uint jobNum)
+{
+ if (m_speechData->getTextJobState(jobNum) == KSpeech::jsSpeaking)
+ m_speechData->setTextJobState(jobNum, KSpeech::jsPaused);
+ deleteUtteranceByJobNum(jobNum);
+ m_speechData->moveTextLater(jobNum);
+ doUtterances();
+}
+
+/**
+ * Jump to the first sentence of a specified part of a text job.
+ * @param partNum Part number of the part to jump to. Parts are numbered starting at 1.
+ * @param jobNum Job number of the text job.
+ * @return Part number of the part actually jumped to.
+ *
+ * If partNum is greater than the number of parts in the job, jumps to last part.
+ * If partNum is 0, does nothing and returns the current part number.
+ * If no such job, does nothing and returns 0.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+int Speaker::jumpToTextPart(const int partNum, const uint jobNum)
+{
+ if (partNum == 0) return m_speechData->jumpToTextPart(partNum, jobNum);
+ deleteUtteranceByJobNum(jobNum);
+ int pNum = m_speechData->jumpToTextPart(partNum, jobNum);
+ if (pNum)
+ {
+ uint seq = m_speechData->getJobSequenceNum(jobNum);
+ if (jobNum == m_lastJobNum)
+ {
+ if (seq == 0)
+ m_lastSeq = seq;
+ else
+ m_lastSeq = seq - 1;
+ }
+ if (jobNum == m_currentJobNum)
+ {
+ m_lastJobNum = jobNum;
+ if (seq == 0)
+ m_lastSeq = 0;
+ else
+ m_lastSeq = seq - 1;
+ doUtterances();
+ }
+ }
+ return pNum;
+}
+
+/**
+ * Advance or rewind N sentences in a text job.
+ * @param n Number of sentences to advance (positive) or rewind (negative)
+ * in the job.
+ * @param jobNum Job number of the text job.
+ * @return Sequence number of the sentence actually moved to.
+ * Sequence numbers are numbered starting at 1.
+ *
+ * If no such job, does nothing and returns 0.
+ * If n is zero, returns the current sequence number of the job.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+uint Speaker::moveRelTextSentence(const int n, const uint jobNum)
+{
+ if (0 == n)
+ return m_speechData->getJobSequenceNum(jobNum);
+ else {
+ deleteUtteranceByJobNum(jobNum);
+ // TODO: More efficient way to advance one or two sentences, since there is a
+ // good chance those utterances are already in the queue and synthesized.
+ uint seq = m_speechData->moveRelTextSentence(n, jobNum);
+ kdDebug() << "Speaker::moveRelTextSentence: job num: " << jobNum << " moved to seq: " << seq << endl;
+ if (jobNum == m_lastJobNum)
+ {
+ if (seq == 0)
+ m_lastSeq = seq;
+ else
+ m_lastSeq = seq - 1;
+ }
+ if (jobNum == m_currentJobNum)
+ {
+ m_lastJobNum = jobNum;
+ if (seq == 0)
+ m_lastSeq = 0;
+ else
+ m_lastSeq = seq - 1;
+ doUtterances();
+ }
+ return seq;
+ }
+}
+
+/* Private Methods ==========================================================*/
+
+/**
+ * Converts an utterance state enumerator to a displayable string.
+ * @param state Utterance state.
+ */
+QString Speaker::uttStateToStr(uttState state)
+{
+ switch (state)
+ {
+ case usNone: return "usNone";
+ case usWaitingTransform: return "usWaitingTransform";
+ case usTransforming: return "usTransforming";
+ case usWaitingSay: return "usWaitingSay";
+ case usWaitingSynth: return "usWaitingSynth";
+ case usWaitingSignal: return "usWaitingSignal";
+ case usSaying: return "usSaying";
+ case usSynthing: return "usSynthing";
+ case usSynthed: return "usSynthed";
+ case usStretching: return "usStretching";
+ case usStretched: return "usStretched";
+ case usPlaying: return "usPlaying";
+ case usPaused: return "usPaused";
+ case usPreempted: return "usPreempted";
+ case usFinished: return "usFinished";
+ }
+ return QString::null;
+}
+
+/**
+ * Converts an utterance type enumerator to a displayable string.
+ * @param utType Utterance type.
+ * @return Displayable string for utterance type.
+ */
+QString Speaker::uttTypeToStr(uttType utType)
+{
+ switch (utType)
+ {
+ case utText: return "utText";
+ case utInterruptMsg: return "utInterruptMsg";
+ case utInterruptSnd: return "utInterruptSnd";
+ case utResumeMsg: return "utResumeMsg";
+ case utResumeSnd: return "utResumeSnd";
+ case utMessage: return "utMessage";
+ case utWarning: return "utWarning";
+ case utScreenReader: return "utScreenReader";
+ case utStartOfJob: return "utStartOfJob";
+ case utEndOfJob: return "utEndOfJob";
+ }
+ return QString::null;
+}
+
+/**
+ * Converts a plugin state enumerator to a displayable string.
+ * @param state Plugin state.
+ * @return Displayable string for plugin state.
+ */
+QString Speaker::pluginStateToStr(pluginState state)
+{
+ switch( state )
+ {
+ case psIdle: return "psIdle";
+ case psSaying: return "psSaying";
+ case psSynthing: return "psSynthing";
+ case psFinished: return "psFinished";
+ }
+ return QString::null;
+}
+
+/**
+ * Converts a job state enumerator to a displayable string.
+ * @param state Job state.
+ * @return Displayable string for job state.
+ */
+QString Speaker::jobStateToStr(int state)
+{
+ switch ( state )
+ {
+ case KSpeech::jsQueued: return "jsQueued";
+ case KSpeech::jsSpeakable: return "jsSpeakable";
+ case KSpeech::jsSpeaking: return "jsSpeaking";
+ case KSpeech::jsPaused: return "jsPaused";
+ case KSpeech::jsFinished: return "jsFinished";
+ }
+ return QString::null;
+}
+
+/**
+ * Delete any utterances in the queue with this jobNum.
+ * @param jobNum Job Number of the utterances to delete.
+ * If currently processing any deleted utterances, stop them.
+ */
+void Speaker::deleteUtteranceByJobNum(const uint jobNum)
+{
+ uttIterator it = m_uttQueue.begin();
+ while (it != m_uttQueue.end())
+ {
+ if (it->sentence)
+ {
+ if (it->sentence->jobNum == jobNum)
+ it = deleteUtterance(it);
+ else
+ ++it;
+ } else
+ ++it;
+ }
+}
+
+/**
+ * Pause the utterance with this jobNum if it is playing on the Audio Player.
+ * @param jobNum The Job Number of the utterance to pause.
+ */
+void Speaker::pauseUtteranceByJobNum(const uint jobNum)
+{
+ uttIterator itEnd = m_uttQueue.end();
+ for (uttIterator it = m_uttQueue.begin(); it != itEnd; ++it)
+ {
+ if (it->sentence) // TODO: Why is this necessary?
+ if (it->sentence->jobNum == jobNum)
+ if (it->state == usPlaying)
+ {
+ if (it->audioPlayer)
+ if (it->audioPlayer->playing())
+ {
+ m_timer->stop();
+ kdDebug() << "Speaker::pauseUtteranceByJobNum: pausing audio player" << endl;
+ it->audioPlayer->pause();
+ kdDebug() << "Speaker::pauseUtteranceByJobNum: Setting utterance state to usPaused" << endl;
+ it->state = usPaused;
+ return;
+ }
+ // Audio player has finished, but timeout hasn't had a chance
+ // to clean up. So do nothing, and let timeout do the cleanup.
+ }
+ }
+}
+
+/**
+ * Determines whether the given text is SSML markup.
+ */
+bool Speaker::isSsml(const QString &text)
+{
+ return KttsUtils::hasRootElement( text, "speak" );
+}
+
+/**
+ * Determines the initial state of an utterance. If the utterance contains
+ * SSML, the state is set to usWaitingTransform. Otherwise, if the plugin
+ * supports async synthesis, sets to usWaitingSynth, otherwise usWaitingSay.
+ * If an utterance has already been transformed, usWaitingTransform is
+ * skipped to either usWaitingSynth or usWaitingSay.
+ * @param utt The utterance.
+ */
+void Speaker::setInitialUtteranceState(Utt &utt)
+{
+ if ((utt.state != usTransforming) && utt.isSSML)
+{
+ utt.state = usWaitingTransform;
+ return;
+}
+ if (utt.plugin->supportsSynth())
+ utt.state = usWaitingSynth;
+ else
+ utt.state = usWaitingSay;
+}
+
+/**
+ * Returns true if the given job and sequence number are already in the utterance queue.
+ */
+bool Speaker::isInUtteranceQueue(uint jobNum, uint seqNum)
+{
+ uttIterator itEnd = m_uttQueue.end();
+ for (uttIterator it = m_uttQueue.begin(); it != itEnd; ++it)
+ {
+ if (it->sentence)
+ {
+ if (it->sentence->jobNum == jobNum && it->sentence->seq == seqNum) return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Gets the next utterance to be spoken from speechdata and adds it to the queue.
+ * @return True if one or more utterances were added to the queue.
+ *
+ * Checks for waiting ScreenReaderOutput, Warnings, Messages, or Text,
+ * in that order.
+ * If Warning or Message and interruption messages have been configured,
+ * adds those to the queue as well.
+ * Determines which plugin should be used for the utterance.
+ */
+bool Speaker::getNextUtterance()
+{
+ bool gotOne = false;
+ Utt* utt = 0;
+ if (m_speechData->screenReaderOutputReady()) {
+ utt = new Utt;
+ utt->utType = utScreenReader;
+ utt->sentence = m_speechData->getScreenReaderOutput();
+ } else {
+ if (m_speechData->warningInQueue()) {
+ utt = new Utt;
+ utt->utType = utWarning;
+ utt->sentence = m_speechData->dequeueWarning();
+ } else {
+ if (m_speechData->messageInQueue()) {
+ utt = new Utt;
+ utt->utType = utMessage;
+ utt->sentence = m_speechData->dequeueMessage();
+ } else {
+ uint jobNum = m_lastJobNum;
+ uint seq = m_lastSeq;
+ mlText* sentence = m_speechData->getNextSentenceText(jobNum, seq);
+ // Skip over blank lines.
+ while (sentence && sentence->text.isEmpty())
+ {
+ jobNum = sentence->jobNum;
+ seq = sentence->seq;
+ sentence = m_speechData->getNextSentenceText(jobNum, seq);
+ }
+ // If this utterance is already in the queue, it means we have run out of
+ // stuff to say and are trying to requeue already queued (and waiting stuff).
+ if (sentence && !isInUtteranceQueue(sentence->jobNum, sentence->seq))
+ {
+ utt = new Utt;
+ utt->utType = utText;
+ utt->sentence = sentence;
+ }
+ }
+ }
+ }
+ if (utt)
+ {
+ gotOne = true;
+ utt->isSSML = isSsml(utt->sentence->text);
+ utt->state = usNone;
+ utt->audioPlayer = 0;
+ utt->audioStretcher = 0;
+ utt->audioUrl = QString::null;
+ utt->plugin = m_talkerMgr->talkerToPlugin(utt->sentence->talker);
+ // Save some time by setting initial state now.
+ setInitialUtteranceState(*utt);
+ // Screen Reader Outputs need to be processed ASAP.
+ if (utt->utType == utScreenReader)
+ {
+ m_uttQueue.insert(m_uttQueue.begin(), *utt);
+ // Delete any other Screen Reader Outputs in the queue.
+ // Only one Screen Reader Output at a time.
+ uttIterator it = m_uttQueue.begin();
+ ++it;
+ while (it != m_uttQueue.end())
+ {
+ if (it->utType == utScreenReader)
+ it = deleteUtterance(it);
+ else
+ ++it;
+ }
+ }
+ // If the new utterance is a Warning or Message...
+ if ((utt->utType == utWarning) || (utt->utType == utMessage))
+ {
+ uttIterator itEnd = m_uttQueue.end();
+ uttIterator it = m_uttQueue.begin();
+ bool interrupting = false;
+ if (it != itEnd)
+ {
+ // New Warnings go after Screen Reader Output, other Warnings,
+ // Interruptions, and in-process text,
+ // but before Resumes, waiting text or signals.
+ if (utt->utType == utWarning)
+ while ( it != itEnd &&
+ ((it->utType == utScreenReader) ||
+ (it->utType == utWarning) ||
+ (it->utType == utInterruptMsg) ||
+ (it->utType == utInterruptSnd))) ++it;
+ // New Messages go after Screen Reader Output, Warnings, other Messages,
+ // Interruptions, and in-process text,
+ // but before Resumes, waiting text or signals.
+ if (utt->utType == utMessage)
+ while ( it != itEnd &&
+ ((it->utType == utScreenReader) ||
+ (it->utType == utWarning) ||
+ (it->utType == utMessage) ||
+ (it->utType == utInterruptMsg) ||
+ (it->utType == utInterruptSnd))) ++it;
+ if (it != itEnd)
+ if (it->utType == utText &&
+ ((it->state == usPlaying) ||
+ (it->state == usSaying))) ++it;
+ // If now pointing at a text message, we are interrupting.
+ // Insert optional Interruption message and sound.
+ if (it != itEnd) interrupting = (it->utType == utText && it->state != usPaused);
+ if (interrupting)
+ {
+ if (m_speechData->textPreSndEnabled)
+ {
+ Utt intrUtt;
+ intrUtt.sentence = new mlText;
+ intrUtt.sentence->text = QString::null;
+ intrUtt.sentence->talker = utt->sentence->talker;
+ intrUtt.sentence->appId = utt->sentence->appId;
+ intrUtt.sentence->jobNum = utt->sentence->jobNum;
+ intrUtt.sentence->seq = 0;
+ intrUtt.audioUrl = m_speechData->textPreSnd;
+ intrUtt.audioPlayer = 0;
+ intrUtt.utType = utInterruptSnd;
+ intrUtt.isSSML = false;
+ intrUtt.state = usStretched;
+ intrUtt.plugin = 0;
+ it = m_uttQueue.insert(it, intrUtt);
+ ++it;
+ }
+ if (m_speechData->textPreMsgEnabled)
+ {
+ Utt intrUtt;
+ intrUtt.sentence = new mlText;
+ intrUtt.sentence->text = m_speechData->textPreMsg;
+ // Interruptions are spoken using default Talker.
+ intrUtt.sentence->talker = QString::null;
+ intrUtt.sentence->appId = utt->sentence->appId;
+ intrUtt.sentence->jobNum = utt->sentence->jobNum;
+ intrUtt.sentence->seq = 0;
+ intrUtt.audioUrl = QString::null;
+ intrUtt.audioPlayer = 0;
+ intrUtt.utType = utInterruptMsg;
+ intrUtt.isSSML = isSsml(intrUtt.sentence->text);
+ intrUtt.plugin = m_talkerMgr->talkerToPlugin(intrUtt.sentence->talker);
+ intrUtt.state = usNone;
+ setInitialUtteranceState(intrUtt);
+ it = m_uttQueue.insert(it, intrUtt);
+ ++it;
+ }
+ }
+ }
+ // Insert the new message or warning.
+ it = m_uttQueue.insert(it, *utt);
+ ++it;
+ // Resumption message and sound.
+ if (interrupting)
+ {
+ if (m_speechData->textPostSndEnabled)
+ {
+ Utt resUtt;
+ resUtt.sentence = new mlText;
+ resUtt.sentence->text = QString::null;
+ resUtt.sentence->talker = utt->sentence->talker;
+ resUtt.sentence->appId = utt->sentence->appId;
+ resUtt.sentence->jobNum = utt->sentence->jobNum;
+ resUtt.sentence->seq = 0;
+ resUtt.audioUrl = m_speechData->textPostSnd;
+ resUtt.audioPlayer = 0;
+ resUtt.utType = utResumeSnd;
+ resUtt.isSSML = false;
+ resUtt.state = usStretched;
+ resUtt.plugin = 0;
+ it = m_uttQueue.insert(it, resUtt);
+ ++it;
+ }
+ if (m_speechData->textPostMsgEnabled)
+ {
+ Utt resUtt;
+ resUtt.sentence = new mlText;
+ resUtt.sentence->text = m_speechData->textPostMsg;
+ resUtt.sentence->talker = QString::null;
+ resUtt.sentence->appId = utt->sentence->appId;
+ resUtt.sentence->jobNum = utt->sentence->jobNum;
+ resUtt.sentence->seq = 0;
+ resUtt.audioUrl = QString::null;
+ resUtt.audioPlayer = 0;
+ resUtt.utType = utResumeMsg;
+ resUtt.isSSML = isSsml(resUtt.sentence->text);
+ resUtt.plugin = m_talkerMgr->talkerToPlugin(resUtt.sentence->talker);
+ resUtt.state = usNone;
+ setInitialUtteranceState(resUtt);
+ it = m_uttQueue.insert(it, resUtt);
+ }
+ }
+ }
+ // If a text message...
+ if (utt->utType == utText)
+ {
+ // If job number has changed...
+ if (utt->sentence->jobNum != m_lastJobNum)
+ {
+ // If we finished the last job, append End-of-job to the queue,
+ // which will become a textFinished signal when it is processed.
+ if (m_lastJobNum)
+ {
+ if (m_lastSeq == static_cast<uint>(m_speechData->getTextCount(m_lastJobNum)))
+ {
+ Utt jobUtt;
+ jobUtt.sentence = new mlText;
+ jobUtt.sentence->text = QString::null;
+ jobUtt.sentence->talker = QString::null;
+ jobUtt.sentence->appId = m_lastAppId;
+ jobUtt.sentence->jobNum = m_lastJobNum;
+ jobUtt.sentence->seq = 0;
+ jobUtt.audioUrl = QString::null;
+ jobUtt.utType = utEndOfJob;
+ jobUtt.isSSML = false;
+ jobUtt.plugin = 0;
+ jobUtt.state = usWaitingSignal;
+ m_uttQueue.append(jobUtt);
+ }
+ }
+ m_lastJobNum = utt->sentence->jobNum;
+ m_lastAppId = utt->sentence->appId;
+ // If we are at beginning of new job, append Start-of-job to queue,
+ // which will become a textStarted signal when it is processed.
+ if (utt->sentence->seq == 1)
+ {
+ Utt jobUtt;
+ jobUtt.sentence = new mlText;
+ jobUtt.sentence->text = QString::null;
+ jobUtt.sentence->talker = QString::null;
+ jobUtt.sentence->appId = m_lastAppId;
+ jobUtt.sentence->jobNum = m_lastJobNum;
+ jobUtt.sentence->seq = utt->sentence->seq;
+ jobUtt.audioUrl = QString::null;
+ jobUtt.utType = utStartOfJob;
+ jobUtt.isSSML = false;
+ jobUtt.plugin = 0;
+ jobUtt.state = usWaitingSignal;
+ m_uttQueue.append(jobUtt);
+ }
+ }
+ m_lastSeq = utt->sentence->seq;
+ // Add the new utterance to the queue.
+ m_uttQueue.append(*utt);
+ }
+ delete utt;
+ } else {
+ // If no more text to speak, and we finished the last job, issue textFinished signal.
+ if (m_lastJobNum)
+ {
+ if (m_lastSeq == static_cast<uint>(m_speechData->getTextCount(m_lastJobNum)))
+ {
+ Utt jobUtt;
+ jobUtt.sentence = new mlText;
+ jobUtt.sentence->text = QString::null;
+ jobUtt.sentence->talker = QString::null;
+ jobUtt.sentence->appId = m_lastAppId;
+ jobUtt.sentence->jobNum = m_lastJobNum;
+ jobUtt.sentence->seq = 0;
+ jobUtt.audioUrl = QString::null;
+ jobUtt.utType = utEndOfJob;
+ jobUtt.isSSML = false;
+ jobUtt.plugin = 0;
+ jobUtt.state = usWaitingSignal;
+ m_uttQueue.append(jobUtt);
+ gotOne = true;
+ ++m_lastSeq; // Don't append another End-of-job
+ }
+ }
+ }
+
+ return gotOne;
+}
+
+/**
+ * Given an iterator pointing to the m_uttQueue, deletes the utterance
+ * from the queue. If the utterance is currently being processed by a
+ * plugin or the Audio Player, halts that operation and deletes Audio Player.
+ * Also takes care of deleting temporary audio file.
+ * @param it Iterator pointer to m_uttQueue.
+ * @return Iterator pointing to the next utterance in the
+ * queue, or m_uttQueue.end().
+ */
+uttIterator Speaker::deleteUtterance(uttIterator it)
+{
+ switch (it->state)
+ {
+ case usNone:
+ case usWaitingTransform:
+ case usWaitingSay:
+ case usWaitingSynth:
+ case usWaitingSignal:
+ case usSynthed:
+ case usFinished:
+ case usStretched:
+ break;
+
+ case usTransforming:
+ {
+ delete it->transformer;
+ it->transformer = 0;
+ break;
+ }
+ case usSaying:
+ case usSynthing:
+ {
+ // If plugin supports asynchronous mode, and it is busy, halt it.
+ PlugInProc* plugin = it->plugin;
+ if (it->plugin->supportsAsync())
+ if ((plugin->getState() == psSaying) || (plugin->getState() == psSynthing))
+ {
+ kdDebug() << "Speaker::deleteUtterance calling stopText" << endl;
+ plugin->stopText();
+ }
+ break;
+ }
+ case usStretching:
+ {
+ delete it->audioStretcher;
+ it->audioStretcher = 0;
+ break;
+ }
+ case usPlaying:
+ {
+ m_timer->stop();
+ it->audioPlayer->stop();
+ delete it->audioPlayer;
+ break;
+ }
+ case usPaused:
+ case usPreempted:
+ {
+ // Note: Must call stop(), even if player not currently playing. Why?
+ it->audioPlayer->stop();
+ delete it->audioPlayer;
+ break;
+ }
+ }
+ if (!it->audioUrl.isNull())
+ {
+ // If the audio file was generated by a plugin, delete it.
+ if (it->plugin)
+ {
+ if (m_speechData->keepAudio)
+ {
+ QCString seqStr;
+ seqStr.sprintf("%08i", it->sentence->seq); // Zero-fill to 8 chars.
+ QCString jobStr;
+ jobStr.sprintf("%08i", it->sentence->jobNum);
+ QString dest = m_speechData->keepAudioPath + "/kttsd-" +
+ QString("%1-%2").arg(jobStr).arg(seqStr) + ".wav";
+ QFile::remove(dest);
+ QDir d;
+ d.rename(it->audioUrl, dest);
+ // TODO: This is always producing the following. Why and how to fix?
+ // It moves the files just fine.
+ // kio (KIOJob): stat file:///home/kde-devel/.kde/share/apps/kttsd/audio/kttsd-5-1.wav
+ // kio (KIOJob): error 11 /home/kde-devel/.kde/share/apps/kttsd/audio/kttsd-5-1.wav
+ // kio (KIOJob): This seems to be a suitable case for trying to rename before stat+[list+]copy+del
+ // KIO::move(it->audioUrl, dest, false);
+ }
+ else
+ QFile::remove(it->audioUrl);
+ }
+ }
+ // Delete the utterance from queue.
+ delete it->sentence;
+ return m_uttQueue.erase(it);
+}
+
+/**
+ * Given an iterator pointing to the m_uttQueue, starts playing audio if
+ * 1) An audio file is ready to be played, and
+ * 2) It is not already playing.
+ * If another audio player is already playing, pauses it before starting
+ * the new audio player.
+ * @param it Iterator pointer to m_uttQueue.
+ * @return True if an utterance began playing or resumed.
+ */
+bool Speaker::startPlayingUtterance(uttIterator it)
+{
+ // kdDebug() << "Speaker::startPlayingUtterance running" << endl;
+ if (it->state == usPlaying) return false;
+ if (it->audioUrl.isNull()) return false;
+ bool started = false;
+ // Pause (preempt) any other utterance currently being spoken.
+ // If any plugins are audibilizing, must wait for them to finish.
+ uttIterator itEnd = m_uttQueue.end();
+ for (uttIterator it2 = m_uttQueue.begin(); it2 != itEnd; ++it2)
+ if (it2 != it)
+ {
+ if (it2->state == usPlaying)
+ {
+ m_timer->stop();
+ it2->audioPlayer->pause();
+ it2->state = usPreempted;
+ }
+ if (it2->state == usSaying) return false;
+ }
+ uttState utState = it->state;
+ switch (utState)
+ {
+ case usNone:
+ case usWaitingTransform:
+ case usTransforming:
+ case usWaitingSay:
+ case usWaitingSynth:
+ case usWaitingSignal:
+ case usSaying:
+ case usSynthing:
+ case usSynthed:
+ case usStretching:
+ case usPlaying:
+ case usFinished:
+ break;
+
+ case usStretched:
+ {
+ // Don't start playback yet if text job is paused.
+ if ((it->utType != utText) ||
+ (m_speechData->getTextJobState(it->sentence->jobNum) != KSpeech::jsPaused))
+ {
+
+ it->audioPlayer = createPlayerObject();
+ if (it->audioPlayer)
+ {
+ it->audioPlayer->startPlay(it->audioUrl);
+ // Set job to speaking state and set sequence number.
+ mlText* sentence = it->sentence;
+ m_currentJobNum = sentence->jobNum;
+ m_speechData->setTextJobState(m_currentJobNum, KSpeech::jsSpeaking);
+ m_speechData->setJobSequenceNum(m_currentJobNum, sentence->seq);
+ prePlaySignals(it);
+ it->state = usPlaying;
+ if (!m_timer->start(timerInterval, FALSE))
+ kdDebug() << "Speaker::startPlayingUtterance: timer.start failed" << endl;
+ started = true;
+ } else {
+ // If could not create audio player object, best we can do is silence.
+ it->state = usFinished;
+ }
+ }
+ break;
+ }
+ case usPaused:
+ {
+ // Unpause playback only if user has resumed.
+ // kdDebug() << "Speaker::startPlayingUtterance: checking whether to resume play" << endl;
+ if ((it->utType != utText) ||
+ (m_speechData->getTextJobState(it->sentence->jobNum) != KSpeech::jsPaused))
+ {
+ // kdDebug() << "Speaker::startPlayingUtterance: resuming play" << endl;
+ it->audioPlayer->startPlay(QString::null); // resume
+ it->state = usPlaying;
+ if (!m_timer->start(timerInterval, FALSE))
+ kdDebug() << "Speaker::startPlayingUtterance: timer.start failed" << endl;
+ started = true;
+ }
+ break;
+ }
+
+ case usPreempted:
+ {
+ // Preempted playback automatically resumes.
+ // Note: Must call stop(), even if player not currently playing. Why?
+ it->audioPlayer->startPlay(QString::null); // resume
+ it->state = usPlaying;
+ if (!m_timer->start(timerInterval, FALSE))
+ kdDebug() << "Speaker::startPlayingUtterance: timer.start failed" << endl;
+ started = true;
+ break;
+ }
+ }
+ return started;
+}
+
+/**
+ * Takes care of emitting reading interrupted/resumed and sentence started signals.
+ * Should be called just before audibilizing an utterance.
+ * @param it Iterator pointer to m_uttQueue.
+ * It also makes sure the job state is set to jsSpeaking.
+ */
+void Speaker::prePlaySignals(uttIterator it)
+{
+ uttType utType = it->utType;
+ if (utType == utText)
+ {
+ // If this utterance is for a regular text message,
+ // and it was interrupted, emit reading resumed signal.
+ if (m_textInterrupted)
+ {
+ m_textInterrupted = false;
+ emit readingResumed();
+ }
+ // Set job to speaking state and set sequence number.
+ mlText* sentence = it->sentence;
+ // Emit sentence started signal.
+ emit sentenceStarted(sentence->text,
+ sentence->talker, sentence->appId,
+ m_currentJobNum, sentence->seq);
+ } else {
+ // If this utterance is not a regular text message,
+ // and we are doing a text job, emit reading interrupted signal.
+ if (isSpeakingText())
+ {
+ m_textInterrupted = true;
+ emit readingInterrupted();
+ }
+ }
+}
+
+/**
+ * Takes care of emitting sentenceFinished signal.
+ * Should be called immediately after an utterance has completed playback.
+ * @param it Iterator pointer to m_uttQueue.
+ */
+void Speaker::postPlaySignals(uttIterator it)
+{
+ uttType utType = it->utType;
+ if (utType == utText)
+ {
+ // If this utterance is for a regular text message,
+ // emit sentence finished signal.
+ mlText* sentence = it->sentence;
+ emit sentenceFinished(sentence->appId,
+ sentence->jobNum, sentence->seq);
+ }
+}
+
+/**
+ * Constructs a temporary filename for plugins to use as a suggested filename
+ * for synthesis to write to.
+ * @return Full pathname of suggested file.
+ */
+QString Speaker::makeSuggestedFilename()
+{
+ KTempFile tempFile (locateLocal("tmp", "kttsd-"), ".wav");
+ QString waveFile = tempFile.file()->name();
+ tempFile.close();
+ QFile::remove(waveFile);
+ // kdDebug() << "Speaker::makeSuggestedFilename: Suggesting filename: " << waveFile << endl;
+ return KStandardDirs::realFilePath(waveFile);
+}
+
+/**
+ * Creates and returns a player object based on user option.
+ */
+Player* Speaker::createPlayerObject()
+{
+ Player* player = 0;
+ QString plugInName;
+ switch(m_playerOption)
+ {
+ case 1 :
+ {
+ plugInName = "kttsd_gstplugin";
+ break;
+ }
+ case 2 :
+ {
+ plugInName = "kttsd_alsaplugin";
+ break;
+ }
+ case 3 :
+ {
+ plugInName = "kttsd_akodeplugin";
+ break;
+ }
+ default:
+ {
+ plugInName = "kttsd_artsplugin";
+ break;
+ }
+ }
+ KTrader::OfferList offers = KTrader::self()->query(
+ "KTTSD/AudioPlugin", QString("DesktopEntryName == '%1'").arg(plugInName));
+
+ if(offers.count() == 1)
+ {
+ kdDebug() << "Speaker::createPlayerObject: Loading " << offers[0]->library() << endl;
+ KLibFactory *factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if (factory)
+ player =
+ KParts::ComponentFactory::createInstanceFromLibrary<Player>(
+ offers[0]->library().latin1(), this, offers[0]->library().latin1());
+ }
+ if (player == 0)
+ {
+ // If we tried for GStreamer or ALSA plugin and failed, fall back to aRts plugin.
+ if (m_playerOption != 0)
+ {
+ kdDebug() << "Speaker::createPlayerObject: Could not load " + plugInName +
+ " plugin. Falling back to aRts." << endl;
+ m_playerOption = 0;
+ return createPlayerObject();
+ }
+ else
+ kdDebug() << "Speaker::createPlayerObject: Could not load aRts plugin. Is KDEDIRS set correctly?" << endl;
+ } else
+ // Must have GStreamer >= 0.8.7. If not, use aRts.
+ if (m_playerOption == 1)
+ {
+ if (!player->requireVersion(0, 8, 7))
+ {
+ delete player;
+ m_playerOption = 0;
+ return createPlayerObject();
+ }
+ }
+ if (player) {
+ player->setSinkName(m_sinkName);
+ player->setPeriodSize(m_periodSize);
+ player->setPeriods(m_periodSize);
+ player->setDebugLevel(m_playerDebugLevel);
+ }
+ return player;
+}
+
+
+/* Slots ==========================================================*/
+
+/**
+* Received from PlugIn objects when they finish asynchronous synthesis
+* and audibilizing.
+*/
+void Speaker::slotSayFinished()
+{
+ // Since this signal handler may be running from a plugin's thread,
+ // convert to postEvent and return immediately.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 101);
+ QApplication::postEvent(this, ev);
+}
+
+/**
+* Received from PlugIn objects when they finish asynchronous synthesis.
+*/
+void Speaker::slotSynthFinished()
+{
+ // Since this signal handler may be running from a plugin's thread,
+ // convert to postEvent and return immediately.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 102);
+ QApplication::postEvent(this, ev);
+}
+
+/**
+* Received from PlugIn objects when they asynchronously stopText.
+*/
+void Speaker::slotStopped()
+{
+ // Since this signal handler may be running from a plugin's thread,
+ // convert to postEvent and return immediately.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 103);
+ QApplication::postEvent(this, ev);
+}
+
+/**
+* Received from audio stretcher when stretching (speed adjustment) is finished.
+*/
+void Speaker::slotStretchFinished()
+{
+ // Convert to postEvent and return immediately.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 104);
+ QApplication::postEvent(this, ev);
+}
+
+/**
+* Received from transformer (SSMLConvert) when transforming is finished.
+*/
+void Speaker::slotTransformFinished()
+{
+ // Convert to postEvent and return immediately.
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 105);
+ QApplication::postEvent(this, ev);
+}
+
+/** Received from PlugIn object when they encounter an error.
+* @param keepGoing True if the plugin can continue processing.
+* False if the plugin cannot continue, for example,
+* the speech engine could not be started.
+* @param msg Error message.
+*/
+void Speaker::slotError(bool /*keepGoing*/, const QString& /*msg*/)
+{
+ // Since this signal handler may be running from a plugin's thread,
+ // convert to postEvent and return immediately.
+ // TODO: Do something with error messages.
+ /*
+ if (keepGoing)
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 106);
+ else
+ QCustomEvent* ev = new QCustomEvent(QEvent::User + 107);
+ QApplication::postEvent(this, ev);
+ */
+}
+
+/**
+* Received from Timer when it fires.
+* Check audio player to see if it is finished.
+*/
+void Speaker::slotTimeout()
+{
+ uttIterator itEnd = m_uttQueue.end();
+ for (uttIterator it = m_uttQueue.begin(); it != itEnd; ++it)
+ {
+ if (it->state == usPlaying)
+ {
+ if (it->audioPlayer->playing()) return; // Still playing.
+ m_timer->stop();
+ postPlaySignals(it);
+ deleteUtterance(it);
+ doUtterances();
+ return;
+ }
+ }
+}
+
+/**
+* Processes events posted by plugins. When asynchronous plugins emit signals
+* they are converted into these events.
+*/
+bool Speaker::event ( QEvent * e )
+{
+ // TODO: Do something with event numbers 106 (error; keepGoing=True)
+ // and 107 (error; keepGoing=False).
+ if ((e->type() >= (QEvent::User + 101)) && (e->type() <= (QEvent::User + 105)))
+ {
+ // kdDebug() << "Speaker::event: received event." << endl;
+ doUtterances();
+ return TRUE;
+ }
+ else return FALSE;
+}
+
diff --git a/kttsd/kttsd/speaker.h b/kttsd/kttsd/speaker.h
new file mode 100644
index 0000000..b72e832
--- /dev/null
+++ b/kttsd/kttsd/speaker.h
@@ -0,0 +1,599 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Speaker class.
+
+ This class is in charge of getting the messages, warnings and text from
+ the queue and call the plug ins function to actually speak the texts.
+ -------------------
+ Copyright:
+ (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández
+ ******************************************************************************/
+
+/******************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License. *
+ * *
+ ******************************************************************************/
+
+#ifndef _SPEAKER_H_
+#define _SPEAKER_H_
+
+// Qt includes.
+#include <qobject.h>
+#include <qvaluevector.h>
+#include <qevent.h>
+
+// KTTSD includes.
+#include <speechdata.h>
+#include <pluginproc.h>
+#include <stretcher.h>
+#include <talkercode.h>
+#include <ssmlconvert.h>
+
+class Player;
+class QTimer;
+class TalkerMgr;
+
+/**
+* Type of utterance.
+*/
+enum uttType
+{
+ utText, /**< Text */
+ utInterruptMsg, /**< Interruption text message */
+ utInterruptSnd, /**< Interruption sound file */
+ utResumeMsg, /**< Resume text message */
+ utResumeSnd, /**< Resume sound file */
+ utMessage, /**< Message */
+ utWarning, /**< Warning */
+ utScreenReader, /**< Screen Reader Output */
+ utStartOfJob, /**< Start-of-job */
+ utEndOfJob /**< End-of-job */
+};
+
+/**
+* Processing state of an utterance.
+*/
+enum uttState
+{
+ usNone, /**< Null state. Brand new utterance. */
+ usWaitingTransform, /**< Waiting to be transformed (XSLT) */
+ usTransforming, /**< Transforming the utterance (XSLT). */
+ usWaitingSay, /**< Waiting to start synthesis. */
+ usWaitingSynth, /**< Waiting to be synthesized and audibilized. */
+ usWaitingSignal, /**< Waiting to emit a textStarted or textFinished signal. */
+ usSaying, /**< Plugin is synthesizing and audibilizing. */
+ usSynthing, /**< Plugin is synthesizing only. */
+ usSynthed, /**< Plugin has finished synthesizing. Ready for stretch. */
+ usStretching, /**< Adjusting speed. */
+ usStretched, /**< Speed adjustment finished. Ready for playback. */
+ usPlaying, /**< Playing on Audio Player. */
+ usPaused, /**< Paused on Audio Player due to user action. */
+ usPreempted, /**< Paused on Audio Player due to Screen Reader Output. */
+ usFinished /**< Ready for deletion. */
+};
+
+/**
+* Structure containing an utterance being synthesized or audibilized.
+*/
+struct Utt{
+ mlText* sentence; /* The text, talker, appId, and sequence num. */
+ uttType utType; /* The type of utterance (text, msg, screen reader) */
+ bool isSSML; /* True if the utterance contains SSML markup. */
+ uttState state; /* Processing state of the utterance. */
+ SSMLConvert* transformer; /* XSLT transformer. */
+ PlugInProc* plugin; /* The plugin that synthesizes the utterance. */
+ Stretcher* audioStretcher; /* Audio stretcher object. Adjusts speed. */
+ QString audioUrl; /* Filename containing synthesized audio. Null if
+ plugin has not yet synthesized the utterance, or if
+ plugin does not support synthesis. */
+ Player* audioPlayer; /* The audio player audibilizing the utterance. Null
+ if not currently audibilizing or if plugin doesn't
+ support synthesis. */
+};
+
+/**
+* Iterator for queue of utterances.
+*/
+typedef QValueVector<Utt>::iterator uttIterator;
+
+// Timer interval for checking whether audio playback is finished.
+const int timerInterval = 500;
+
+/**
+ * This class is in charge of getting the messages, warnings and text from
+ * the queue and call the plug ins function to actually speak the texts.
+ */
+class Speaker : public QObject{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ * Calls load plug ins
+ */
+ Speaker(SpeechData* speechData, TalkerMgr* talkerMgr,
+ QObject *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor
+ */
+ ~Speaker();
+
+ /**
+ * Tells the thread to exit
+ */
+ void requestExit();
+
+ /**
+ * Main processing loop. Dequeues utterances and sends them to the
+ * plugins and/or Audio Player.
+ */
+ void doUtterances();
+
+ /**
+ * Determine if kttsd is currently speaking any text jobs.
+ * @return True if currently speaking any text jobs.
+ */
+ bool isSpeakingText();
+
+ /**
+ * Get the job number of the current text job.
+ * @return Job number of the current text job. 0 if no jobs.
+ *
+ * Note that the current job may not be speaking. See @ref isSpeakingText.
+ * @see getTextJobState.
+ * @see isSpeakingText
+ */
+ uint getCurrentTextJob();
+
+ /**
+ * Remove a text job from the queue.
+ * @param jobNum Job number of the text job.
+ *
+ * The job is deleted from the queue and the @ref textRemoved signal is emitted.
+ *
+ * If there is another job in the text queue, and it is marked speakable,
+ * that job begins speaking.
+ */
+ void removeText(const uint jobNum);
+
+ /**
+ * Start a text job at the beginning.
+ * @param jobNum Job number of the text job.
+ *
+ * Rewinds the job to the beginning.
+ *
+ * The job is marked speakable.
+ * If there are other speakable jobs preceeding this one in the queue,
+ * those jobs continue speaking and when finished, this job will begin speaking.
+ * If there are no other speakable jobs preceeding this one, it begins speaking.
+ *
+ * The @ref textStarted signal is emitted when the text job begins speaking.
+ * When all the sentences of the job have been spoken, the job is marked for deletion from
+ * the text queue and the @ref textFinished signal is emitted.
+ */
+ void startText(const uint jobNum);
+
+ /**
+ * Stop a text job and rewind to the beginning.
+ * @param jobNum Job number of the text job.
+ *
+ * The job is marked not speakable and will not be speakable until @ref startText or @ref resumeText
+ * is called.
+ *
+ * If there are speaking jobs preceeding this one in the queue, they continue speaking.
+ * If the job is currently speaking, the @ref textStopped signal is emitted and the job stops speaking.
+ * Depending upon the speech engine and plugin used, speeking may not stop immediately
+ * (it might finish the current sentence).
+ */
+ void stopText(const uint jobNum);
+
+ /**
+ * Pause a text job.
+ * @param jobNum Job number of the text job.
+ *
+ * The job is marked as paused and will not be speakable until @ref resumeText or
+ * @ref startText is called.
+ *
+ * If there are speaking jobs preceeding this one in the queue, they continue speaking.
+ * If the job is currently speaking, the @ref textPaused signal is emitted and the job stops speaking.
+ * Depending upon the speech engine and plugin used, speeking may not stop immediately
+ * (it might finish the current sentence).
+ * @see resumeText
+ */
+ void pauseText(const uint jobNum);
+
+ /**
+ * Start or resume a text job where it was paused.
+ * @param jobNum Job number of the text job.
+ *
+ * The job is marked speakable.
+ *
+ * If the job is currently speaking, or is waiting to be spoken (speakable
+ * state), the resumeText() call is ignored.
+ *
+ * If the job is currently queued, or is finished, it is the same as calling
+ * @ref startText .
+ *
+ * If there are speaking jobs preceeding this one in the queue, those jobs continue speaking and,
+ * when finished this job will begin speaking where it left off.
+ *
+ * The @ref textResumed signal is emitted when the job resumes.
+ * @see pauseText
+ */
+ void resumeText(const uint jobNum);
+
+ /**
+ * Move a text job down in the queue so that it is spoken later.
+ * @param jobNum Job number of the text job.
+ *
+ * If the job is currently speaking, it is paused.
+ * If the next job in the queue is speakable, it begins speaking.
+ */
+ void moveTextLater(const uint jobNum);
+
+ /**
+ * Jump to the first sentence of a specified part of a text job.
+ * @param partNum Part number of the part to jump to. Parts are numbered starting at 1.
+ * @param jobNum Job number of the text job.
+ * @return Part number of the part actually jumped to.
+ *
+ * If partNum is greater than the number of parts in the job, jumps to last part.
+ * If partNum is 0, does nothing and returns the current part number.
+ * If no such job, does nothing and returns 0.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+ int jumpToTextPart(const int partNum, const uint jobNum);
+
+ /**
+ * Advance or rewind N sentences in a text job.
+ * @param n Number of sentences to advance (positive) or rewind (negative)
+ * in the job.
+ * @param jobNum Job number of the text job.
+ * @return Sequence number of the sentence actually moved to.
+ * Sequence numbers are numbered starting at 1.
+ *
+ * If no such job, does nothing and returns 0.
+ * If n is zero, returns the current sequence number of the job.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+ uint moveRelTextSentence(const int n, const uint jobNum);
+
+ signals:
+ /**
+ * Emitted whenever reading a text was started or resumed
+ */
+ void readingStarted();
+
+ /**
+ * Emitted whenever reading a text was finished,
+ * or paused, or stopped before it was finished
+ */
+ void readingStopped();
+
+ /**
+ * Emitted whenever a message or warning interrupts reading a text
+ */
+ void readingInterrupted();
+
+ /**
+ * Emitted whenever reading a text is resumed after it was interrupted
+ * Note: In function resumeText, readingStarted is called instead
+ */
+ void readingResumed();
+
+ /* The following signals correspond to the signals in the KSpeech interface. */
+
+ /**
+ * This signal is emitted when the speech engine/plugin encounters a marker in the text.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param markerName The name of the marker seen.
+ * @see markers
+ */
+ void markerSeen(const QCString& appId, const QString& markerName);
+
+ /**
+ * This signal is emitted whenever a sentence begins speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ */
+ void sentenceStarted(QString text, QString language, const QCString& appId,
+ const uint jobNum, const uint seq);
+
+ /**
+ * This signal is emitted when a sentence has finished speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ */
+ void sentenceFinished(const QCString& appId, const uint jobNum, const uint seq);
+
+ /**
+ * This signal is emitted whenever speaking of a text job begins.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ void textStarted(const QCString& appId, const uint jobNum);
+
+ /**
+ * This signal is emitted whenever a text job is finished. The job has
+ * been marked for deletion from the queue and will be deleted when another
+ * job reaches the Finished state. (Only one job in the text queue may be
+ * in state Finished at one time.) If @ref startText or @ref resumeText is
+ * called before the job is deleted, it will remain in the queue for speaking.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textFinished(const QCString& appId, const uint jobNum);
+
+ /**
+ * This signal is emitted whenever a speaking text job stops speaking.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textStopped(const QCString& appId, const uint jobNum);
+ /**
+ * This signal is emitted whenever a speaking text job is paused.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textPaused(const QCString& appId, const uint jobNum);
+ /**
+ * This signal is emitted when a text job, that was previously paused, resumes speaking.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textResumed(const QCString& appId, const uint jobNum);
+
+ protected:
+ /**
+ * Processes events posted by ThreadedPlugIns.
+ */
+ virtual bool event ( QEvent * e );
+
+ private slots:
+ /**
+ * Received from PlugIn objects when they finish asynchronous synthesis.
+ */
+ void slotSynthFinished();
+ /**
+ * Received from PlugIn objects when they finish asynchronous synthesis
+ * and audibilizing.
+ */
+ void slotSayFinished();
+ /**
+ * Received from PlugIn objects when they asynchronously stopText.
+ */
+ void slotStopped();
+ /**
+ * Received from audio stretcher when stretching (speed adjustment) is finished.
+ */
+ void slotStretchFinished();
+ /**
+ * Received from transformer (SSMLConvert) when transforming is finished.
+ */
+ void slotTransformFinished();
+ /** Received from PlugIn object when they encounter an error.
+ * @param keepGoing True if the plugin can continue processing.
+ * False if the plugin cannot continue, for example,
+ * the speech engine could not be started.
+ * @param msg Error message.
+ */
+ void slotError(bool keepGoing, const QString &msg);
+ /**
+ * Received from Timer when it fires.
+ * Check audio player to see if it is finished.
+ */
+ void slotTimeout();
+
+ private:
+
+ /**
+ * Converts an utterance state enumerator to a displayable string.
+ * @param state Utterance state.
+ * @return Displayable string for utterance state.
+ */
+ QString uttStateToStr(uttState state);
+
+ /**
+ * Converts an utterance type enumerator to a displayable string.
+ * @param utType Utterance type.
+ * @return Displayable string for utterance type.
+ */
+ QString uttTypeToStr(uttType utType);
+
+ /**
+ * Converts a plugin state enumerator to a displayable string.
+ * @param state Plugin state.
+ * @return Displayable string for plugin state.
+ */
+ QString pluginStateToStr(pluginState state);
+
+ /**
+ * Converts a job state enumerator to a displayable string.
+ * @param state Job state.
+ * @return Displayable string for job state.
+ */
+ QString jobStateToStr(int state);
+
+ /**
+ * Determines whether the given text is SSML markup.
+ */
+ bool isSsml(const QString &text);
+
+ /**
+ * Determines the initial state of an utterance. If the utterance contains
+ * SSML, the state is set to usWaitingTransform. Otherwise, if the plugin
+ * supports async synthesis, sets to usWaitingSynth, otherwise usWaitingSay.
+ * If an utterance has already been transformed, usWaitingTransform is
+ * skipped to either usWaitingSynth or usWaitingSay.
+ * @param utt The utterance.
+ */
+ void setInitialUtteranceState(Utt &utt);
+
+ /**
+ * Returns true if the given job and sequence number is already in the utterance queue.
+ */
+ bool isInUtteranceQueue(uint jobNum, uint seqNum);
+
+ /**
+ * Gets the next utterance to be spoken from speechdata and adds it to the queue.
+ * @return True if one or more utterances were added to the queue.
+ *
+ * Checks for waiting ScreenReaderOutput, Warnings, Messages, or Text,
+ * in that order.
+ * If Warning or Message and interruption messages have been configured,
+ * adds those to the queue as well.
+ * Determines which plugin should be used for the utterance.
+ */
+ bool getNextUtterance();
+
+ /**
+ * Given an iterator pointing to the m_uttQueue, deletes the utterance
+ * from the queue. If the utterance is currently being processed by a
+ * plugin or the Audio Player, halts that operation and deletes Audio Player.
+ * Also takes care of deleting temporary audio file.
+ * @param it Iterator pointer to m_uttQueue.
+ * @return Iterator pointing to the next utterance in the
+ * queue, or m_uttQueue.end().
+ */
+ uttIterator deleteUtterance(uttIterator it);
+
+ /**
+ * Given an iterator pointing to the m_uttQueue, starts playing audio if
+ * 1) An audio file is ready to be played, and
+ * 2) It is not already playing.
+ * If another audio player is already playing, pauses it before starting
+ * the new audio player.
+ * @param it Iterator pointer to m_uttQueue.
+ * @return True if an utterance began playing or resumed.
+ */
+ bool startPlayingUtterance(uttIterator it);
+
+ /**
+ * Delete any utterances in the queue with this jobNum.
+ * @param jobNum The Job Number of the utterance(s) to delete.
+ * If currently processing any deleted utterances, stop them.
+ */
+ void deleteUtteranceByJobNum(const uint jobNum);
+
+ /**
+ * Pause the utterance with this jobNum and if it is playing on the Audio Player,
+ * pause the Audio Player.
+ * @param jobNum The Job Number of the utterance to pause.
+ */
+ void pauseUtteranceByJobNum(const uint jobNum);
+
+ /**
+ * Takes care of emitting reading interrupted/resumed and sentence started signals.
+ * Should be called just before audibilizing an utterance.
+ * @param it Iterator pointer to m_uttQueue.
+ */
+ void prePlaySignals(uttIterator it);
+
+ /**
+ * Takes care of emitting sentenceFinished signal.
+ * Should be called immediately after an utterance has completed playback.
+ * @param it Iterator pointer to m_uttQueue.
+ */
+ void postPlaySignals(uttIterator it);
+
+ /**
+ * Constructs a temporary filename for plugins to use as a suggested filename
+ * for synthesis to write to.
+ * @return Full pathname of suggested file.
+ */
+ QString makeSuggestedFilename();
+
+ /**
+ * Creates and returns a player object based on user option.
+ */
+ Player* createPlayerObject();
+
+ /**
+ * SpeechData local pointer
+ */
+ SpeechData* m_speechData;
+
+ /**
+ * TalkerMgr local pointer.
+ */
+ TalkerMgr* m_talkerMgr;
+
+ /**
+ * True if the speaker was requested to exit.
+ */
+ volatile bool m_exitRequested;
+
+ /**
+ * Queue of utterances we are currently processing.
+ */
+ QValueVector<Utt> m_uttQueue;
+
+ /**
+ * True when text job reading has been interrupted.
+ */
+ bool m_textInterrupted;
+
+ /**
+ * Used to prevent doUtterances from prematurely exiting.
+ */
+ bool m_again;
+
+ /**
+ * Which audio player to use.
+ * 0 = aRts
+ * 1 = gstreamer
+ * 2 = ALSA
+ */
+ int m_playerOption;
+
+ /**
+ * Audio stretch factor (Speed).
+ */
+ float m_audioStretchFactor;
+
+ /**
+ * GStreamer sink name to use, or ALSA PCM device name.
+ */
+ QString m_sinkName;
+
+ /**
+ * Timer for monitoring audio player.
+ */
+ QTimer* m_timer;
+
+ /**
+ * Current Text job being processed.
+ */
+ uint m_currentJobNum;
+
+ /**
+ * Job Number, appId, and sequence number of the last text sentence queued.
+ */
+ uint m_lastJobNum;
+ QCString m_lastAppId;
+ uint m_lastSeq;
+
+ /**
+ * Some parameters used by ALSA plugin.
+ * Size of buffer interrupt period (in frames)
+ * Number of periods in buffer.
+ */
+ uint m_periodSize;
+ uint m_periods;
+
+ /**
+ * Debug level in players.
+ */
+ uint m_playerDebugLevel;
+};
+
+#endif // _SPEAKER_H_
diff --git a/kttsd/kttsd/speechdata.cpp b/kttsd/kttsd/speechdata.cpp
new file mode 100644
index 0000000..a1bf26e
--- /dev/null
+++ b/kttsd/kttsd/speechdata.cpp
@@ -0,0 +1,1275 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ This contains the SpeechData class which is in charge of maintaining
+ all the data on the memory.
+ It maintains queues manages the text.
+ We could say that this is the common repository between the KTTSD class
+ (dcop service) and the Speaker class (speaker, loads plug ins, call plug in
+ functions)
+ -------------------
+ Copyright:
+ (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2004-2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández
+ ******************************************************************************/
+
+/******************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License. *
+ * *
+ ******************************************************************************/
+
+// C++ includes.
+#include <stdlib.h>
+
+// Qt includes.
+#include <qregexp.h>
+#include <qpair.h>
+#include <qvaluelist.h>
+#include <qdom.h>
+#include <qfile.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+
+// KTTS includes.
+#include "talkermgr.h"
+#include "notify.h"
+
+// SpeechData includes.
+#include "speechdata.h"
+#include "speechdata.moc"
+
+// Set this to 1 to turn off filter support, including SBD as a plugin.
+#define NO_FILTERS 0
+
+/**
+* Constructor
+* Sets text to be stopped and warnings and messages queues to be autodelete.
+*/
+SpeechData::SpeechData(){
+ // kdDebug() << "Running: SpeechData::SpeechData()" << endl;
+ // The text should be stoped at the beggining (thread safe)
+ jobCounter = 0;
+ config = 0;
+ textJobs.setAutoDelete(true);
+ supportsHTML = false;
+
+ // Warnings queue to be autodelete (thread safe)
+ warnings.setAutoDelete(true);
+
+ // Messages queue to be autodelete (thread safe)
+ messages.setAutoDelete(true);
+
+ screenReaderOutput.jobNum = 0;
+ screenReaderOutput.text = "";
+}
+
+bool SpeechData::readConfig(){
+ // Load configuration
+ delete config;
+ //config = KGlobal::config();
+ config = new KConfig("kttsdrc");
+
+ // Set the group general for the configuration of KTTSD itself (no plug ins)
+ config->setGroup("General");
+
+ // Load the configuration of the text interruption messages and sound
+ textPreMsgEnabled = config->readBoolEntry("TextPreMsgEnabled", false);
+ textPreMsg = config->readEntry("TextPreMsg");
+
+ textPreSndEnabled = config->readBoolEntry("TextPreSndEnabled", false);
+ textPreSnd = config->readEntry("TextPreSnd");
+
+ textPostMsgEnabled = config->readBoolEntry("TextPostMsgEnabled", false);
+ textPostMsg = config->readEntry("TextPostMsg");
+
+ textPostSndEnabled = config->readBoolEntry("TextPostSndEnabled", false);
+ textPostSnd = config->readEntry("TextPostSnd");
+ keepAudio = config->readBoolEntry("KeepAudio", false);
+ keepAudioPath = config->readEntry("KeepAudioPath", locateLocal("data", "kttsd/audio/"));
+
+ // Notification (KNotify).
+ notify = config->readBoolEntry("Notify", false);
+ notifyExcludeEventsWithSound = config->readBoolEntry("ExcludeEventsWithSound", true);
+ loadNotifyEventsFromFile( locateLocal("config", "kttsd_notifyevents.xml"), true );
+
+ // KTTSMgr auto start and auto exit.
+ autoStartManager = config->readBoolEntry("AutoStartManager", false);
+ autoExitManager = config->readBoolEntry("AutoExitManager", false);
+
+ // Clear the pool of filter managers so that filters re-init themselves.
+ QPtrListIterator<PooledFilterMgr> it( m_pooledFilterMgrs );
+ for( ; it.current(); ++it )
+ {
+ PooledFilterMgr* pooledFilterMgr = it.current();
+ delete pooledFilterMgr->filterMgr;
+ delete pooledFilterMgr->talkerCode;
+ delete pooledFilterMgr;
+ }
+ m_pooledFilterMgrs.clear();
+
+ // Create an initial FilterMgr for the pool to save time later.
+ PooledFilterMgr* pooledFilterMgr = new PooledFilterMgr();
+ FilterMgr* filterMgr = new FilterMgr();
+ filterMgr->init(config, "General");
+ supportsHTML = filterMgr->supportsHTML();
+ pooledFilterMgr->filterMgr = filterMgr;
+ pooledFilterMgr->busy = false;
+ pooledFilterMgr->job = 0;
+ pooledFilterMgr->partNum = 0;
+ // Connect signals from FilterMgr.
+ connect (filterMgr, SIGNAL(filteringFinished()), this, SLOT(slotFilterMgrFinished()));
+ connect (filterMgr, SIGNAL(filteringStopped()), this, SLOT(slotFilterMgrStopped()));
+ m_pooledFilterMgrs.append(pooledFilterMgr);
+
+ return true;
+}
+
+/**
+ * Loads notify events from a file. Clearing data if clear is True.
+ */
+void SpeechData::loadNotifyEventsFromFile( const QString& filename, bool clear)
+{
+ // Open existing event list.
+ QFile file( filename );
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ kdDebug() << "SpeechData::loadNotifyEventsFromFile: Unable to open file " << filename << endl;
+ }
+ // QDomDocument doc( "http://www.kde.org/share/apps/kttsd/stringreplacer/wordlist.dtd []" );
+ QDomDocument doc( "" );
+ if ( !doc.setContent( &file ) ) {
+ file.close();
+ kdDebug() << "SpeechData::loadNotifyEventsFromFile: File not in proper XML format. " << filename << endl;
+ }
+ // kdDebug() << "StringReplacerConf::load: document successfully parsed." << endl;
+ file.close();
+
+ if ( clear )
+ {
+ notifyDefaultPresent = NotifyPresent::Passive;
+ notifyDefaultOptions.action = NotifyAction::SpeakMsg;
+ notifyDefaultOptions.talker = QString::null;
+ notifyDefaultOptions.customMsg = QString::null;
+ notifyAppMap.clear();
+ }
+
+ // Event list.
+ QDomNodeList eventList = doc.elementsByTagName("notifyEvent");
+ const int eventListCount = eventList.count();
+ for (int eventIndex = 0; eventIndex < eventListCount; ++eventIndex)
+ {
+ QDomNode eventNode = eventList.item(eventIndex);
+ QDomNodeList propList = eventNode.childNodes();
+ QString eventSrc;
+ QString event;
+ QString actionName;
+ QString message;
+ TalkerCode talkerCode;
+ const int propListCount = propList.count();
+ for (int propIndex = 0; propIndex < propListCount; ++propIndex)
+ {
+ QDomNode propNode = propList.item(propIndex);
+ QDomElement prop = propNode.toElement();
+ if (prop.tagName() == "eventSrc") eventSrc = prop.text();
+ if (prop.tagName() == "event") event = prop.text();
+ if (prop.tagName() == "action") actionName = prop.text();
+ if (prop.tagName() == "message") message = prop.text();
+ if (prop.tagName() == "talker") talkerCode = TalkerCode(prop.text(), false);
+ }
+ NotifyOptions notifyOptions;
+ notifyOptions.action = NotifyAction::action( actionName );
+ notifyOptions.talker = talkerCode.getTalkerCode();
+ notifyOptions.customMsg = message;
+ if ( eventSrc != "default" )
+ {
+ notifyOptions.eventName = NotifyEvent::getEventName( eventSrc, event );
+ NotifyEventMap notifyEventMap = notifyAppMap[ eventSrc ];
+ notifyEventMap[ event ] = notifyOptions;
+ notifyAppMap[ eventSrc ] = notifyEventMap;
+ } else {
+ notifyOptions.eventName = QString::null;
+ notifyDefaultPresent = NotifyPresent::present( event );
+ notifyDefaultOptions = notifyOptions;
+ }
+ }
+}
+
+/**
+* Destructor
+*/
+SpeechData::~SpeechData(){
+ // kdDebug() << "Running: SpeechData::~SpeechData()" << endl;
+ // Walk through jobs and emit a textRemoved signal for each job.
+ for (mlJob* job = textJobs.first(); (job); job = textJobs.next())
+ {
+ emit textRemoved(job->appId, job->jobNum);
+ }
+
+ QPtrListIterator<PooledFilterMgr> it( m_pooledFilterMgrs );
+ for( ; it.current(); ++it )
+ {
+ PooledFilterMgr* pooledFilterMgr = it.current();
+ delete pooledFilterMgr->filterMgr;
+ delete pooledFilterMgr->talkerCode;
+ delete pooledFilterMgr;
+ }
+
+ delete config;
+}
+
+/**
+* Say a message as soon as possible, interrupting any other speech in progress.
+* IMPORTANT: This method is reserved for use by Screen Readers and should not be used
+* by any other applications.
+* @param msg The message to be spoken.
+* @param talker Code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* If no plugin has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+* @param appId The DCOP senderId of the application. NULL if kttsd.
+*
+* If an existing Screen Reader output is in progress, it is stopped and discarded and
+* replaced with this new message.
+*/
+void SpeechData::setScreenReaderOutput(const QString &msg, const QString &talker, const QCString &appId)
+{
+ screenReaderOutput.text = msg;
+ screenReaderOutput.talker = talker;
+ screenReaderOutput.appId = appId;
+ screenReaderOutput.seq = 1;
+}
+
+/**
+* Retrieves the Screen Reader Output.
+*/
+mlText* SpeechData::getScreenReaderOutput()
+{
+ mlText* temp = new mlText();
+ temp->text = screenReaderOutput.text;
+ temp->talker = screenReaderOutput.talker;
+ temp->appId = screenReaderOutput.appId;
+ temp->seq = screenReaderOutput.seq;
+ // Blank the Screen Reader to text to "empty" it.
+ screenReaderOutput.text = "";
+ return temp;
+}
+
+/**
+* Returns true if Screen Reader Output is ready to be spoken.
+*/
+bool SpeechData::screenReaderOutputReady()
+{
+ return !screenReaderOutput.text.isEmpty();
+}
+
+/**
+* Add a new warning to the queue.
+*/
+void SpeechData::enqueueWarning( const QString &warning, const QString &talker, const QCString &appId){
+ // kdDebug() << "Running: SpeechData::enqueueWarning( const QString &warning )" << endl;
+ mlJob* job = new mlJob();
+ ++jobCounter;
+ if (jobCounter == 0) ++jobCounter; // Overflow is OK, but don't want any 0 jobNums.
+ uint jobNum = jobCounter;
+ job->jobNum = jobNum;
+ job->talker = talker;
+ job->appId = appId;
+ job->seq = 1;
+ job->partCount = 1;
+ warnings.enqueue( job );
+ job->sentences = QStringList();
+ // Do not apply Sentence Boundary Detection filters to warnings.
+ startJobFiltering( job, warning, true );
+ // uint count = warnings.count();
+ // kdDebug() << "Adding '" << temp->text << "' with talker '" << temp->talker << "' from application " << appId << " to the warnings queue leaving a total of " << count << " items." << endl;
+}
+
+/**
+* Pop (get and erase) a warning from the queue.
+* @return Pointer to mlText structure containing the message.
+*
+* Caller is responsible for deleting the structure.
+*/
+mlText* SpeechData::dequeueWarning(){
+ // kdDebug() << "Running: SpeechData::dequeueWarning()" << endl;
+ mlJob* job = warnings.dequeue();
+ waitJobFiltering(job);
+ mlText* temp = new mlText();
+ temp->jobNum = job->jobNum;
+ temp->text = job->sentences.join("");
+ temp->talker = job->talker;
+ temp->appId = job->appId;
+ temp->seq = 1;
+ delete job;
+ // uint count = warnings.count();
+ // kdDebug() << "Removing '" << temp->text << "' with talker '" << temp->talker << "' from the warnings queue leaving a total of " << count << " items." << endl;
+ return temp;
+}
+
+/**
+* Are there any Warnings?
+*/
+bool SpeechData::warningInQueue(){
+ // kdDebug() << "Running: SpeechData::warningInQueue() const" << endl;
+ bool temp = !warnings.isEmpty();
+ // if(temp){
+ // kdDebug() << "The warnings queue is NOT empty" << endl;
+ // } else {
+ // kdDebug() << "The warnings queue is empty" << endl;
+ // }
+ return temp;
+}
+
+/**
+* Add a new message to the queue.
+*/
+void SpeechData::enqueueMessage( const QString &message, const QString &talker, const QCString& appId){
+ // kdDebug() << "Running: SpeechData::enqueueMessage" << endl;
+ mlJob* job = new mlJob();
+ ++jobCounter;
+ if (jobCounter == 0) ++jobCounter; // Overflow is OK, but don't want any 0 jobNums.
+ uint jobNum = jobCounter;
+ job->jobNum = jobNum;
+ job->talker = talker;
+ job->appId = appId;
+ job->seq = 1;
+ job->partCount = 1;
+ messages.enqueue( job );
+ job->sentences = QStringList();
+ // Do not apply Sentence Boundary Detection filters to messages.
+ startJobFiltering( job, message, true );
+ // uint count = messages.count();
+ // kdDebug() << "Adding '" << temp->text << "' with talker '" << temp->talker << "' from application " << appId << " to the messages queue leaving a total of " << count << " items." << endl;
+}
+
+/**
+* Pop (get and erase) a message from the queue.
+* @return Pointer to mlText structure containing the message.
+*
+* Caller is responsible for deleting the structure.
+*/
+mlText* SpeechData::dequeueMessage(){
+ // kdDebug() << "Running: SpeechData::dequeueMessage()" << endl;
+ mlJob* job = messages.dequeue();
+ waitJobFiltering(job);
+ mlText* temp = new mlText();
+ temp->jobNum = job->jobNum;
+ temp->text = job->sentences.join("");
+ temp->talker = job->talker;
+ temp->appId = job->appId;
+ temp->seq = 1;
+ delete job;
+ /* mlText *temp = messages.dequeue(); */
+ // uint count = messages.count();
+ // kdDebug() << "Removing '" << temp->text << "' with talker '" << temp->talker << "' from the messages queue leaving a total of " << count << " items." << endl;
+ return temp;
+}
+
+/**
+* Are there any Messages?
+*/
+bool SpeechData::messageInQueue(){
+ // kdDebug() << "Running: SpeechData::messageInQueue() const" << endl;
+ bool temp = !messages.isEmpty();
+ // if(temp){
+ // kdDebug() << "The messages queue is NOT empty" << endl;
+ // } else {
+ // kdDebug() << "The messages queue is empty" << endl;
+ // }
+ return temp;
+}
+
+/**
+* Determines whether the given text is SSML markup.
+*/
+bool SpeechData::isSsml(const QString &text)
+{
+ /// This checks to see if the root tag of the text is a <speak> tag.
+ QDomDocument ssml;
+ ssml.setContent(text, false); // No namespace processing.
+ /// Check to see if this is SSML
+ QDomElement root = ssml.documentElement();
+ return (root.tagName() == "speak");
+}
+
+/**
+* Parses a block of text into sentences using the application-specified regular expression
+* or (if not specified), the default regular expression.
+* @param text The message to be spoken.
+* @param appId The DCOP senderId of the application. NULL if kttsd.
+* @return List of parsed sentences.
+*
+* If the text contains SSML, it is not parsed into sentences at all.
+* TODO: Need a way to preserve SSML but still parse into sentences.
+* We will walk before we run for now and not sentence parse.
+*/
+
+QStringList SpeechData::parseText(const QString &text, const QCString &appId /*=NULL*/)
+{
+ // There has to be a better way
+ // kdDebug() << "I'm getting: " << endl << text << " from application " << appId << endl;
+ if (isSsml(text))
+ {
+ QString tempList(text);
+ return tempList;
+ }
+ // See if app has specified a custom sentence delimiter and use it, otherwise use default.
+ QRegExp sentenceDelimiter;
+ if (sentenceDelimiters.find(appId) != sentenceDelimiters.end())
+ sentenceDelimiter = QRegExp(sentenceDelimiters[appId]);
+ else
+ sentenceDelimiter = QRegExp("([\\.\\?\\!\\:\\;]\\s)|(\\n *\\n)");
+ QString temp = text;
+ // Replace spaces, tabs, and formfeeds with a single space.
+ temp.replace(QRegExp("[ \\t\\f]+"), " ");
+ // Replace sentence delimiters with tab.
+ temp.replace(sentenceDelimiter, "\\1\t");
+ // Replace remaining newlines with spaces.
+ temp.replace("\n"," ");
+ temp.replace("\r"," ");
+ // Remove leading spaces.
+ temp.replace(QRegExp("\\t +"), "\t");
+ // Remove trailing spaces.
+ temp.replace(QRegExp(" +\\t"), "\t");
+ // Remove blank lines.
+ temp.replace(QRegExp("\t\t+"),"\t");
+ // Split into sentences.
+ QStringList tempList = QStringList::split("\t", temp, false);
+
+// for ( QStringList::Iterator it = tempList.begin(); it != tempList.end(); ++it ) {
+// kdDebug() << "'" << *it << "'" << endl;
+// }
+ return tempList;
+}
+
+/**
+* Queues a text job.
+*/
+uint SpeechData::setText( const QString &text, const QString &talker, const QCString &appId)
+{
+ // kdDebug() << "Running: SpeechData::setText" << endl;
+ mlJob* job = new mlJob;
+ ++jobCounter;
+ if (jobCounter == 0) ++jobCounter; // Overflow is OK, but don't want any 0 jobNums.
+ uint jobNum = jobCounter;
+ job->jobNum = jobNum;
+ job->appId = appId;
+ job->talker = talker;
+ job->state = KSpeech::jsQueued;
+ job->seq = 0;
+ job->partCount = 1;
+#if NO_FILTERS
+ QStringList tempList = parseText(text, appId);
+ job->sentences = tempList;
+ job->partSeqNums.append(tempList.count());
+ textJobs.append(job);
+ emit textSet(appId, jobNum);
+#else
+ job->sentences = QStringList();
+ job->partSeqNums = QValueList<int>();
+ textJobs.append(job);
+ startJobFiltering(job, text, false);
+#endif
+ return jobNum;
+}
+
+/**
+* Adds another part to a text job. Does not start speaking the text.
+* (thread safe)
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application,
+* but if no such job, applies to the last job queued by any application.
+* @param text The message to be spoken.
+* @param appId The DCOP senderId of the application. NULL if kttsd.
+* @return Part number for the added part. Parts are numbered starting at 1.
+*
+* The text is parsed into individual sentences. Call getTextCount to retrieve
+* the sentence count. Call startText to mark the job as speakable and if the
+* job is the first speakable job in the queue, speaking will begin.
+* @see setText.
+* @see startText.
+*/
+int SpeechData::appendText(const QString &text, const uint jobNum, const QCString& /*appId*/)
+{
+ // kdDebug() << "Running: SpeechData::appendText" << endl;
+ int newPartNum = 0;
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job)
+ {
+ job->partCount++;
+#if NO_FILTERS
+ QStringList tempList = parseText(text, appId);
+ int sentenceCount = job->sentences.count();
+ job->sentences += tempList;
+ job->partSeqNums.append(sentenceCount + tempList.count());
+ newPartNum = job->partSeqNums.count() + 1;
+ emit textAppended(job->appId, jobNum, newPartNum);
+#else
+ newPartNum = job->partSeqNums.count() + 1;
+ startJobFiltering(job, text, false);
+#endif
+ }
+ return newPartNum;
+}
+
+/**
+* Given an appId, returns the last (most recently queued) job with that appId.
+* @param appId The DCOP senderId of the application. NULL if kttsd.
+* @return Pointer to the text job.
+* If no such job, returns 0.
+* If appId is NULL, returns the last job in the queue.
+* Does not change textJobs.current().
+*/
+mlJob* SpeechData::findLastJobByAppId(const QCString& appId)
+{
+ if (appId == NULL)
+ return textJobs.getLast();
+ else
+ {
+ QPtrListIterator<mlJob> it(textJobs);
+ for (it.toLast() ; it.current(); --it )
+ {
+ if (it.current()->appId == appId)
+ {
+ return it.current();
+ }
+ }
+ return 0;
+ }
+}
+
+/**
+* Given an appId, returns the last (most recently queued) job with that appId,
+* or if no such job, the last (most recent) job in the queue.
+* @param appId The DCOP senderId of the application. NULL if kttsd.
+* @return Pointer to the text job.
+* If no such job, returns 0.
+* If appId is NULL, returns the last job in the queue.
+* Does not change textJobs.current().
+*/
+mlJob* SpeechData::findAJobByAppId(const QCString& appId)
+{
+ mlJob* job = findLastJobByAppId(appId);
+ // if (!job) job = textJobs.getLast();
+ return job;
+}
+
+/**
+* Given an appId, returns the last (most recently queued) Job Number with that appId,
+* or if no such job, the Job Number of the last (most recent) job in the queue.
+* @param appId The DCOP senderId of the application. NULL if kttsd.
+* @return Job Number of the text job.
+* If no such job, returns 0.
+* If appId is NULL, returns the Job Number of the last job in the queue.
+* Does not change textJobs.current().
+*/
+uint SpeechData::findAJobNumByAppId(const QCString& appId)
+{
+ mlJob* job = findAJobByAppId(appId);
+ if (job)
+ return job->jobNum;
+ else
+ return 0;
+}
+
+/**
+* Given a jobNum, returns the first job with that jobNum.
+* @return Pointer to the text job.
+* If no such job, returns 0.
+* Does not change textJobs.current().
+*/
+mlJob* SpeechData::findJobByJobNum(const uint jobNum)
+{
+ QPtrListIterator<mlJob> it(textJobs);
+ for ( ; it.current(); ++it )
+ {
+ if (it.current()->jobNum == jobNum)
+ {
+ return it.current();
+ }
+ }
+ return 0;
+}
+
+/**
+* Given a jobNum, returns the appId of the application that owns the job.
+* @param jobNum Job number of the text job.
+* @return appId of the job.
+* If no such job, returns "".
+* Does not change textJobs.current().
+*/
+QCString SpeechData::getAppIdByJobNum(const uint jobNum)
+{
+ QCString appId;
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job) appId = job->appId;
+ return appId;
+}
+
+/**
+* Sets pointer to the TalkerMgr object.
+*/
+void SpeechData::setTalkerMgr(TalkerMgr* talkerMgr) { m_talkerMgr = talkerMgr; }
+
+/**
+* Remove a text job from the queue.
+* (thread safe)
+* @param jobNum Job number of the text job.
+*
+* The job is deleted from the queue and the textRemoved signal is emitted.
+*/
+void SpeechData::removeText(const uint jobNum)
+{
+ // kdDebug() << "Running: SpeechData::removeText" << endl;
+ uint removeJobNum = 0;
+ QCString removeAppId; // The appId of the removed (and stopped) job.
+ mlJob* removeJob = findJobByJobNum(jobNum);
+ if (removeJob)
+ {
+ removeAppId = removeJob->appId;
+ removeJobNum = removeJob->jobNum;
+ // If filtering on the job, cancel it.
+ QPtrListIterator<PooledFilterMgr> it( m_pooledFilterMgrs );
+ for ( ; it.current(); ++it ) {
+ PooledFilterMgr* pooledFilterMgr = it.current();
+ if (pooledFilterMgr->job && (pooledFilterMgr->job->jobNum == removeJobNum))
+ {
+ pooledFilterMgr->busy = false;
+ pooledFilterMgr->job = 0;
+ pooledFilterMgr->partNum = 0;
+ delete pooledFilterMgr->talkerCode;
+ pooledFilterMgr->talkerCode = 0;
+ pooledFilterMgr->filterMgr->stopFiltering();
+ }
+ }
+ // Delete the job.
+ textJobs.removeRef(removeJob);
+ }
+ if (removeJobNum) emit textRemoved(removeAppId, removeJobNum);
+}
+
+/**
+* Given a job and a sequence number, returns the part that sentence is in.
+* If no such job or sequence number, returns 0.
+* @param job The text job.
+* @param seq Sequence number of the sentence. Sequence numbers begin with 1.
+* @return Part number of the part the sentence is in. Parts are numbered
+* beginning with 1. If no such job or sentence, returns 0.
+*
+*/
+int SpeechData::getJobPartNumFromSeq(const mlJob& job, const int seq)
+{
+ int foundPartNum = 0;
+ int desiredSeq = seq;
+ uint partNum = 0;
+ // Wait until all filtering has stopped for the job.
+ waitJobFiltering(&job);
+ while (partNum < job.partSeqNums.count())
+ {
+ if (desiredSeq <= job.partSeqNums[partNum])
+ {
+ foundPartNum = partNum + 1;
+ break;
+ }
+ desiredSeq = desiredSeq - job.partSeqNums[partNum];
+ ++partNum;
+ }
+ return foundPartNum;
+}
+
+
+/**
+* Delete expired jobs. At most, one finished job is kept on the queue.
+* @param finishedJobNum Job number of a job that just finished.
+* The just finished job is not deleted, but any other finished jobs are.
+* Does not change the textJobs.current() pointer.
+*/
+void SpeechData::deleteExpiredJobs(const uint finishedJobNum)
+{
+ // Save current pointer.
+ typedef QPair<QCString, uint> removedJob;
+ typedef QValueList<removedJob> removedJobsList;
+ removedJobsList removedJobs;
+ // Walk through jobs and delete any other finished jobs.
+ for (mlJob* job = textJobs.first(); (job); job = textJobs.next())
+ {
+ if (job->jobNum != finishedJobNum && job->state == KSpeech::jsFinished)
+ {
+ removedJobs.append(removedJob(job->appId, job->jobNum));
+ textJobs.removeRef(job);
+ }
+ }
+ // Emit signals for removed jobs.
+ removedJobsList::const_iterator it;
+ removedJobsList::const_iterator endRemovedJobsList(removedJobs.constEnd());
+ for (it = removedJobs.constBegin(); it != endRemovedJobsList ; ++it)
+ {
+ QCString appId = (*it).first;
+ uint jobNum = (*it).second;
+ textRemoved(appId, jobNum);
+ }
+}
+
+/**
+* Given a Job Number, returns the next speakable text job on the queue.
+* @param prevJobNum Current job number (which should not be returned).
+* @return Pointer to mlJob structure of the first speakable job
+* not equal prevJobNum. If no such job, returns null.
+*
+* Caller must not delete the job.
+*/
+mlJob* SpeechData::getNextSpeakableJob(const uint prevJobNum)
+{
+ for (mlJob* job = textJobs.first(); (job); job = textJobs.next())
+ if (job->jobNum != prevJobNum)
+ if (job->state == KSpeech::jsSpeakable)
+ {
+ waitJobFiltering(job);
+ return job;
+ }
+ return 0;
+}
+
+/**
+* Given previous job number and sequence number, returns the next sentence from the
+* text queue. If no such sentence is available, either because we've run out of
+* jobs, or because all jobs are paused, returns null.
+* @param prevJobNum Previous Job Number.
+* @param prevSeq Previous sequency number.
+* @return Pointer to n mlText structure containing the next sentence. If no
+* sentence, returns null.
+*
+* Caller is responsible for deleting the returned mlText structure (if not null).
+*/
+mlText* SpeechData::getNextSentenceText(const uint prevJobNum, const uint prevSeq)
+{
+ // kdDebug() << "SpeechData::getNextSentenceText running with prevJobNum " << prevJobNum << " prevSeq " << prevSeq << endl;
+ mlText* temp = 0;
+ uint jobNum = prevJobNum;
+ mlJob* job = 0;
+ uint seq = prevSeq;
+ ++seq;
+ if (!jobNum)
+ {
+ job = getNextSpeakableJob(jobNum);
+ if (job) seq =+ job->seq;
+ } else
+ job = findJobByJobNum(prevJobNum);
+ if (!job)
+ {
+ job = getNextSpeakableJob(jobNum);
+ if (job) seq =+ job->seq;
+ }
+ else
+ {
+ if ((job->state != KSpeech::jsSpeakable) && (job->state != KSpeech::jsSpeaking))
+ {
+ job = getNextSpeakableJob(job->jobNum);
+ if (job) seq =+ job->seq;
+ }
+ }
+ if (job)
+ {
+ // If we run out of sentences in the job, move on to next job.
+ jobNum = job->jobNum;
+ if (seq > job->sentences.count())
+ {
+ job = getNextSpeakableJob(jobNum);
+ if (job) seq =+ job->seq;
+ }
+ }
+ if (job)
+ {
+ if (seq == 0) seq = 1;
+ temp = new mlText;
+ temp->text = job->sentences[seq - 1];
+ temp->appId = job->appId;
+ temp->talker = job->talker;
+ temp->jobNum = job->jobNum;
+ temp->seq = seq;
+ // kdDebug() << "SpeechData::getNextSentenceText: return job number " << temp->jobNum << " seq " << temp->seq << " sentence count = " << job->sentences.count() << endl;
+ } // else kdDebug() << "SpeechData::getNextSentenceText: no more sentences in queue" << endl;
+ return temp;
+}
+
+/**
+* Given a Job Number, sets the current sequence number of the job.
+* @param jobNum Job Number.
+* @param seq Sequence number.
+* If for some reason, the job does not exist, nothing happens.
+*/
+void SpeechData::setJobSequenceNum(const uint jobNum, const uint seq)
+{
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job) job->seq = seq;
+}
+
+/**
+* Given a Job Number, returns the current sequence number of the job.
+* @param jobNum Job Number.
+* @return Sequence number of the job. If no such job, returns 0.
+*/
+uint SpeechData::getJobSequenceNum(const uint jobNum)
+{
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job)
+ return job->seq;
+ else
+ return 0;
+}
+
+/**
+* Sets the GREP pattern that will be used as the sentence delimiter.
+* @param delimiter A valid GREP pattern.
+* @param appId The DCOP senderId of the application. NULL if kttsd.
+*
+* The default delimiter is
+ @verbatim
+ ([\\.\\?\\!\\:\\;])\\s
+ @endverbatim
+*
+* Note that backward slashes must be escaped.
+*
+* Changing the sentence delimiter does not affect other applications.
+* @see sentenceparsing
+*/
+void SpeechData::setSentenceDelimiter(const QString &delimiter, const QCString appId)
+{
+ sentenceDelimiters[appId] = delimiter;
+}
+
+/**
+* Get the number of sentences in a text job.
+* (thread safe)
+* @param jobNum Job number of the text job.
+* @return The number of sentences in the job. -1 if no such job.
+*
+* The sentences of a job are given sequence numbers from 1 to the number returned by this
+* method. The sequence numbers are emitted in the sentenceStarted and sentenceFinished signals.
+*/
+int SpeechData::getTextCount(const uint jobNum)
+{
+ mlJob* job = findJobByJobNum(jobNum);
+ int temp;
+ if (job)
+ {
+ waitJobFiltering(job);
+ temp = job->sentences.count();
+ } else
+ temp = -1;
+ return temp;
+}
+
+/**
+* Get the number of jobs in the text job queue.
+* (thread safe)
+* @return Number of text jobs in the queue. 0 if none.
+*/
+uint SpeechData::getTextJobCount()
+{
+ return textJobs.count();
+}
+
+/**
+* Get a comma-separated list of text job numbers in the queue.
+* @return Comma-separated list of text job numbers in the queue.
+*/
+QString SpeechData::getTextJobNumbers()
+{
+ QString jobs;
+ QPtrListIterator<mlJob> it(textJobs);
+ for ( ; it.current(); ++it )
+ {
+ if (!jobs.isEmpty()) jobs.append(",");
+ jobs.append(QString::number(it.current()->jobNum));
+ }
+ return jobs;
+}
+
+/**
+* Get the state of a text job.
+* (thread safe)
+* @param jobNum Job number of the text job.
+* @return State of the job. -1 if invalid job number.
+*/
+int SpeechData::getTextJobState(const uint jobNum)
+{
+ mlJob* job = findJobByJobNum(jobNum);
+ int temp;
+ if (job)
+ temp = job->state;
+ else
+ temp = -1;
+ return temp;
+}
+
+/**
+* Set the state of a text job.
+* @param jobNum Job Number of the job.
+* @param state New state for the job.
+*
+* If the new state is Finished, deletes other expired jobs.
+*
+**/
+void SpeechData::setTextJobState(const uint jobNum, const KSpeech::kttsdJobState state)
+{
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job)
+ {
+ job->state = state;
+ if (state == KSpeech::jsFinished) deleteExpiredJobs(jobNum);
+ }
+}
+
+/**
+* Get information about a text job.
+* @param jobNum Job number of the text job.
+* @return A QDataStream containing information about the job.
+* Blank if no such job.
+*
+* The stream contains the following elements:
+* - int state Job state.
+* - QCString appId DCOP senderId of the application that requested the speech job.
+* - QString talker Language code in which to speak the text.
+* - int seq Current sentence being spoken. Sentences are numbered starting at 1.
+* - int sentenceCount Total number of sentences in the job.
+* - int partNum Current part of the job begin spoken. Parts are numbered starting at 1.
+* - int partCount Total number of parts in the job.
+*
+* Note that sequence numbers apply to the entire job.
+* They do not start from 1 at the beginning of each part.
+*
+* The following sample code will decode the stream:
+ @verbatim
+ QByteArray jobInfo = getTextJobInfo(jobNum);
+ QDataStream stream(jobInfo, IO_ReadOnly);
+ int state;
+ QCString appId;
+ QString talker;
+ int seq;
+ int sentenceCount;
+ int partNum;
+ int partCount;
+ stream >> state;
+ stream >> appId;
+ stream >> talker;
+ stream >> seq;
+ stream >> sentenceCount;
+ stream >> partNum;
+ stream >> partCount;
+ @endverbatim
+*/
+QByteArray SpeechData::getTextJobInfo(const uint jobNum)
+{
+ mlJob* job = findJobByJobNum(jobNum);
+ QByteArray temp;
+ if (job)
+ {
+ waitJobFiltering(job);
+ QDataStream stream(temp, IO_WriteOnly);
+ stream << job->state;
+ stream << job->appId;
+ stream << job->talker;
+ stream << job->seq;
+ stream << job->sentences.count();
+ stream << getJobPartNumFromSeq(*job, job->seq);
+ stream << job->partSeqNums.count();
+ }
+ return temp;
+}
+
+/**
+* Return a sentence of a job.
+* @param jobNum Job number of the text job.
+* @param seq Sequence number of the sentence.
+* @return The specified sentence in the specified job. If no such
+* job or sentence, returns "".
+*/
+QString SpeechData::getTextJobSentence(const uint jobNum, const uint seq /*=1*/)
+{
+ mlJob* job = findJobByJobNum(jobNum);
+ QString temp;
+ if (job)
+ {
+ waitJobFiltering(job);
+ temp = job->sentences[seq - 1];
+ }
+ return temp;
+}
+
+/**
+* Change the talker for a text job.
+* @param jobNum Job number of the text job.
+* If zero, applies to the last job queued by the application,
+* but if no such job, applies to the last job queued by any application.
+* @param talker New code for the talker to do the speaking. Example "en".
+* If NULL, defaults to the user's default talker.
+* If no plugin has been configured for the specified Talker code,
+* defaults to the closest matching talker.
+*/
+void SpeechData::changeTextTalker(const QString &talker, uint jobNum)
+{
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job) job->talker = talker;
+}
+
+/**
+* Move a text job down in the queue so that it is spoken later.
+* @param jobNum Job number of the text job.
+*/
+void SpeechData::moveTextLater(const uint jobNum)
+{
+ // kdDebug() << "Running: SpeechData::moveTextLater" << endl;
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job)
+ {
+ // Get index of the job.
+ uint index = textJobs.findRef(job);
+ // Move job down one position in the queue.
+ // kdDebug() << "In SpeechData::moveTextLater, moving jobNum " << movedJobNum << endl;
+ if (textJobs.insert(index + 2, job)) textJobs.take(index);
+ }
+}
+
+/**
+* Jump to the first sentence of a specified part of a text job.
+* @param partNum Part number of the part to jump to. Parts are numbered starting at 1.
+* @param jobNum Job number of the text job.
+* @return Part number of the part actually jumped to.
+*
+* If partNum is greater than the number of parts in the job, jumps to last part.
+* If partNum is 0, does nothing and returns the current part number.
+* If no such job, does nothing and returns 0.
+* Does not affect the current speaking/not-speaking state of the job.
+*/
+int SpeechData::jumpToTextPart(const int partNum, const uint jobNum)
+{
+ // kdDebug() << "Running: SpeechData::jumpToTextPart" << endl;
+ int newPartNum = 0;
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job)
+ {
+ waitJobFiltering(job);
+ if (partNum > 0)
+ {
+ newPartNum = partNum;
+ int partCount = job->partSeqNums.count();
+ if (newPartNum > partCount) newPartNum = partCount;
+ if (newPartNum > 1)
+ job->seq = job->partSeqNums[newPartNum - 1];
+ else
+ job->seq = 0;
+ }
+ else
+ newPartNum = getJobPartNumFromSeq(*job, job->seq);
+ }
+ return newPartNum;
+}
+
+/**
+* Advance or rewind N sentences in a text job.
+* @param n Number of sentences to advance (positive) or rewind (negative)
+* in the job.
+* @param jobNum Job number of the text job.
+* @return Sequence number of the sentence actually moved to. Sequence numbers
+* are numbered starting at 1.
+*
+* If no such job, does nothing and returns 0.
+* If n is zero, returns the current sequence number of the job.
+* Does not affect the current speaking/not-speaking state of the job.
+*/
+uint SpeechData::moveRelTextSentence(const int n, const uint jobNum /*=0*/)
+{
+ // kdDebug() << "Running: SpeechData::moveRelTextSentence" << endl;
+ int newSeqNum = 0;
+ mlJob* job = findJobByJobNum(jobNum);
+ if (job)
+ {
+ waitJobFiltering(job);
+ int oldSeqNum = job->seq;
+ newSeqNum = oldSeqNum + n;
+ if (n != 0)
+ {
+ if (newSeqNum < 0) newSeqNum = 0;
+ int sentenceCount = job->sentences.count();
+ if (newSeqNum > sentenceCount) newSeqNum = sentenceCount;
+ job->seq = newSeqNum;
+ }
+ }
+ return newSeqNum;
+}
+
+/**
+* Assigns a FilterMgr to a job and starts filtering on it.
+*/
+void SpeechData::startJobFiltering(mlJob* job, const QString& text, bool noSBD)
+{
+ uint jobNum = job->jobNum;
+ int partNum = job->partCount;
+ // kdDebug() << "SpeechData::startJobFiltering: jobNum = " << jobNum << " partNum = " << partNum << " text.left(500) = " << text.left(500) << endl;
+ // Find an idle FilterMgr, if any.
+ // If filtering is already in progress for this job and part, do nothing.
+ PooledFilterMgr* pooledFilterMgr = 0;
+ QPtrListIterator<PooledFilterMgr> it( m_pooledFilterMgrs );
+ for( ; it.current(); ++it )
+ {
+ if (it.current()->busy) {
+ if ((it.current()->job->jobNum == jobNum) && (it.current()->partNum == partNum)) return;
+ } else {
+ if (!it.current()->job && !pooledFilterMgr) pooledFilterMgr = it.current();
+ }
+ }
+ // Create a new FilterMgr if needed and add to pool.
+ if (!pooledFilterMgr)
+ {
+ // kdDebug() << "SpeechData::startJobFiltering: adding new pooledFilterMgr for job " << jobNum << " part " << partNum << endl;
+ pooledFilterMgr = new PooledFilterMgr();
+ FilterMgr* filterMgr = new FilterMgr();
+ filterMgr->init(config, "General");
+ pooledFilterMgr->filterMgr = filterMgr;
+ // Connect signals from FilterMgr.
+ connect (filterMgr, SIGNAL(filteringFinished()), this, SLOT(slotFilterMgrFinished()));
+ connect (filterMgr, SIGNAL(filteringStopped()), this, SLOT(slotFilterMgrStopped()));
+ m_pooledFilterMgrs.append(pooledFilterMgr);
+ }
+ // else kdDebug() << "SpeechData::startJobFiltering: re-using idle pooledFilterMgr for job " << jobNum << " part " << partNum << endl;
+ // Flag the FilterMgr as busy and set it going.
+ pooledFilterMgr->busy = true;
+ pooledFilterMgr->job = job;
+ pooledFilterMgr->partNum = partNum;
+ pooledFilterMgr->filterMgr->setNoSBD( noSBD );
+ // Get TalkerCode structure of closest matching Talker.
+ pooledFilterMgr->talkerCode = m_talkerMgr->talkerToTalkerCode(job->talker);
+ // Pass Sentence Boundary regular expression (if app overrode default);
+ if (sentenceDelimiters.find(job->appId) != sentenceDelimiters.end())
+ pooledFilterMgr->filterMgr->setSbRegExp(sentenceDelimiters[job->appId]);
+ pooledFilterMgr->filterMgr->asyncConvert(text, pooledFilterMgr->talkerCode, job->appId);
+}
+
+/**
+* Waits for filtering to be completed on a job.
+* This is typically called because an app has requested job info that requires
+* filtering to be completed, such as getJobInfo.
+*/
+void SpeechData::waitJobFiltering(const mlJob* job)
+{
+#if NO_FILTERS
+ return;
+#endif
+ uint jobNum = job->jobNum;
+ bool waited = false;
+ QPtrListIterator<PooledFilterMgr> it(m_pooledFilterMgrs);
+ for ( ; it.current(); ++it )
+ {
+ PooledFilterMgr* pooledFilterMgr = it.current();
+ if (pooledFilterMgr->busy)
+ {
+ if (pooledFilterMgr->job->jobNum == jobNum)
+ {
+ if (!pooledFilterMgr->filterMgr->noSBD())
+ kdDebug() << "SpeechData::waitJobFiltering: Waiting for filter to finish. Not optimium. " <<
+ "Try waiting for textSet signal before querying for job information." << endl;
+ pooledFilterMgr->filterMgr->waitForFinished();
+ // kdDebug() << "SpeechData::waitJobFiltering: waiting for job " << jobNum << endl;
+ waited = true;
+ }
+ }
+ }
+ if (waited)
+ doFiltering();
+}
+
+/**
+* Processes filters by looping across the pool of FilterMgrs.
+* As each FilterMgr finishes, emits appropriate signals and flags it as no longer busy.
+*/
+void SpeechData::doFiltering()
+{
+ // kdDebug() << "SpeechData::doFiltering: Running. " << m_pooledFilterMgrs.count() << " filters in pool." << endl;
+ bool again = true;
+ while (again)
+ {
+ again = false;
+ QPtrListIterator<PooledFilterMgr> it( m_pooledFilterMgrs );
+ for( ; it.current(); ++it )
+ {
+ PooledFilterMgr* pooledFilterMgr = it.current();
+ // If FilterMgr is busy, see if it is now finished.
+ if (pooledFilterMgr->busy)
+ {
+ FilterMgr* filterMgr = pooledFilterMgr->filterMgr;
+ if (filterMgr->getState() == FilterMgr::fsFinished)
+ {
+ mlJob* job = pooledFilterMgr->job;
+ // kdDebug() << "SpeechData::doFiltering: filter finished, jobNum = " << job->jobNum << " partNum = " << pooledFilterMgr->partNum << endl;
+ // We have to retrieve parts in order, but parts may not be completed in order.
+ // See if this is the next part we need.
+ if ((int)job->partSeqNums.count() == (pooledFilterMgr->partNum - 1))
+ {
+ pooledFilterMgr->busy = false;
+ // Retrieve text from FilterMgr.
+ QString text = filterMgr->getOutput();
+ // kdDebug() << "SpeechData::doFiltering: text.left(500) = " << text.left(500) << endl;
+ filterMgr->ackFinished();
+ // Convert the TalkerCode back into string.
+ job->talker = pooledFilterMgr->talkerCode->getTalkerCode();
+ // TalkerCode object no longer needed.
+ delete pooledFilterMgr->talkerCode;
+ pooledFilterMgr->talkerCode = 0;
+ if (filterMgr->noSBD())
+ job->sentences = text;
+ else
+ {
+ // Split the text into sentences and store in the job.
+ // The SBD plugin does all the real sentence parsing, inserting tabs at each
+ // sentence boundary.
+ QStringList sentences = QStringList::split("\t", text, false);
+ int sentenceCount = job->sentences.count();
+ job->sentences += sentences;
+ job->partSeqNums.append(sentenceCount + sentences.count());
+ }
+ int partNum = job->partSeqNums.count();
+ // Clean up.
+ pooledFilterMgr->job = 0;
+ pooledFilterMgr->partNum = 0;
+ // Emit signal.
+ if (!filterMgr->noSBD())
+ {
+ if (partNum == 1)
+ emit textSet(job->appId, job->jobNum);
+ else
+ emit textAppended(job->appId, job->jobNum, partNum);
+ }
+ } else {
+ // A part is ready, but need to first process a finished preceeding part
+ // that follows this one in the pool of filter managers.
+ again = true;
+ // kdDebug() << "SpeechData::doFiltering: filter is finished, but must wait for earlier part to finish filter, job = " << pooledFilterMgr->job->jobNum << endl;
+ }
+ }
+ // else kdDebug() << "SpeechData::doFiltering: filter for job " << pooledFilterMgr->job->jobNum << " is busy." << endl;
+ }
+ // else kdDebug() << "SpeechData::doFiltering: filter is idle" << endl;
+ }
+ }
+}
+
+void SpeechData::slotFilterMgrFinished()
+{
+ // kdDebug() << "SpeechData::slotFilterMgrFinished: received signal FilterMgr finished signal." << endl;
+ doFiltering();
+}
+
+void SpeechData::slotFilterMgrStopped()
+{
+ doFiltering();
+}
+
diff --git a/kttsd/kttsd/speechdata.h b/kttsd/kttsd/speechdata.h
new file mode 100644
index 0000000..40294bf
--- /dev/null
+++ b/kttsd/kttsd/speechdata.h
@@ -0,0 +1,731 @@
+/*************************************************** vim:set ts=4 sw=4 sts=4:
+ This contains the SpeechData class which is in charge of maintaining
+ all the data on the memory.
+ It maintains queues manages the text.
+ We could say that this is the common repository between the KTTSD class
+ (dcop service) and the Speaker class (speaker, loads plug ins, call plug in
+ functions)
+ -------------------
+ Copyright:
+ (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ (C) 2003-2004 by Olaf Schmidt <ojschmidt@kde.org>
+ (C) 2004-2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández
+ ******************************************************************************/
+
+/******************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License. *
+ * *
+ ******************************************************************************/
+
+#ifndef _SPEECHDATA_H_
+#define _SPEECHDATA_H_
+
+// Qt includes.
+#include <qptrqueue.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+// KDE includes.
+#include <kconfig.h>
+
+// KTTS includes.
+#include <kspeech.h>
+#include <talkercode.h>
+#include <filtermgr.h>
+
+class TalkerMgr;
+
+/**
+* Struct containing a text cell, for messages, warnings, and texts.
+* Contains the text itself, the associated talker,
+* the ID of the application that requested it be spoken, and a sequence number.
+*/
+struct mlText{
+ QString talker; /* Requested Talker code for the sentence. */
+ QString text; /* Text of sentence. */
+ QCString appId; /* DCOP senderId of the application that requested the speech. */
+ uint jobNum; /* Text jobNum. Only applies to text messages; not warning and messages. */
+ uint seq; /* Sequence number. */
+};
+
+/**
+ * Struct containing a text job.
+ */
+struct mlJob {
+ uint jobNum; /* Job number. */
+ KSpeech::kttsdJobState state; /* Job state. */
+ QCString appId; /* DCOP senderId of the application that requested the speech job. */
+ QString talker; /* Requested Talker code in which to speak the text. */
+ int seq; /* Current sentence being spoken. */
+ QValueList<int> partSeqNums; /* List containing last sequence number for each part of a job. */
+ QStringList sentences; /* List of sentences in the job. */
+ int partCount; /* Number of parts in the job. */
+};
+
+/**
+ * Struct used to keep a pool of FilterMgr objects.
+ */
+struct PooledFilterMgr {
+ FilterMgr* filterMgr; /* The FilterMgr object. */
+ bool busy; /* True if the FilterMgr is busy. */
+ mlJob* job; /* The job the FilterMgr is filtering. */
+ int partNum; /* The part number of the job that is filtering. */
+ TalkerCode* talkerCode; /* TalkerCode object passed to FilterMgr. */
+};
+
+/**
+ * Struct used to keep notification options.
+ */
+struct NotifyOptions {
+ QString eventName;
+ int action;
+ QString talker;
+ QString customMsg;
+};
+
+/**
+ * A list of notification options for a single app, indexed by event.
+ */
+typedef QMap<QString, NotifyOptions> NotifyEventMap;
+
+/**
+ * A list of notification event maps for all apps, indexed by app.
+ */
+typedef QMap<QString, NotifyEventMap> NotifyAppMap;
+
+/**
+ * SpeechData class which is in charge of maintaining all the data on the memory.
+ * It maintains queues and has methods to enque
+ * messages and warnings and manage the text queues.
+ * We could say that this is the common repository between the KTTSD class
+ * (dcop service) and the Speaker class (speaker, loads plug ins, call plug in
+ * functions)
+ */
+class SpeechData : public QObject {
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ * Sets text to be stopped and warnings and messages queues to be autodelete (thread safe)
+ */
+ SpeechData();
+
+ /**
+ * Destructor
+ */
+ ~SpeechData();
+
+ /**
+ * Read the configuration
+ */
+ bool readConfig();
+
+ /**
+ * Say a message as soon as possible, interrupting any other speech in progress.
+ * IMPORTANT: This method is reserved for use by Screen Readers and should not be used
+ * by any other applications.
+ * @param msg The message to be spoken.
+ * @param talker Code for the talker to speak the message. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ * @param appId The DCOP senderId of the application.
+ *
+ * If an existing Screen Reader output is in progress, it is stopped and discarded and
+ * replaced with this new message.
+ */
+ void setScreenReaderOutput(const QString &msg, const QString &talker,
+ const QCString& appId);
+
+ /**
+ * Given an appId, returns the last (most recently queued) Job Number with that appId,
+ * or if no such job, the Job Number of the last (most recent) job in the queue.
+ * @param appId The DCOP senderId of the application.
+ * @return Job Number of the text job.
+ * If no such job, returns 0.
+ * If appId is NULL, returns the Job Number of the last job in the queue.
+ * Does not change textJobs.current().
+ */
+ uint findAJobNumByAppId(const QCString& appId);
+
+ /**
+ * Retrieves the Screen Reader Output.
+ */
+ mlText* getScreenReaderOutput();
+
+ /**
+ * Returns true if Screen Reader Output is ready to be spoken.
+ */
+ bool screenReaderOutputReady();
+
+ /**
+ * Add a new warning to the queue.
+ */
+ void enqueueWarning( const QString &, const QString &talker,
+ const QCString& appId);
+
+ /**
+ * Pop (get and erase) a warning from the queue.
+ * @return Pointer to mlText structure containing the warning.
+ *
+ * Caller is responsible for deleting the structure.
+ */
+ mlText* dequeueWarning();
+
+ /**
+ * Are there any Warnings?
+ */
+ bool warningInQueue();
+
+ /**
+ * Add a new message to the queue.
+ */
+ void enqueueMessage( const QString &, const QString &talker,
+ const QCString&);
+
+ /**
+ * Pop (get and erase) a message from the queue.
+ * @return Pointer to mlText structure containing the message.
+ *
+ * Caller is responsible for deleting the structure.
+ */
+ mlText* dequeueMessage();
+
+ /**
+ * Are there any Messages?
+ */
+ bool messageInQueue();
+
+ /**
+ * Sets the GREP pattern that will be used as the sentence delimiter.
+ * @param delimiter A valid GREP pattern.
+ * @param appId The DCOP senderId of the application.
+ *
+ * The default delimiter is
+ @verbatim
+ ([\\.\\?\\!\\:\\;])\\s
+ @endverbatim
+ *
+ * Note that backward slashes must be escaped.
+ *
+ * Changing the sentence delimiter does not affect other applications.
+ * @see sentenceparsing
+ */
+ void setSentenceDelimiter(const QString &delimiter, const QCString appId);
+
+ /* The following methods correspond to the methods in KSpeech interface. */
+
+ /**
+ * Queue a text job. Does not start speaking the text.
+ * (thread safe)
+ * @param text The message to be spoken.
+ * @param talker Code for the talker to speak the text. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ * @param appId The DCOP senderId of the application.
+ * @return Job number.
+ *
+ * The text is parsed into individual sentences. Call getTextCount to retrieve
+ * the sentence count. Call startText to mark the job as speakable and if the
+ * job is the first speakable job in the queue, speaking will begin.
+ * @see startText.
+ */
+ uint setText(const QString &text, const QString &talker, const QCString& appId);
+
+ /**
+ * Adds another part to a text job. Does not start speaking the text.
+ * (thread safe)
+ * @param jobNum Job number of the text job.
+ * @param text The message to be spoken.
+ * @param appId The DCOP senderId of the application.
+ * @return Part number for the added part. Parts are numbered starting at 1.
+ *
+ * The text is parsed into individual sentences. Call getTextCount to retrieve
+ * the sentence count. Call startText to mark the job as speakable and if the
+ * job is the first speakable job in the queue, speaking will begin.
+ * @see setText.
+ * @see startText.
+ */
+ int appendText(const QString &text, const uint jobNum, const QCString& appId);
+
+ /**
+ * Get the number of sentences in a text job.
+ * (thread safe)
+ * @param jobNum Job number of the text job.
+ * @return The number of sentences in the job. -1 if no such job.
+ *
+ * The sentences of a job are given sequence numbers from 1 to the number returned by this
+ * method. The sequence numbers are emitted in the sentenceStarted and sentenceFinished signals.
+ */
+ int getTextCount(const uint jobNum);
+
+ /**
+ * Get the number of jobs in the text job queue.
+ * (thread safe)
+ * @return Number of text jobs in the queue. 0 if none.
+ */
+ uint getTextJobCount();
+
+ /**
+ * Get a comma-separated list of text job numbers in the queue.
+ * @return Comma-separated list of text job numbers in the queue.
+ */
+ QString getTextJobNumbers();
+
+ /**
+ * Get the state of a text job.
+ * (thread safe)
+ * @param jobNum Job number of the text job.
+ * @return State of the job. -1 if invalid job number.
+ */
+ int getTextJobState(const uint jobNum);
+
+ /**
+ * Set the state of a text job.
+ * @param jobNum Job Number of the job.
+ * @param state New state for the job.
+ *
+ **/
+ void setTextJobState(const uint jobNum, const KSpeech::kttsdJobState state);
+
+ /**
+ * Get information about a text job.
+ * @param jobNum Job number of the text job.
+ * @return A QDataStream containing information about the job.
+ * Blank if no such job.
+ *
+ * The stream contains the following elements:
+ * - int state Job state.
+ * - QCString appId DCOP senderId of the application that requested the speech job.
+ * - QString talker Talker code as requested by application.
+ * - int seq Current sentence being spoken. Sentences are numbered starting at 1.
+ * - int sentenceCount Total number of sentences in the job.
+ * - int partNum Current part of the job begin spoken. Parts are numbered starting at 1.
+ * - int partCount Total number of parts in the job.
+ *
+ * Note that sequence numbers apply to the entire job.
+ * They do not start from 1 at the beginning of each part.
+ *
+ * The following sample code will decode the stream:
+ @verbatim
+ QByteArray jobInfo = getTextJobInfo(jobNum);
+ QDataStream stream(jobInfo, IO_ReadOnly);
+ int state;
+ QCString appId;
+ QString talker;
+ int seq;
+ int sentenceCount;
+ int partNum;
+ int partCount;
+ stream >> state;
+ stream >> appId;
+ stream >> talker;
+ stream >> seq;
+ stream >> sentenceCount;
+ stream >> partNum;
+ stream >> partCount;
+ @endverbatim
+ */
+ QByteArray getTextJobInfo(const uint jobNum);
+
+ /**
+ * Return a sentence of a job.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the sentence.
+ * @return The specified sentence in the specified job. If no such
+ * job or sentence, returns "".
+ */
+ QString getTextJobSentence(const uint jobNum, const uint seq=1);
+
+ /**
+ * Remove a text job from the queue.
+ * (thread safe)
+ * @param jobNum Job number of the text job.
+ *
+ * The job is deleted from the queue and the textRemoved signal is emitted.
+ */
+ void removeText(const uint jobNum);
+
+ /**
+ * Change the talker for a text job.
+ * @param jobNum Job number of the text job.
+ * @param talker New code for the talker to do speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * If no plugin has been configured for the specified Talker code,
+ * defaults to the closest matching talker.
+ */
+ void changeTextTalker(const QString &talker, uint jobNum);
+
+ /**
+ * Move a text job down in the queue so that it is spoken later.
+ * @param jobNum Job number of the text job.
+ */
+ void moveTextLater(const uint jobNum);
+
+ /**
+ * Jump to the first sentence of a specified part of a text job.
+ * @param partNum Part number of the part to jump to. Parts are numbered starting at 1.
+ * @param jobNum Job number of the text job.
+ * @return Part number of the part actually jumped to.
+ *
+ * If partNum is greater than the number of parts in the job, jumps to last part.
+ * If partNum is 0, does nothing and returns the current part number.
+ * If no such job, does nothing and returns 0.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+ int jumpToTextPart(const int partNum, const uint jobNum);
+
+ /**
+ * Advance or rewind N sentences in a text job.
+ * @param n Number of sentences to advance (positive) or rewind (negative)
+ * in the job.
+ * @param jobNum Job number of the text job.
+ * @return Sequence number of the sentence actually moved to. Sequence numbers
+ * are numbered starting at 1.
+ *
+ * If no such job, does nothing and returns 0.
+ * If n is zero, returns the current sequence number of the job.
+ * Does not affect the current speaking/not-speaking state of the job.
+ */
+ uint moveRelTextSentence(const int n, const uint jobNum);
+
+ /**
+ * Given a jobNum, returns the first job with that jobNum.
+ * @return Pointer to the text job.
+ * If no such job, returns 0.
+ * Does not change textJobs.current().
+ */
+ mlJob* findJobByJobNum(const uint jobNum);
+
+ /**
+ * Given a Job Number, returns the next speakable text job on the queue.
+ * @param prevJobNum Current job number (which should not be returned).
+ * @return Pointer to mlJob structure of the first speakable job
+ * not equal prevJobNum. If no such job, returns null.
+ *
+ * Caller must not delete the job.
+ */
+ mlJob* getNextSpeakableJob(const uint prevJobNum);
+
+ /**
+ * Given previous job number and sequence number, returns the next sentence from the
+ * text queue. If no such sentence is available, either because we've run out of
+ * jobs, or because all jobs are paused, returns null.
+ * @param prevJobNum Previous Job Number.
+ * @param prevSeq Previous sequency number.
+ * @return Pointer to n mlText structure containing the next sentence. If no
+ * sentence, returns null.
+ *
+ * Caller is responsible for deleting the returned mlText structure (if not null).
+ */
+ mlText* getNextSentenceText(const uint prevJobNum, const uint prevSeq);
+
+ /**
+ * Given a Job Number, sets the current sequence number of the job.
+ * @param jobNum Job Number.
+ * @param seq Sequence number.
+ * If for some reason, the job does not exist, nothing happens.
+ */
+ void setJobSequenceNum(const uint jobNum, const uint seq);
+
+ /**
+ * Given a Job Number, returns the current sequence number of the job.
+ * @param jobNum Job Number.
+ * @return Sequence number of the job. If no such job, returns 0.
+ */
+ uint getJobSequenceNum(const uint jobNum);
+
+ /**
+ * Given a jobNum, returns the appId of the application that owns the job.
+ * @param jobNum Job number of the text job.
+ * @return appId of the job.
+ * If no such job, returns "".
+ * Does not change textJobs.current().
+ */
+ QCString getAppIdByJobNum(const uint jobNum);
+
+ /**
+ * Sets pointer to the TalkerMgr object.
+ */
+ void setTalkerMgr(TalkerMgr* talkerMgr);
+
+ /* The following properties come from the configuration. */
+
+ /**
+ * Text pre message
+ */
+ QString textPreMsg;
+
+ /**
+ * Text pre message enabled ?
+ */
+ bool textPreMsgEnabled;
+
+ /**
+ * Text pre sound
+ */
+ QString textPreSnd;
+
+ /**
+ * Text pre sound enabled ?
+ */
+ bool textPreSndEnabled;
+
+ /**
+ * Text post message
+ */
+ QString textPostMsg;
+
+ /**
+ * Text post message enabled ?
+ */
+ bool textPostMsgEnabled;
+
+ /**
+ * Text post sound
+ */
+ QString textPostSnd;
+
+ /**
+ * Text post sound enabled ?
+ */
+ bool textPostSndEnabled;
+
+ /**
+ * Paragraph pre message
+ */
+ QString parPreMsg;
+
+ /**
+ * Paragraph pre message enabled ?
+ */
+ bool parPreMsgEnabled;
+
+ /**
+ * Paragraph pre sound
+ */
+ QString parPreSnd;
+
+ /**
+ * Paragraph pre sound enabled ?
+ */
+ bool parPreSndEnabled;
+
+ /**
+ * Paragraph post message
+ */
+ QString parPostMsg;
+
+ /**
+ * Paragraph post message enabled ?
+ */
+ bool parPostMsgEnabled;
+
+ /**
+ * Paragraph post sound
+ */
+ QString parPostSnd;
+
+ /**
+ * Paragraph post sound enabled ?
+ */
+ bool parPostSndEnabled;
+
+ /**
+ * Keep audio files. Do not delete generated tmp wav files.
+ */
+ bool keepAudio;
+ QString keepAudioPath;
+
+ /**
+ * Notification settings.
+ */
+ bool notify;
+ bool notifyExcludeEventsWithSound;
+ NotifyAppMap notifyAppMap;
+ int notifyDefaultPresent;
+ NotifyOptions notifyDefaultOptions;
+
+ /**
+ * Automatically start KTTSMgr whenever speaking.
+ */
+ bool autoStartManager;
+
+ /**
+ * Automatically exit auto-started KTTSMgr when speaking finishes.
+ */
+ bool autoExitManager;
+
+ /**
+ * Configuration
+ */
+ KConfig *config;
+
+ /**
+ * True if at least one XML Transformer plugin for html is enabled.
+ */
+ bool supportsHTML;
+
+ signals:
+ /**
+ * This signal is emitted whenever a new text job is added to the queue.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textSet(const QCString& appId, const uint jobNum);
+
+ /**
+ * This signal is emitted whenever a new part is appended to a text job.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ * @param partNum Part number of the new part. Parts are numbered starting
+ * at 1.
+ */
+ void textAppended(const QCString& appId, const uint jobNum, const int partNum);
+
+ /**
+ * This signal is emitted whenever a text job is deleted from the queue.
+ * The job is no longer in the queue when this signal is emitted.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ */
+ void textRemoved(const QCString& appId, const uint jobNum);
+
+ private:
+ /**
+ * Screen Reader Output.
+ */
+ mlText screenReaderOutput;
+
+ /**
+ * Queue of warnings
+ */
+ QPtrQueue<mlJob> warnings;
+
+ /**
+ * Queue of messages
+ */
+ QPtrQueue<mlJob> messages;
+
+ /**
+ * Queue of text jobs.
+ */
+ QPtrList<mlJob> textJobs;
+
+ /**
+ * TalkerMgr object local pointer.
+ */
+ TalkerMgr* m_talkerMgr;
+
+ /**
+ * Pool of FilterMgrs.
+ */
+ QPtrList<PooledFilterMgr> m_pooledFilterMgrs;
+
+ /**
+ * Job counter. Each new job increments this counter.
+ */
+ uint jobCounter;
+
+ /**
+ * Talker of the text
+ */
+ QString textTalker;
+
+ /**
+ * Map of sentence delimiters. One per app. If none specified for an app, uses default.
+ */
+ QMap<QCString, QString> sentenceDelimiters;
+
+ /**
+ * Determines whether the given text is SSML markup.
+ */
+ bool isSsml(const QString &text);
+
+ /**
+ * Given an appId, returns the last (most recently queued) job with that appId.
+ * @param appId The DCOP senderId of the application.
+ * @return Pointer to the text job.
+ * If no such job, returns 0.
+ * If appId is NULL, returns the last job in the queue.
+ * Does not change textJobs.current().
+ */
+ mlJob* findLastJobByAppId(const QCString& appId);
+
+ /**
+ * Given an appId, returns the last (most recently queued) job with that appId,
+ * or if no such job, the last (most recent) job in the queue.
+ * @param appId The DCOP senderId of the application.
+ * @return Pointer to the text job.
+ * If no such job, returns 0.
+ * If appId is NULL, returns the last job in the queue.
+ * Does not change textJobs.current().
+ */
+ mlJob* findAJobByAppId(const QCString& appId);
+
+ /**
+ * Given a job and a sequence number, returns the part that sentence is in.
+ * If no such job or sequence number, returns 0.
+ * @param job The text job.
+ * @param seq Sequence number of the sentence. Sequence numbers begin with 1.
+ * @return Part number of the part the sentence is in. Parts are numbered
+ * beginning with 1. If no such job or sentence, returns 0.
+ */
+ int getJobPartNumFromSeq(const mlJob& job, const int seq);
+
+ /**
+ * Parses a block of text into sentences using the application-specified regular expression
+ * or (if not specified), the default regular expression.
+ * @param text The message to be spoken.
+ * @param appId The DCOP senderId of the application.
+ * @return List of parsed sentences.
+ */
+
+ QStringList parseText(const QString &text, const QCString &appId);
+
+ /**
+ * Delete expired jobs. At most, one finished job is kept on the queue.
+ * @param finishedJobNum Job number of a job that just finished
+ * The just finished job is not deleted, but any other finished jobs are.
+ * Does not change the textJobs.current() pointer.
+ */
+ void deleteExpiredJobs(const uint finishedJobNum);
+
+ /**
+ * Assigns a FilterMgr to a job and starts filtering on it.
+ */
+ void startJobFiltering(mlJob* job, const QString& text, bool noSBD);
+
+ /**
+ * Waits for filtering to be completed on a job.
+ * This is typically called because an app has requested job info that requires
+ * filtering to be completed, such as getJobInfo.
+ */
+ void waitJobFiltering(const mlJob* job);
+
+ /**
+ * Processes filters by looping across the pool of FilterMgrs.
+ * As each FilterMgr finishes, emits appropriate signals and flags it as no longer busy.
+ */
+ void doFiltering();
+
+ /**
+ * Loads notify events from a file. Clearing data if clear is True.
+ */
+ void loadNotifyEventsFromFile( const QString& filename, bool clear);
+
+ private slots:
+ void slotFilterMgrFinished();
+ void slotFilterMgrStopped();
+};
+
+#endif // _SPEECHDATA_H_
diff --git a/kttsd/kttsd/ssmlconvert.cpp b/kttsd/kttsd/ssmlconvert.cpp
new file mode 100644
index 0000000..521a9a6
--- /dev/null
+++ b/kttsd/kttsd/ssmlconvert.cpp
@@ -0,0 +1,295 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ SSMLConvert class
+
+ This class is in charge of converting SSML text into a format that can
+ be handled by individual synths.
+ -------------------
+ Copyright:
+ (C) 2004 by Paul Giannaros <ceruleanblaze@gmail.com>
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qtextstream.h>
+
+// KDE includes.
+#include <kdeversion.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+
+// SSMLConvert includes.
+#include "ssmlconvert.h"
+#include "ssmlconvert.moc"
+
+/// Constructor.
+SSMLConvert::SSMLConvert() {
+ m_talkers = QStringList();
+ m_xsltProc = 0;
+ m_state = tsIdle;
+}
+
+/// Constructor. Set the talkers to be used as reference for entered text.
+SSMLConvert::SSMLConvert(const QStringList &talkers) {
+ m_talkers = talkers;
+ m_xsltProc = 0;
+ m_state = tsIdle;
+}
+
+/// Destructor.
+SSMLConvert::~SSMLConvert() {
+ delete m_xsltProc;
+ if (!m_inFilename.isEmpty()) QFile::remove(m_inFilename);
+ if (!m_outFilename.isEmpty()) QFile::remove(m_outFilename);
+}
+
+/// Set the talkers to be used as reference for entered text.
+void SSMLConvert::setTalkers(const QStringList &talkers) {
+ m_talkers = talkers;
+}
+
+QString SSMLConvert::extractTalker(const QString &talkercode) {
+ QString t = talkercode.section("synthesizer=", 1, 1);
+ t = t.section('"', 1, 1);
+ if(t.contains("flite"))
+ return "flite";
+ else
+ return t.left(t.find(" ")).lower();
+}
+
+/**
+* Return the most appropriate talker for the text to synth talker code.
+* @param text the text that will be parsed.
+* @returns the appropriate talker for the job as a talker code.
+*
+* The appropriate talker is the one that has the most features that are required in some
+* SSML markup. In the future i'm hoping to make the importance of individual features
+* configurable, but better to walk before you can run.
+* Currently, the searching method in place is like a filter: Those that meet the criteria we're
+* searchin for stay while others are sifted out. This should leave us with the right talker to use.
+* It's not a very good method, but should be appropriate in most cases and should do just fine for now.
+*
+* As it stands, here is the list of things that are looked for, in order of most importance:
+* - Language
+* Obviously the most important. If a language is specified, look for the talkers that support it.
+* Default to en (or some form of en - en_US, en_GB, etc). Only one language at a time is allowed
+* at the moment, and must be specified in the root speak element (<speak xml:lang="en-US">)
+* - Gender
+* If a gender is specified, look for talkers that comply. There is no default so if no gender is
+* specified, no talkers will be removed. The only gender that will be searched for is the one
+* specified in the root speak element. This should change in the future.
+* - Prosody
+* Check if prosody modification is allowed by the talker. Currently this is hardcoded (it
+* is stated which talkers do and do not in a variable somewhere).
+*
+* Bear in mind that the XSL stylesheet that will be applied to the SSML is the same regardless
+* of the how the talker is chosen, meaning that you don't lose some features of the talker if this
+* search doesn't encompass them.
+*
+* QDom is the item of choice for the matching. Just walk the tree..
+*/
+QString SSMLConvert::appropriateTalker(const QString &text) const {
+ QDomDocument ssml;
+ ssml.setContent(text, false); // No namespace processing.
+ /// Matches are stored here. Obviously to begin with every talker matches.
+ QStringList matches = m_talkers;
+
+ /// Check that this is (well formed) SSML and all our searching will not be in vain.
+ QDomElement root = ssml.documentElement();
+ if(root.tagName() != "speak") {
+ // Not SSML.
+ return QString::null;
+ }
+
+ /**
+ * For each rule that we are looking through, iterate over all currently
+ * matching talkers and remove all the talkers that don't match.
+ *
+ * Storage for talker code components.
+ */
+ QString talklang, talkvoice, talkgender, talkvolume, talkrate, talkname;
+
+ kdDebug() << "SSMLConvert::appropriateTalker: BEFORE LANGUAGE SEARCH: " << matches.join(" ") << endl;;
+ /**
+ * Language searching
+ */
+ if(root.hasAttribute("xml:lang")) {
+ QString lang = root.attribute("xml:lang");
+ kdDebug() << "SSMLConvert::appropriateTalker: xml:lang found (" << lang << ")" << endl;
+ /// If it is set to en*, then match all english speakers. They all sound the same anyways.
+ if(lang.contains("en-")) {
+ kdDebug() << "SSMLConvert::appropriateTalker: English" << endl;
+ lang = "en";
+ }
+ /// Find all hits and place them in matches. We don't search for the closing " because if
+ /// the talker emits lang="en-UK" or something we'll be ignoring it, which we don't what.
+ matches = matches.grep("lang=\"" + lang);
+ }
+ else {
+ kdDebug() << "SSMLConvert::appropriateTalker: no xml:lang found. Defaulting to en.." << endl;
+ matches = matches.grep("lang=\"en");
+ }
+
+ kdDebug() << "SSMLConvert::appropriateTalker: AFTER LANGUAGE SEARCH: " << matches.join(" ") << endl;;
+
+ /**
+ * Gender searching
+ * If, for example, male is specified and only female is found,
+ * ignore the choice and just use female.
+ */
+ if(root.hasAttribute("gender")) {
+ QString gender = root.attribute("gender");
+ kdDebug() << "SSMLConvert::appropriateTalker: gender found (" << gender << ")" << endl;
+ /// If the gender found is not 'male' or 'female' then ignore it.
+ if(!(gender == "male" || gender == "female")) {
+ /// Make sure that we don't strip away all the talkers because of no matches.
+ if(matches.grep("gender=\"" + gender).count() >= 1)
+ matches = matches.grep("gender=\"" + gender);
+ }
+ }
+ else {
+ kdDebug() << "SSMLConvert::appropriateTalker: no gender found." << endl;
+ }
+
+ /**
+ * Prosody
+ * Search for talkers that allow modification of the synth output - louder, higher,
+ * slower, etc. There should be a direct way to query each synth to find out if this
+ * is supported (some function in PlugInConf), but for now, hardcode all the way :(
+ */
+ /// Known to support (feel free to add to the list and if search):
+ /// Festival Int (not flite), Hadifix
+ if(matches.grep("synthesizer=\"Festival Interactive").count() >= 1 ||
+ matches.grep("synthesizer=\"Hadifix").count() >= 1) {
+
+ kdDebug() << "SSMLConvert::appropriateTalker: Prosody allowed" << endl;
+ QStringList tmpmatches = matches.grep("synthesizer=\"Festival Interactive");
+ matches = matches.grep("synthesizer=\"Hadifix");
+ matches = tmpmatches + matches;
+ }
+ else
+ kdDebug() << "SSMLConvert::appropriateTalker: No prosody-supporting talkers found" << endl;
+
+ /// Return the first match that complies. Maybe a discrete way to
+ /// choose between all the matches could be offered in the future. Some form of preference.
+ return matches[0];
+}
+
+/**
+* Applies the spreadsheet for a talker to the SSML and returns the talker-native output.
+* @param text The markup to apply the spreadsheet to.
+* @param xsltFilename The name of the stylesheet file that will be applied (i.e freetts, flite).
+* @returns False if an error occurs.
+*
+* This converts a piece of SSML into a format the given talker can understand. It applies
+* an XSLT spreadsheet to the SSML and returns the output.
+*
+* Emits transformFinished signal when completed. Caller then calls getOutput to retrieve
+* the transformed text.
+*/
+
+bool SSMLConvert::transform(const QString &text, const QString &xsltFilename) {
+ m_xsltFilename = xsltFilename;
+ /// Write @param text to a temporary file.
+ KTempFile inFile(locateLocal("tmp", "kttsd-"), ".ssml");
+ m_inFilename = inFile.file()->name();
+ QTextStream* wstream = inFile.textStream();
+ if (wstream == 0) {
+ /// wtf...
+ kdDebug() << "SSMLConvert::transform: Can't write to " << m_inFilename << endl;;
+ return false;
+ }
+ // TODO: Is encoding an issue here?
+ // TODO: It would be nice if we detected whether the XML is properly formed
+ // with the required xml processing instruction and encoding attribute. If
+ // not wrap it in such. But maybe this should be handled by SpeechData::setText()?
+ *wstream << text;
+ inFile.close();
+#if KDE_VERSION >= KDE_MAKE_VERSION (3,3,0)
+ inFile.sync();
+#endif
+
+ // Get a temporary output file name.
+ KTempFile outFile(locateLocal("tmp", "kttsd-"), ".output");
+ m_outFilename = outFile.file()->name();
+ outFile.close();
+ // outFile.unlink(); // only activate this if necessary.
+
+ /// Spawn an xsltproc process to apply our stylesheet to our SSML file.
+ m_xsltProc = new KProcess;
+ *m_xsltProc << "xsltproc";
+ *m_xsltProc << "-o" << m_outFilename << "--novalid"
+ << m_xsltFilename << m_inFilename;
+ // Warning: This won't compile under KDE 3.2. See FreeTTS::argsToStringList().
+ // kdDebug() << "SSMLConvert::transform: executing command: " <<
+ // m_xsltProc->args() << endl;
+
+ connect(m_xsltProc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*)));
+ if (!m_xsltProc->start(KProcess::NotifyOnExit, KProcess::NoCommunication))
+ {
+ kdDebug() << "SSMLConvert::transform: Error starting xsltproc" << endl;
+ return false;
+ }
+ m_state = tsTransforming;
+ return true;
+}
+
+void SSMLConvert::slotProcessExited(KProcess* /*proc*/)
+{
+ m_xsltProc->deleteLater();
+ m_xsltProc = 0;
+ m_state = tsFinished;
+ emit transformFinished();
+}
+
+/**
+* Returns current processing state.
+*/
+int SSMLConvert::getState() { return m_state; }
+
+/**
+* Returns the output from call to transform.
+*/
+QString SSMLConvert::getOutput()
+{
+ /// Read back the data that was written to /tmp/fileName.output.
+ QFile readfile(m_outFilename);
+ if(!readfile.open(IO_ReadOnly)) {
+ /// uhh yeah... Issues writing to the SSML file.
+ kdDebug() << "SSMLConvert::slotProcessExited: Could not read file " << m_outFilename << endl;
+ return QString::null;
+ }
+ QTextStream rstream(&readfile);
+ QString convertedData = rstream.read();
+ readfile.close();
+
+ // kdDebug() << "SSMLConvert::slotProcessExited: Read SSML file at " + m_inFilename + " and created " + m_outFilename + " based on the stylesheet at " << m_xsltFilename << endl;
+
+ // Clean up.
+ QFile::remove(m_inFilename);
+ m_inFilename = QString::null;
+ QFile::remove(m_outFilename);
+ m_outFilename = QString::null;
+
+ // Ready for another transform.
+ m_state = tsIdle;
+
+ return convertedData;
+}
+
diff --git a/kttsd/kttsd/ssmlconvert.h b/kttsd/kttsd/ssmlconvert.h
new file mode 100644
index 0000000..1ee332c
--- /dev/null
+++ b/kttsd/kttsd/ssmlconvert.h
@@ -0,0 +1,129 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ SSMLConvert class
+
+ This class is in charge of converting SSML text into a format that can
+ be handled by individual synths.
+ -------------------
+ Copyright:
+ (C) 2004 by Paul Giannaros <ceruleanblaze@gmail.com>
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _SSMLCONVERT_H_
+#define _SSMLCONVERT_H_
+
+/**
+ * SsmlConvert class:
+ * Receives a QStringList of talkers and, based on that information,
+ * evaluates received SSML to discover which of the given talkers best
+ * suits it. It can then convert the given SSML into a format understandable
+ * by the talker.
+ */
+
+// Qt includes
+#include <qobject.h>
+#include <qstringlist.h>
+
+class KProcess;
+class QString;
+
+class SSMLConvert : public QObject {
+ Q_OBJECT
+public:
+ /** Constructors */
+ SSMLConvert();
+ SSMLConvert(const QStringList &talkers);
+ /** Destructor */
+ virtual ~SSMLConvert();
+
+ enum TransformState {
+ tsIdle = 0, // Not doing anything. Ready to transform.
+ tsTransforming = 1, // Transforming.
+ tsFinished = 2 // Transforming finished.
+ };
+
+ /**
+ * Set the talker codes to be used.
+ * @param talkers talker codes to be used.
+ */
+ void setTalkers(const QStringList &talkers);
+
+ /**
+ * Extract the synth name from a talker code (i.e festival, flite, freetts).
+ * @param talkercode the talker code to extract the talker from.
+ * @returns the talker.
+ */
+ QString extractTalker(const QString &talkercode);
+
+ /**
+ * Returns the most appropriate talker for the text to synth's talker code.
+ * @param text the text that will be parsed.
+ * @returns the appropriate talker for the job as a talker code QString.
+ *
+ * The appropriate talker is the one that has the most features that are required in some
+ * SSML markup. In the future i'm hoping to make the importance of individual features
+ * configurable, but better to walk before you can run.
+ * Currently, the searching method in place is like a filter: Those that meet the criteria we're
+ * searchin for stay while others are sifted out. This should leave us with the right talker to use.
+ * It's not a very good method, but should be appropriate in most cases and should do just fine for now.
+ *
+ * See the implementation file for more detail.
+ */
+ QString appropriateTalker(const QString &text) const;
+
+ /**
+ * Applies the spreadsheet for a talker to the SSML and returns the talker-native output.
+ * @param text the markup to apply the spreadsheet to.
+ * @param xsltFilename the name of the stylesheet file that will be applied (i.e freetts, flite).
+ * @returns the output that the synth can understand.
+ *
+ * This converts a piece of SSML into a format the given talker can understand. It applies
+ * an XSLT spreadsheet to the SSML and returns the output.
+ */
+ bool transform(const QString &text, const QString &xsltFilename);
+
+ /**
+ * Returns current processing state.
+ */
+ int getState();
+
+ /**
+ * Returns the output from call to transform.
+ */
+ QString getOutput();
+
+signals:
+ /**
+ * Emitted whenever tranforming is completed.
+ */
+ void transformFinished();
+
+private slots:
+ void slotProcessExited(KProcess* proc);
+
+private:
+ /// The XSLT processor.
+ KProcess *m_xsltProc;
+ /// Current talkers.
+ QStringList m_talkers;
+ // Current state.
+ int m_state;
+ // Name of XSLT file.
+ QString m_xsltFilename;
+ // Name of temporary input file.
+ QString m_inFilename;
+ // Name of temporary output file.
+ QString m_outFilename;
+};
+
+#endif // _SSMLCONVERT_H_
diff --git a/kttsd/kttsd/talkermgr.cpp b/kttsd/kttsd/talkermgr.cpp
new file mode 100644
index 0000000..345f12b
--- /dev/null
+++ b/kttsd/kttsd/talkermgr.cpp
@@ -0,0 +1,388 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Manages all the Talker (synth) plugins.
+ -------------------
+ Copyright:
+ (C) 2004-2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+
+// KDE includes.
+#include <kdebug.h>
+#include <kparts/componentfactory.h>
+#include <ktrader.h>
+#include <kstandarddirs.h>
+
+// KTTS includes.
+#include "pluginconf.h"
+#include "talkermgr.h"
+#include "threadedplugin.h"
+
+/**
+ * Constructor.
+ */
+TalkerMgr::TalkerMgr(QObject *parent, const char *name) :
+ QObject( parent, name )
+{
+ m_loadedPlugIns.setAutoDelete(true);
+}
+
+/**
+ * Destructor.
+ */
+TalkerMgr::~TalkerMgr()
+{
+ m_loadedPlugIns.clear();
+}
+
+/**
+ * Load all the configured synth plugins, populating loadedPlugIns structure.
+ */
+int TalkerMgr::loadPlugIns(KConfig* config)
+{
+ // kdDebug() << "Running: TalkerMgr::loadPlugIns()" << endl;
+ int good = 0;
+ int bad = 0;
+
+ m_talkerToPlugInCache.clear();
+ m_loadedPlugIns.clear();
+ m_loadedTalkerCodes.clear();
+ m_loadedTalkerIds.clear();
+
+ config->setGroup("General");
+ QStringList talkerIDsList = config->readListEntry("TalkerIDs", ',');
+ if (!talkerIDsList.isEmpty())
+ {
+ KLibFactory *factory;
+ QStringList::ConstIterator itEnd(talkerIDsList.constEnd());
+ for( QStringList::ConstIterator it = talkerIDsList.constBegin(); it != itEnd; ++it )
+ {
+ // kdDebug() << "Loading plugInProc for Talker ID " << *it << endl;
+
+ // Talker ID.
+ QString talkerID = *it;
+
+ // Set the group for the language we're loading
+ config->setGroup("Talker_" + talkerID);
+
+ // Get the DesktopEntryName of the plugin we will try to load.
+ QString desktopEntryName = config->readEntry("DesktopEntryName", QString::null);
+
+ // If a DesktopEntryName is not in the config file, it was configured before
+ // we started using them, when we stored translated plugin names instead.
+ // Try to convert the translated plugin name to a DesktopEntryName.
+ // DesktopEntryNames are better because user can change their desktop language
+ // and DesktopEntryName won't change.
+ if (desktopEntryName.isEmpty())
+ {
+ QString synthName = config->readEntry("PlugIn", QString::null);
+ // See if the translated name will untranslate. If not, well, sorry.
+ desktopEntryName = TalkerCode::TalkerNameToDesktopEntryName(synthName);
+ // Record the DesktopEntryName from now on.
+ if (!desktopEntryName.isEmpty()) config->writeEntry("DesktopEntryName", desktopEntryName);
+ }
+
+ // Get the talker code.
+ QString talkerCode = config->readEntry("TalkerCode", QString::null);
+
+ // Normalize the talker code.
+ QString fullLanguageCode;
+ talkerCode = TalkerCode::normalizeTalkerCode(talkerCode, fullLanguageCode);
+
+ // Find the KTTSD SynthPlugin.
+ KTrader::OfferList offers = KTrader::self()->query(
+ "KTTSD/SynthPlugin", QString("DesktopEntryName == '%1'").arg(desktopEntryName));
+
+ if(offers.count() > 1){
+ ++bad;
+ kdDebug() << "More than 1 plug in doesn't make any sense, well, let's use any" << endl;
+ } else if(offers.count() < 1){
+ ++bad;
+ kdDebug() << "Less than 1 plug in, nothing can be done" << endl;
+ } else {
+ kdDebug() << "Loading " << offers[0]->library() << endl;
+ factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if(factory){
+ PlugInProc *speech =
+ KParts::ComponentFactory::createInstanceFromLibrary<PlugInProc>(
+ offers[0]->library().latin1(), this, offers[0]->library().latin1());
+ if(!speech){
+ kdDebug() << "Couldn't create the speech object from " << offers[0]->library() << endl;
+ ++bad;
+ } else {
+ if (speech->supportsAsync())
+ {
+ speech->init(config, "Talker_" + talkerID);
+ // kdDebug() << "Plug in " << desktopEntryName << " created successfully." << endl;
+ m_loadedPlugIns.append(speech);
+ } else {
+ // Synchronous plugins are run in a separate thread.
+ // Init will start the thread and it will immediately go to sleep.
+ QString threadedPlugInName = QString::fromLatin1("threaded") + desktopEntryName;
+ ThreadedPlugIn* speechThread = new ThreadedPlugIn(speech,
+ this, threadedPlugInName.latin1());
+ speechThread->init(config, "Talker_" + talkerCode);
+ // kdDebug() << "Threaded Plug in " << desktopEntryName << " for language " << (*it).right((*it).length()-5) << " created succesfully." << endl;
+ m_loadedPlugIns.append(speechThread);
+ }
+ ++good;
+ m_loadedTalkerCodes.append(TalkerCode(talkerCode));
+ m_loadedTalkerIds.append(talkerID);
+ }
+ } else {
+ kdDebug() << "Couldn't create the factory object from " << offers[0]->library() << endl;
+ ++bad;
+ }
+ }
+ }
+ }
+ if(bad > 0){
+ if(good == 0){
+ // No plugin could be loaded.
+ return -1;
+ } else {
+ // At least one plugin was loaded and one failed.
+ return 0;
+ }
+ } else {
+ if (good == 0)
+ // No plugin could be loaded.
+ return -1;
+ else
+ // All the plug in were loaded perfectly
+ return 1;
+ }
+}
+
+/**
+ * Get a list of the talkers configured in KTTS.
+ * @return A QStringList of fully-specified talker codes, one
+ * for each talker user has configured.
+ */
+QStringList TalkerMgr::getTalkers()
+{
+ QStringList talkerList;
+ for (int ndx = 0; ndx < int(m_loadedPlugIns.count()); ++ndx)
+ {
+ talkerList.append(m_loadedTalkerCodes[ndx].getTalkerCode());
+ }
+ return talkerList;
+}
+
+/**
+ * Returns a list of all the loaded plugins.
+ */
+QPtrList<PlugInProc> TalkerMgr::getLoadedPlugIns()
+{
+ return m_loadedPlugIns;
+}
+
+/**
+ * Given a talker code, returns pointer to the closest matching plugin.
+ * @param talker The talker (language) code.
+ * @return Index to m_loadedPlugins array of Talkers.
+ *
+ * If a plugin has not been loaded to match the talker, returns the default
+ * plugin.
+ */
+int TalkerMgr::talkerToPluginIndex(const QString& talker) const
+{
+ // kdDebug() << "TalkerMgr::talkerToPluginIndex: matching talker " << talker << " to closest matching plugin." << endl;
+ // If we have a cached match, return that.
+ if (m_talkerToPlugInCache.contains(talker))
+ return m_talkerToPlugInCache[talker];
+ else
+ {
+ int winner = TalkerCode::findClosestMatchingTalker(m_loadedTalkerCodes, talker, true);
+ m_talkerToPlugInCache[talker] = winner;
+ return winner;
+ }
+}
+
+/**
+ * Given a talker code, returns pointer to the closest matching plugin.
+ * @param talker The talker (language) code.
+ * @return Pointer to closest matching plugin.
+ *
+ * If a plugin has not been loaded to match the talker, returns the default
+ * plugin.
+ *
+ * TODO: When picking a talker, %KTTSD will automatically determine if text contains
+ * markup and pick a talker that supports that markup, if available. This
+ * overrides all other attributes, i.e, it is treated as an automatic "top priority"
+ * attribute.
+ */
+PlugInProc* TalkerMgr::talkerToPlugin(const QString& talker) const
+{
+ int talkerNdx = talkerToPluginIndex(talker);
+ return const_cast< QPtrList<PlugInProc>* >(&m_loadedPlugIns)->at(talkerNdx);
+}
+
+/**
+ * Given a talker code, returns the parsed TalkerCode of the closest matching Talker.
+ * @param talker The talker (language) code.
+ * @return Parsed TalkerCode structure.
+ *
+ * If a plugin has not been loaded to match the talker, returns the default
+ * plugin.
+ *
+ * The returned TalkerCode is a copy and should be destroyed by caller.
+ *
+ * TODO: When picking a talker, %KTTSD will automatically determine if text contains
+ * markup and pick a talker that supports that markup, if available. This
+ * overrides all other attributes, i.e, it is treated as an automatic "top priority"
+ * attribute.
+ */
+TalkerCode* TalkerMgr::talkerToTalkerCode(const QString& talker)
+{
+ int talkerNdx = talkerToPluginIndex(talker);
+ return new TalkerCode(&m_loadedTalkerCodes[talkerNdx]);
+}
+
+/**
+ * Given a Talker Code, returns the Talker ID of the talker that would speak
+ * a text job with that Talker Code.
+ * @param talkerCode Talker Code.
+ * @return Talker ID of the talker that would speak the text job.
+ */
+QString TalkerMgr::talkerCodeToTalkerId(const QString& talkerCode)
+{
+ int talkerNdx = talkerToPluginIndex(talkerCode);
+ return m_loadedTalkerIds[talkerNdx];
+}
+
+/**
+ * Get the user's default talker.
+ * @return A fully-specified talker code.
+ *
+ * @see talkers
+ * @see getTalkers
+ */
+QString TalkerMgr::userDefaultTalker() const
+{
+ return m_loadedTalkerCodes[0].getTalkerCode();
+}
+
+/**
+ * Determine whether the currently-configured speech plugin supports a speech markup language.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * @param markupType The kttsd code for the desired speech markup language.
+ * @return True if the plugin currently configured for the indicated
+ * talker supports the indicated speech markup language.
+ * @see kttsdMarkupType
+ */
+bool TalkerMgr::supportsMarkup(const QString& talker, const uint /*markupType*/) const
+{
+ kdDebug() << "TalkerMgr::supportsMarkup: Testing talker " << talker << endl;
+ QString matchingTalker = talker;
+ if (matchingTalker.isEmpty()) matchingTalker = userDefaultTalker();
+ PlugInProc* plugin = talkerToPlugin(matchingTalker);
+ return ( plugin->getSsmlXsltFilename() !=
+ KGlobal::dirs()->resourceDirs("data").last() + "kttsd/xslt/SSMLtoPlainText.xsl");
+}
+
+bool TalkerMgr::autoconfigureTalker(const QString& langCode, KConfig* config)
+{
+ // Not yet implemented.
+ // return false;
+
+ QString languageCode = langCode;
+
+ // Get last TalkerID from config.
+ QStringList talkerIDsList = config->readListEntry("TalkerIDs", ',');
+ int lastTalkerID = 0;
+ for (uint talkerIdNdx = 0; talkerIdNdx < talkerIDsList.count(); ++talkerIdNdx)
+ {
+ int id = talkerIDsList[talkerIdNdx].toInt();
+ if (id > lastTalkerID) lastTalkerID = id;
+ }
+
+ // Assign a new Talker ID for the talker. Wraps around to 1.
+ QString talkerID = QString::number(lastTalkerID + 1);
+
+ // Query for all the KTTSD SynthPlugins.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/SynthPlugin");
+
+ // Iterate thru the possible plug ins.
+ for(unsigned int i=0; i < offers.count() ; ++i)
+ {
+ // See if this plugin supports the desired language.
+ QStringList languageCodes = offers[i]->property("X-KDE-Languages").toStringList();
+ if (languageCodes.contains(languageCode))
+ {
+ QString desktopEntryName = offers[i]->desktopEntryName();
+
+ // Load the plugin.
+ KLibFactory *factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if (factory)
+ {
+ // If the factory is created successfully, instantiate the PlugInConf class for the
+ // specific plug in to get the plug in configuration object.
+ PlugInConf* loadedTalkerPlugIn =
+ KParts::ComponentFactory::createInstanceFromLibrary<PlugInConf>(
+ offers[0]->library().latin1(), NULL, offers[0]->library().latin1());
+ if (loadedTalkerPlugIn)
+ {
+ // Give plugin the language code and permit plugin to autoconfigure itself.
+ loadedTalkerPlugIn->setDesiredLanguage(languageCode);
+ loadedTalkerPlugIn->load(config, QString("Talker_")+talkerID);
+
+ // If plugin was able to configure itself, it returns a full talker code.
+ QString talkerCode = loadedTalkerPlugIn->getTalkerCode();
+
+ if (!talkerCode.isEmpty())
+ {
+ // Erase extraneous Talker configuration entries that might be there.
+ config->deleteGroup(QString("Talker_")+talkerID);
+
+ // Let plugin save its configuration.
+ config->setGroup(QString("Talker_")+talkerID);
+ loadedTalkerPlugIn->save(config, QString("Talker_"+talkerID));
+
+ // Record configuration data.
+ config->setGroup(QString("Talker_")+talkerID);
+ config->writeEntry("DesktopEntryName", desktopEntryName);
+ talkerCode = TalkerCode::normalizeTalkerCode(talkerCode, languageCode);
+ config->writeEntry("TalkerCode", talkerCode);
+
+ // Add TalkerID to configured list.
+ talkerIDsList.append(talkerID);
+ config->setGroup("General");
+ config->writeEntry("TalkerIDs", talkerIDsList.join(","));
+ config->sync();
+
+ // TODO: Now that we have modified the config, need a way to inform
+ // other apps, including KTTSMgr. As this routine is likely called
+ // when KTTSMgr is not running, is not a serious problem.
+
+ // Success!
+ delete loadedTalkerPlugIn;
+ return true;
+ }
+
+ // Plugin no longer needed.
+ delete loadedTalkerPlugIn;
+ }
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/kttsd/kttsd/talkermgr.h b/kttsd/kttsd/talkermgr.h
new file mode 100644
index 0000000..5b890ae
--- /dev/null
+++ b/kttsd/kttsd/talkermgr.h
@@ -0,0 +1,159 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Manages all the Talker (synth) plugins.
+ -------------------
+ Copyright:
+ (C) 2004-2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _TALKERMGR_H_
+#define _TALKERMGR_H_
+
+// Qt includes.
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <qptrlist.h>
+
+// KTTS includes.
+#include "talkercode.h"
+#include "pluginproc.h"
+
+class TalkerMgr: public QObject
+{
+public:
+
+ /**
+ * Constructor.
+ */
+ TalkerMgr(QObject *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor.
+ */
+ ~TalkerMgr();
+
+ /**
+ * Load all the configured plug ins populating loadedPlugIns
+ */
+ int loadPlugIns(KConfig* config);
+
+ /**
+ * Get a list of the talkers configured in KTTS.
+ * @return A QStringList of fully-specified talker codes, one
+ * for each talker user has configured.
+ */
+ QStringList getTalkers();
+
+ /**
+ * Returns a list of all the loaded plugins.
+ */
+ QPtrList<PlugInProc> getLoadedPlugIns();
+
+ /**
+ * Given a talker code, returns pointer to the closest matching plugin.
+ * @param talker The talker (language) code.
+ * @return Index to m_loadedPlugins array of Talkers.
+ *
+ * If a plugin has not been loaded to match the talker, returns the default
+ * plugin.
+ */
+ int talkerToPluginIndex(const QString& talker) const;
+
+ /**
+ * Given a talker code, returns pointer to the closest matching plugin.
+ * @param talker The talker (language) code.
+ * @return Pointer to closest matching plugin.
+ *
+ * If a plugin has not been loaded to match the talker, returns the default
+ * plugin.
+ */
+ PlugInProc* talkerToPlugin(const QString& talker) const;
+
+ /**
+ * Given a talker code, returns the parsed TalkerCode of the closest matching Talker.
+ * @param talker The talker (language) code.
+ * @return Parsed TalkerCode structure.
+ *
+ * If a plugin has not been loaded to match the talker, returns the default
+ * plugin.
+ *
+ * The returned TalkerCode is a copy and should be destroyed by caller.
+ *
+ * TODO: When picking a talker, %KTTSD will automatically determine if text contains
+ * markup and pick a talker that supports that markup, if available. This
+ * overrides all other attributes, i.e, it is treated as an automatic "top priority"
+ * attribute.
+ */
+ TalkerCode* talkerToTalkerCode(const QString& talker);
+
+ /**
+ * Given a Talker Code, returns the Talker ID of the talker that would speak
+ * a text job with that Talker Code.
+ * @param talkerCode Talker Code.
+ * @return Talker ID of the talker that would speak the text job.
+ */
+ QString talkerCodeToTalkerId(const QString& talkerCode);
+
+ /**
+ * Get the user's default talker.
+ * @return A fully-specified talker code.
+ *
+ * @see talkers
+ * @see getTalkers
+ */
+ QString userDefaultTalker() const;
+
+ /**
+ * Determine whether the currently-configured speech plugin supports a speech markup language.
+ * @param talker Code for the talker to do the speaking. Example "en".
+ * If NULL, defaults to the user's default talker.
+ * @param markupType The kttsd code for the desired speech markup language.
+ * @return True if the plugin currently configured for the indicated
+ * talker supports the indicated speech markup language.
+ * @see kttsdMarkupType
+ */
+ bool supportsMarkup(const QString& talker, const uint markupType) const;
+
+ /**
+ * Try to automatically configure a Talker in the specified language.
+ * @param langCode Two-letter language code.
+ * @param config KConfig to be updated if successful.
+ * @return True if successful.
+ *
+ * If successful, the KConfig rc file is updated but the talker has not been loaded.
+ */
+ bool autoconfigureTalker(const QString& langCode, KConfig* config);
+
+private:
+
+ /**
+ * Array of the loaded plug ins for different Talkers.
+ * Array of parsed Talker Codes for the plugins.
+ */
+ QPtrList<PlugInProc> m_loadedPlugIns;
+ QStringList m_loadedTalkerIds;
+ TalkerCode::TalkerCodeList m_loadedTalkerCodes;
+
+ /**
+ * Cache of talker codes and index of closest matching Talker.
+ */
+ mutable QMap<QString,int> m_talkerToPlugInCache;
+};
+
+#endif // _TALKERMGR_H_
diff --git a/kttsd/kttsd/threadedplugin.cpp b/kttsd/kttsd/threadedplugin.cpp
new file mode 100644
index 0000000..babc792
--- /dev/null
+++ b/kttsd/kttsd/threadedplugin.cpp
@@ -0,0 +1,282 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Converts a synchronous plugin into an asynchronous one.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <qevent.h>
+#include <qapplication.h>
+
+#include <kdebug.h>
+
+#include "speaker.h"
+#include "threadedplugin.h"
+
+/**
+* Constructor.
+*/
+ThreadedPlugIn::ThreadedPlugIn(PlugInProc* plugin,
+ QObject *parent /*= 0*/, const char *name /*= 0*/):
+ PlugInProc(parent, name),
+ QThread(),
+ m_plugin(plugin),
+ m_filename(QString::null),
+ m_requestExit(false),
+ m_supportsSynth(false)
+{
+ m_waitingStop = false;
+ m_state = psIdle;
+}
+
+/**
+* Destructor.
+*/
+ThreadedPlugIn::~ThreadedPlugIn()
+{
+ if (running())
+ {
+ // If thread is busy, try to stop it.
+ m_requestExit = true;
+ if (m_threadRunningMutex.locked()) m_plugin->stopText();
+ m_action = paNone;
+ m_waitCondition.wakeOne();
+ wait(5000);
+ // If thread still active, stopText didn't succeed. Terminate the thread.
+ if (running())
+ {
+ terminate();
+ wait();
+ }
+ }
+ delete m_plugin;
+}
+
+/**
+* Initialize the speech plugin.
+*/
+bool ThreadedPlugIn::init(KConfig *config, const QString &configGroup)
+{
+ bool stat = m_plugin->init(config, configGroup);
+ m_supportsSynth = m_plugin->supportsSynth();
+ // Start thread running, which will immediately go to sleep.
+ start();
+ return stat;
+}
+
+/**
+* Say a text. Synthesize and audibilize it.
+* @param text The text to be spoken.
+*
+* If the plugin supports asynchronous operation, it should return immediately
+* and emit sayFinished signal when synthesis and audibilizing is finished.
+*/
+void ThreadedPlugIn::sayText(const QString &text)
+{
+ kdDebug() << "ThreadedPlugin::sayText running with text " << text << endl;
+ waitThreadNotBusy();
+ m_action = paSayText;
+ m_text = text;
+ m_state = psSaying;
+ m_waitCondition.wakeOne();
+}
+
+/**
+* Synthesize text into an audio file, but do not send to the audio device.
+* @param text The text to be synthesized.
+* @param suggestedFilename Full pathname of file to create. The plugin
+* may ignore this parameter and choose its own
+* filename. KTTSD will query the generated
+* filename using getFilename().
+*
+* If the plugin supports asynchronous operation, it should return immediately
+* and emit synthFinished signal when synthesis is completed.
+*/
+void ThreadedPlugIn::synthText(const QString &text, const QString &suggestedFilename)
+{
+ waitThreadNotBusy();
+ m_action = paSynthText;
+ m_text = text;
+ m_filename = suggestedFilename;
+ m_state = psSynthing;
+ m_waitCondition.wakeOne();
+}
+
+/**
+* Get the generated audio filename from synthText.
+* @return Name of the audio file the plugin generated.
+* Null if no such file.
+*
+* The plugin must not re-use the filename.
+*/
+QString ThreadedPlugIn::getFilename()
+{
+ return m_filename;
+}
+
+/**
+* Stop current operation (saying or synthesizing text).
+* This function only makes sense in asynchronus modes.
+* The plugin should return to the psIdle state.
+*/
+void ThreadedPlugIn::stopText()
+{
+ // If thread is busy, call stopText and wait for thread to stop being busy.
+ if (m_threadRunningMutex.locked())
+ {
+ kdDebug() << "ThreadedPlugIn::stopText:: calling m_plugin->stopText" << endl;
+ m_plugin->stopText();
+ // Set flag that will force state to idle once the plugin finishes.
+ m_waitingStop = true;
+// waitThreadNotBusy();
+ } else m_state = psIdle;
+}
+
+/**
+* Return the current state of the plugin.
+* This function only makes sense in asynchronous mode.
+* @return The pluginState of the plugin.
+*
+* @ref pluginState
+*/
+pluginState ThreadedPlugIn::getState()
+{
+ m_stateMutex.unlock();
+ bool emitStopped = false;
+ // If stopText was called, plugin may not have truly stopped, in which
+ // case, if has finally completed the operation, return idle state.
+ if (m_waitingStop)
+ {
+ if (m_state == psFinished) m_state = psIdle;
+ if (m_state == psIdle)
+ {
+ m_waitingStop = false;
+ emitStopped = true;
+ }
+ }
+ pluginState plugState = m_state;
+ m_stateMutex.unlock();
+ if (emitStopped) emit stopped();
+ return plugState;
+}
+
+/**
+* Acknowleges a finished state and resets the plugin state to psIdle.
+*
+* If the plugin is not in state psFinished, nothing happens.
+* The plugin may use this call to do any post-processing cleanup,
+* for example, blanking the stored filename (but do not delete the file).
+* Calling program should call getFilename prior to ackFinished.
+*/
+void ThreadedPlugIn::ackFinished()
+{
+ // Since plugin should not be running, don't bother with Mutex here.
+ if (m_state == psFinished) m_state = psIdle;
+ m_filename = QString::null;
+}
+
+/**
+* Returns True if the plugin supports asynchronous processing,
+* i.e., returns immediately from sayText or synthText.
+* @return True if this plugin supports asynchronous processing.
+*
+* Since this is a threaded wrapper, return True.
+*/
+bool ThreadedPlugIn::supportsAsync() { return true; }
+
+/**
+* Returns True if the plugin supports synthText method,
+* i.e., is able to synthesize text to a sound file without
+* audibilizing the text.
+* @return True if this plugin supports synthText method.
+*/
+bool ThreadedPlugIn::supportsSynth() { return m_supportsSynth; }
+
+/**
+* Waits for the thread to go to sleep.
+*/
+void ThreadedPlugIn::waitThreadNotBusy()
+{
+ m_threadRunningMutex.lock();
+ m_threadRunningMutex.unlock();
+}
+
+/**
+* Base function, where the thread will start.
+*/
+void ThreadedPlugIn::run()
+{
+ while (!m_requestExit)
+ {
+
+ if (!m_threadRunningMutex.locked()) m_threadRunningMutex.lock();
+ // Go to sleep until asked to do something.
+ // Mutex unlocks as we go to sleep and locks as we wake up.
+ kdDebug() << "ThreadedPlugIn::run going to sleep." << endl;
+ m_waitCondition.wait(&m_threadRunningMutex);
+ kdDebug() << "ThreadedPlugIn::run waking up." << endl;
+ // Woken up.
+ // See if we've been told to exit.
+ if (m_requestExit)
+ {
+ m_threadRunningMutex.unlock();
+ return;
+ }
+
+ // Branch on requested action.
+ switch( m_action )
+ {
+ case paNone: break;
+
+ case paSayText:
+ {
+ m_stateMutex.lock();
+ m_state = psSaying;
+ m_stateMutex.unlock();
+ kdDebug() << "ThreadedPlugIn::run calling sayText" << endl;
+ m_plugin->sayText(m_text);
+ kdDebug() << "ThreadedPlugIn::run back from sayText" << endl;
+ m_stateMutex.lock();
+ if (m_state == psSaying) m_state = psFinished;
+ m_stateMutex.unlock();
+ emit sayFinished();
+ break;
+ }
+
+ case paSynthText:
+ {
+ m_stateMutex.lock();
+ m_state = psSynthing;
+ m_stateMutex.unlock();
+ QString filename = m_filename;
+ m_filename = QString::null;
+ kdDebug() << "ThreadedPlugIn::run calling synthText" << endl;
+ m_plugin->synthText(m_text, filename);
+ kdDebug() << "ThreadedPlugIn::run back from synthText" << endl;
+ m_filename = m_plugin->getFilename();
+ m_stateMutex.lock();
+ if (m_state == psSynthing) m_state = psFinished;
+ m_stateMutex.unlock();
+ emit synthFinished();
+ break;
+ }
+ }
+ }
+ if (m_threadRunningMutex.locked()) m_threadRunningMutex.unlock();
+}
diff --git a/kttsd/kttsd/threadedplugin.h b/kttsd/kttsd/threadedplugin.h
new file mode 100644
index 0000000..bc9ed6a
--- /dev/null
+++ b/kttsd/kttsd/threadedplugin.h
@@ -0,0 +1,200 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Converts a synchronous plugin into an asynchronous one.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _THREADEDPLUGIN_H_
+#define _THREADEDPLUGIN_H_
+
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+
+#include "pluginproc.h"
+
+class Speaker;
+
+class ThreadedPlugIn : public PlugInProc, public QThread
+{
+ public:
+ enum pluginAction
+ {
+ paNone = 0,
+ paSayText = 1,
+ paSynthText = 2
+ };
+
+ /**
+ * Constructor.
+ */
+ ThreadedPlugIn(PlugInProc* plugin, QObject *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor.
+ */
+ virtual ~ThreadedPlugIn();
+
+ /**
+ * Initializate the speech plugin.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Say a text. Synthesize and audibilize it.
+ * @param text The text to be spoken.
+ *
+ * If the plugin supports asynchronous operation, it should return immediately
+ * and emit sayFinished signal when synthesis and audibilizing is finished.
+ */
+ virtual void sayText(const QString &text);
+
+ /**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately
+ * and emit synthFinished signal when synthesis is completed.
+ */
+ virtual void synthText(const QString &text, const QString &suggestedFilename);
+
+ /**
+ * Get the generated audio filename from synthText.
+ * @return Name of the audio file the plugin generated.
+ * Null if no such file.
+ *
+ * The plugin must not re-use the filename.
+ */
+ virtual QString getFilename();
+
+ /**
+ * Stop current operation (saying or synthesizing text).
+ * This function only makes sense in asynchronus modes.
+ * The plugin should return to the psIdle state.
+ */
+ virtual void stopText();
+
+ /**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @ref pluginState
+ */
+ virtual pluginState getState();
+
+ /**
+ * Acknowleges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Returns True if the plugin supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ */
+ virtual bool supportsSynth();
+
+ protected:
+ /**
+ * Base function, where the thread will start.
+ */
+ virtual void run();
+
+ private:
+ /**
+ * Waits for the thread to go to sleep.
+ */
+ void waitThreadNotBusy();
+
+ /**
+ * The plugin we wrap.
+ */
+ PlugInProc* m_plugin;
+
+ /**
+ * An action requested of the plugin.
+ */
+ pluginAction m_action;
+
+ /**
+ * A text buffer to go with an action (if applicable).
+ */
+ QString m_text;
+
+ /**
+ * Current state of the plugin.
+ */
+ volatile pluginState m_state;
+
+ /**
+ * Mutext for accessing state variable.
+ */
+ QMutex m_stateMutex;
+
+ /**
+ * True when stopText was called but the plugin did not stop.
+ */
+ bool m_waitingStop;
+
+ /**
+ * Locked when thread is running.
+ */
+ QMutex m_threadRunningMutex;
+
+ /**
+ * Filename for generated synthesized text.
+ */
+ QString m_filename;
+
+ /**
+ * Thread wait condition.
+ */
+ QWaitCondition m_waitCondition;
+
+ /**
+ * Thread exit flag.
+ */
+ volatile bool m_requestExit;
+
+ /**
+ * Whether wrapped plugin supports separate synthesis.
+ */
+ bool m_supportsSynth;
+};
+
+#endif // _THREADEDPLUGIN_H_
diff --git a/kttsd/kttsjobmgr/Makefile.am b/kttsd/kttsjobmgr/Makefile.am
new file mode 100644
index 0000000..98727e0
--- /dev/null
+++ b/kttsd/kttsjobmgr/Makefile.am
@@ -0,0 +1,40 @@
+# Include paths. INCLUDES is maintained by KDevelop, AM_CPPFLAGS is the preferred variable,
+# so keep them synchronized.
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(KTTS_KSPEECH_INCLUDE) \
+ $(all_includes)
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# KPART SECTION
+#########################################################################
+# This is the kpart that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+kde_module_LTLIBRARIES = libkttsjobmgrpart.la
+
+kspeech_DIR = $(KTTS_KSPEECH_DIR)
+kspeechsink_DIR = $(KTTS_KSPEECH_DIR)
+
+# The source, library search path, and link libraries.
+libkttsjobmgrpart_la_SOURCES = \
+ kspeech.stub kspeechsink.skel \
+ kttsjobmgr.cpp
+
+libkttsjobmgrpart_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries) $(KDE_PLUGIN)
+libkttsjobmgrpart_la_LIBADD = \
+ $(top_builddir)/kttsd/libkttsd/libkttsd.la \
+ $(LIB_KFILE) $(LIBVM) $(LIB_KPARTS)
+
+# Header files not to be installed.
+noinst_HEADERS =
+
+# Install desktop file to standard services directory.
+kde_services_DATA = kttsjobmgr.desktop
+
+# This rc file should never have been installed.
+# createGUI not supported within a KCModule.
+install-data-local:
+ rm -f $(DESTDIR)$(kde_datadir)/kttsjobmgr/kttsjobmgrui.rc
diff --git a/kttsd/kttsjobmgr/kttsjobmgr.cpp b/kttsd/kttsjobmgr/kttsjobmgr.cpp
new file mode 100644
index 0000000..2b2e1c5
--- /dev/null
+++ b/kttsd/kttsjobmgr/kttsjobmgr.cpp
@@ -0,0 +1,1023 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ A KPart to display running jobs in KTTSD and permit user to stop, rewind,
+ advance, change Talker, etc.
+ -------------------
+ Copyright : (C) 2004,2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// QT includes.
+#include <qvbox.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qsplitter.h>
+#include <qclipboard.h>
+#include <qpushbutton.h>
+#include <qobjectlist.h>
+#include <qwhatsthis.h>
+
+#include <qmime.h>
+
+// KDE includes.
+#include <kinstance.h>
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kencodingfiledialog.h>
+#include <kapplication.h>
+#include <kinputdialog.h>
+#include <ktextedit.h>
+
+// KTTS includes.
+#include "kspeech.h"
+#include "talkercode.h"
+#include "selecttalkerdlg.h"
+#include "kttsjobmgr.h"
+#include "kttsjobmgr.moc"
+
+K_EXPORT_COMPONENT_FACTORY( libkttsjobmgrpart, KttsJobMgrFactory )
+
+/**
+* We need one static instance of the factory for our C 'main'
+* function
+*/
+KInstance *KttsJobMgrFactory::s_instance = 0L;
+
+KttsJobMgrFactory::~KttsJobMgrFactory()
+{
+ if (s_instance)
+ {
+ delete s_instance->aboutData();
+ delete s_instance;
+ }
+
+ s_instance = 0;
+}
+
+QObject *KttsJobMgrFactory::createObject(QObject *parent, const char *name, const char*,
+ const QStringList& )
+{
+ QObject *obj = new KttsJobMgrPart((QWidget*)parent, name);
+ emit objectCreated(obj);
+ return obj;
+}
+
+KInstance *KttsJobMgrFactory::instance()
+{
+ if ( !s_instance )
+ s_instance = new KInstance( aboutData() );
+ return s_instance;
+}
+
+KAboutData *KttsJobMgrFactory::aboutData()
+{
+ KAboutData *about = new KAboutData("kttsjobmgr", I18N_NOOP("KttsJobMgr"), "1.99");
+ return about;
+}
+
+KttsJobMgrPart::KttsJobMgrPart(QWidget *parent, const char *name) :
+ DCOPStub("kttsd", "KSpeech"),
+ DCOPObject("kttsjobmgr_kspeechsink"),
+ KParts::ReadOnlyPart(parent, name)
+{
+ // Initialize some variables.
+ m_selectOnTextSet = false;
+ m_buttonBox = 0;
+
+ setInstance(KttsJobMgrFactory::instance());
+
+ // All the ktts components use the same catalogue.
+ KGlobal::locale()->insertCatalogue("kttsd");
+
+ // Create a QVBox to host everything.
+ QVBox* vBox = new QVBox(parent);
+ vBox->setMargin(6);
+
+ // Create a splitter to contain the Job List View and the current sentence.
+ QSplitter* splitter = new QSplitter(vBox);
+ splitter->setOrientation(QSplitter::Vertical);
+
+ // Create Job List View widget.
+ m_jobListView = new KListView(splitter, "joblistview");
+ m_jobListView->setSelectionModeExt(KListView::Single);
+ m_jobListView->addColumn(i18n("Job Num"));
+ m_jobListView->addColumn(i18n("Owner"));
+ m_jobListView->addColumn(i18n("Talker ID"));
+ m_jobListView->addColumn(i18n("State"));
+ m_jobListView->addColumn(i18n("Position"));
+ m_jobListView->addColumn(i18n("Sentences"));
+ m_jobListView->addColumn(i18n("Part Num"));
+ m_jobListView->addColumn(i18n("Parts"));
+
+ // Do not sort the list.
+ m_jobListView->setSorting(-1);
+
+ QString jobListViewWT = i18n(
+ "<p>These are all the text jobs. The <b>State</b> column "
+ "may be:"
+ "<ul>"
+ "<li><b>Queued</b> - the job is waiting and will not be spoken until its state "
+ "is changed to <b>Waiting</b> by clicking the <b>Resume</b> or <b>Restart</b> buttons.</li>"
+ "<li><b>Waiting</b> - the job is ready to be spoken. It will be spoken when the jobs "
+ "preceding it in the list have finished.</li>"
+ "<li><b>Speaking</b> - the job is speaking. The <b>Position</b> column shows the current "
+ "sentence of the job being spoken. You may pause a speaking job by clicking the "
+ "<b>Hold</b> button.</li>"
+ "<li><b>Paused</b> - the job is currently paused. Paused jobs prevent jobs below them "
+ "from speaking. Use the <b>Resume</b> or <b>Restart</b> buttons to resume speaking the "
+ "job, or click <b>Later</b> to move the job down in the list.</li>"
+ "<li><b>Finished</b> - the job has finished speaking. When a second job finishes, "
+ "this one will be deleted. You may click <b>Restart</b> to repeat the job.</li>"
+ "</ul>"
+ "<em>Note</em>: Messages, Warnings, and Screen Reader Output do not appear in this list. "
+ "See the Handbook for more information."
+ "</p>");
+ QWhatsThis::add(m_jobListView, jobListViewWT);
+
+ // splitter->setResizeMode(m_jobListView, QSplitter::Stretch);
+
+ // Create a VBox to hold buttons and current sentence.
+ QVBox* bottomBox = new QVBox(splitter);
+
+ // Create a box to hold buttons.
+ m_buttonBox = new QVBox(bottomBox);
+ m_buttonBox->setSpacing(6);
+
+ // Create 3 HBoxes to host buttons.
+ QHBox* hbox1 = new QHBox(m_buttonBox);
+ hbox1->setSpacing(6);
+ QHBox* hbox2 = new QHBox(m_buttonBox);
+ hbox2->setSpacing(6);
+ QHBox* hbox3 = new QHBox(m_buttonBox);
+ hbox3->setSpacing(6);
+
+ // Do not let button box stretch vertically.
+ m_buttonBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+
+ // All the buttons with "job_" at start of their names will be enabled/disabled when a job is
+ // selected in the Job List View.
+ // All the buttons with "part_" at the start of their names will be enabled/disabled when a
+ // job is selected in the Job List View that has multiple parts.
+
+ QPushButton* btn;
+ QString wt;
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("stop", KIcon::Small, 0, true),
+ i18n("Hold"), hbox1, "job_hold");
+ wt = i18n(
+ "<p>Changes a job to Paused state. If currently speaking, the job stops speaking. "
+ "Paused jobs prevent jobs that follow them from speaking, so either click "
+ "<b>Resume</b> to make the job speakable, or click <b>Later</b> to move it "
+ "down in the list.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_hold()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("exec", KIcon::Small, 0, true),
+ i18n("Resume"), hbox1, "job_resume");
+ wt = i18n(
+ "<p>Resumes a paused job or changes a Queued job to Waiting. If the job is the "
+ "top speakable job in the list, it begins speaking.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_resume()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("redo", KIcon::Small, 0, true),
+ i18n("R&estart"), hbox1, "job_restart");
+ wt = i18n(
+ "<p>Rewinds a job to the beginning and changes its state to Waiting. If the job "
+ "is the top speakable job in the list, it begins speaking.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_restart()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("edittrash", KIcon::Small, 0, true),
+ i18n("Re&move"), hbox1, "job_remove");
+ wt = i18n(
+ "<p>Deletes the job. If it is currently speaking, it stops speaking. The next "
+ "speakable job in the list begins speaking.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_remove()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("down", KIcon::Small, 0, true),
+ i18n("&Later"), hbox1, "job_later");
+ wt = i18n(
+ "<p>Moves a job downward in the list so that it will be spoken later. If the job "
+ "is currently speaking, its state changes to Paused.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_move()));
+
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("2leftarrow", KIcon::Small, 0, true),
+ i18n("Pre&vious Part"), hbox2, "part_prevpart");
+ wt = i18n(
+ "<p>Rewinds a multi-part job to the previous part.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_prev_par()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("1leftarrow", KIcon::Small, 0, true),
+ i18n("&Previous Sentence"), hbox2, "job_prevsentence");
+ wt = i18n(
+ "<p>Rewinds a job to the previous sentence.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_prev_sen()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("1rightarrow", KIcon::Small, 0, true),
+ i18n("&Next Sentence"), hbox2, "job_nextsentence");
+ wt = i18n(
+ "<p>Advances a job to the next sentence.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_next_sen()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("2rightarrow", KIcon::Small, 0, true),
+ i18n("Ne&xt Part"), hbox2, "part_nextpart");
+ wt = i18n(
+ "<p>Advances a multi-part job to the next part.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_next_par()));
+
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("klipper", KIcon::Small, 0, true),
+ i18n("&Speak Clipboard"), hbox3, "speak_clipboard");
+ wt = i18n(
+ "<p>Queues the current contents of the clipboard for speaking and sets its state "
+ "to Waiting. If the job is the topmost in the list, it begins speaking. "
+ "The job will be spoken by the topmost Talker in the <b>Talkers</b> tab.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_speak_clipboard()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("fileopen", KIcon::Small, 0, true),
+ i18n("Spea&k File"), hbox3, "speak_file");
+ wt = i18n(
+ "<p>Prompts you for a file name and queues the contents of the file for speaking. "
+ "You must click the <b>Resume</b> button before the job will be speakable. "
+ "The job will be spoken by the topmost Talker in the <b>Talkers</b> tab.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_speak_file()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("translate", KIcon::Small, 0, true),
+ i18n("Change Talker"), hbox3, "job_changetalker");
+ wt = i18n(
+ "<p>Prompts you with a list of your configured Talkers from the <b>Talkers</b> tab. "
+ "The job will be spoken using the selected Talker.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_job_change_talker()));
+ btn = new QPushButton(KGlobal::iconLoader()->loadIconSet("reload_page", KIcon::Small, 0, true),
+ i18n("&Refresh"), hbox3, "refresh");
+ wt = i18n(
+ "<p>Refresh the list of jobs.</p>");
+ QWhatsThis::add(btn, wt);
+ connect (btn, SIGNAL(clicked()), this, SLOT(slot_refresh()));
+
+ // Disable job buttons until a job is selected.
+ enableJobActions(false);
+ enableJobPartActions(false);
+
+ // Create a VBox for the current sentence and sentence label.
+ QVBox* sentenceVBox = new QVBox(bottomBox);
+
+ // Create a label for current sentence.
+ QLabel* currentSentenceLabel = new QLabel(sentenceVBox);
+ currentSentenceLabel->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+ currentSentenceLabel->setText(i18n("Current Sentence"));
+
+ // Create a box to contain the current sentence.
+ m_currentSentence = new KTextEdit(sentenceVBox);
+ m_currentSentence->setReadOnly(true);
+ m_currentSentence->setWordWrap(QTextEdit::WidgetWidth);
+ m_currentSentence->setWrapPolicy(QTextEdit::AtWordOrDocumentBoundary);
+ m_currentSentence->setHScrollBarMode(QScrollView::AlwaysOff);
+ m_currentSentence->setVScrollBarMode(QScrollView::Auto);
+ wt = i18n(
+ "<p>The text of the sentence currently speaking.</p>");
+ QWhatsThis::add(m_currentSentence, wt);
+
+ // Set the main widget for the part.
+ setWidget(vBox);
+
+ connect(m_jobListView, SIGNAL(selectionChanged(QListViewItem* )),
+ this, SLOT(slot_selectionChanged(QListViewItem* )));
+
+ // Fill the Job List View.
+ refreshJobListView();
+ // Select first item (if any).
+ autoSelectInJobListView();
+
+ // Connect DCOP Signals emitted by KTTSD to our own DCOP methods.
+ connectDCOPSignal("kttsd", "KSpeech",
+ "kttsdStarted()",
+ "kttsdStarted()",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "markerSeen(QCString,QString)",
+ "markerSeen(QCString,QString)",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "sentenceStarted(QCString,uint,uint)",
+ "sentenceStarted(QCString,uint,uint)",
+ false);
+ connectDCOPSignal(0, 0,
+ "sentenceFinished(QCString,uint,uint)",
+ "sentenceFinished(QCString,uint,uint)",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textSet(QCString,uint)",
+ "textSet(QCString,uint)",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textStarted(QCString,uint)",
+ "textStarted(QCString,uint)",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textFinished(QCString,uint)",
+ "textFinished(QCString,uint)",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textStopped(QCString,uint)",
+ "textStopped(QCString,uint)",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textPaused(QCString,uint)",
+ "textPaused(QCString,uint)",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textResumed(QCString,uint)",
+ "textResumed(QCString,uint)",
+ false);
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textRemoved(QCString,uint)",
+ "textRemoved(QCString,uint)",
+ false);
+
+ m_extension = new KttsJobMgrBrowserExtension(this);
+
+ m_jobListView->show();
+
+ // Divide splitter in half. ListView gets half. Buttons and Current Sentence get half.
+ int halfSplitterSize = splitter->height()/2;
+ QValueList<int> splitterSizes;
+ splitterSizes.append(halfSplitterSize);
+ splitterSizes.append(halfSplitterSize);
+ splitter->setSizes(splitterSizes);
+}
+
+KttsJobMgrPart::~KttsJobMgrPart()
+{
+ closeURL();
+}
+
+bool KttsJobMgrPart::openFile()
+{
+ return true;
+}
+
+bool KttsJobMgrPart::closeURL()
+{
+ return true;
+}
+
+/**
+* This slot is connected to the Job List View selectionChanged signal.
+*/
+void KttsJobMgrPart::slot_selectionChanged(QListViewItem*)
+{
+ // Enable job buttons.
+ enableJobActions(true);
+ enableJobPartActions((getCurrentJobPartCount() > 1));
+}
+
+/**
+* Slots connected to buttons.
+*/
+void KttsJobMgrPart::slot_job_hold()
+{
+ uint jobNum = getCurrentJobNum();
+ if (jobNum)
+ {
+ pauseText(jobNum);
+ refreshJob(jobNum);
+ }
+}
+
+void KttsJobMgrPart::slot_job_resume()
+{
+ uint jobNum = getCurrentJobNum();
+ if (jobNum)
+ {
+ resumeText(jobNum);
+ refreshJob(jobNum);
+ }
+}
+
+void KttsJobMgrPart::slot_job_restart()
+{
+ uint jobNum = getCurrentJobNum();
+ // kdDebug() << "KttsJobMgrPart::slot_job_restart: jobNum = " << jobNum << endl;
+ if (jobNum)
+ {
+ startText(jobNum);
+ refreshJob(jobNum);
+ }
+}
+
+void KttsJobMgrPart::slot_job_prev_par()
+{
+ uint jobNum = getCurrentJobNum();
+ if (jobNum)
+ {
+ // Get current part number.
+ uint partNum = jumpToTextPart(0, jobNum);
+ if (partNum > 1) jumpToTextPart(--partNum, jobNum);
+ refreshJob(jobNum);
+ }
+}
+
+void KttsJobMgrPart::slot_job_prev_sen()
+{
+ uint jobNum = getCurrentJobNum();
+ if (jobNum)
+ {
+ moveRelTextSentence(-1, jobNum);
+ refreshJob(jobNum);
+ }
+}
+
+void KttsJobMgrPart::slot_job_next_sen()
+{
+ uint jobNum = getCurrentJobNum();
+ if (jobNum)
+ {
+ moveRelTextSentence(1, jobNum);
+ refreshJob(jobNum);
+ }
+}
+
+void KttsJobMgrPart::slot_job_next_par()
+{
+ uint jobNum = getCurrentJobNum();
+ if (jobNum)
+ {
+ // Get current part number.
+ uint partNum = jumpToTextPart(0, jobNum);
+ jumpToTextPart(++partNum, jobNum);
+ refreshJob(jobNum);
+ }
+}
+
+void KttsJobMgrPart::slot_job_remove()
+{
+ uint jobNum = getCurrentJobNum();
+ if (jobNum)
+ {
+ removeText(jobNum);
+ m_currentSentence->clear();
+ }
+}
+
+void KttsJobMgrPart::slot_job_move()
+{
+ uint jobNum = getCurrentJobNum();
+ if (jobNum)
+ {
+ moveTextLater(jobNum);
+ refreshJobListView();
+ // Select the job we just moved.
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item) m_jobListView->setSelected(item, true);
+ }
+}
+
+void KttsJobMgrPart::slot_job_change_talker()
+{
+ QListViewItem* item = m_jobListView->selectedItem();
+ if (item)
+ {
+ QString talkerID = item->text(jlvcTalkerID);
+ QStringList talkerIDs = m_talkerCodesToTalkerIDs.values();
+ int ndx = talkerIDs.findIndex(talkerID);
+ QString talkerCode;
+ if (ndx >= 0) talkerCode = m_talkerCodesToTalkerIDs.keys()[ndx];
+ SelectTalkerDlg dlg(widget(), "selecttalkerdialog", i18n("Select Talker"), talkerCode, true);
+ int dlgResult = dlg.exec();
+ if (dlgResult != KDialogBase::Accepted) return;
+ talkerCode = dlg.getSelectedTalkerCode();
+ int jobNum = item->text(jlvcJobNum).toInt();
+ changeTextTalker(talkerCode, jobNum);
+ refreshJob(jobNum);
+ }
+}
+
+void KttsJobMgrPart::slot_speak_clipboard()
+{
+ // Get the clipboard object.
+ QClipboard *cb = kapp->clipboard();
+
+
+ // Copy text from the clipboard.
+ QString text;
+ QMimeSource* data = cb->data();
+ if (data)
+ {
+ if (data->provides("text/html"))
+ {
+ if (supportsMarkup(NULL, KSpeech::mtHtml))
+ {
+ QByteArray d = data->encodedData("text/html");
+ text = QString(d);
+ }
+ }
+ if (data->provides("text/ssml"))
+ {
+ if (supportsMarkup(NULL, KSpeech::mtSsml))
+ {
+ QByteArray d = data->encodedData("text/ssml");
+ text = QString(d);
+ }
+ }
+ }
+ if (text.isEmpty())
+ text = cb->text();
+
+ // Speak it.
+ if ( !text.isEmpty() )
+ {
+ uint jobNum = setText(text, NULL);
+ // kdDebug() << "KttsJobMgrPart::slot_speak_clipboard: started jobNum " << jobNum << endl;
+ startText(jobNum);
+ // Set flag so that the job we just created will be selected when textSet signal is received.
+ m_selectOnTextSet = true;
+ }
+}
+
+void KttsJobMgrPart::slot_speak_file()
+{
+ KEncodingFileDialog dlg;
+ KEncodingFileDialog::Result result = dlg.getOpenFileNameAndEncoding();
+ if (result.fileNames.count() == 1)
+ {
+ // kdDebug() << "KttsJobMgr::slot_speak_file: calling setFile with filename " <<
+ // result.fileNames[0] << " and encoding " << result.encoding << endl;
+ setFile(result.fileNames[0], NULL, result.encoding);
+ }
+}
+
+void KttsJobMgrPart::slot_refresh()
+{
+ // Clear TalkerID cache.
+ m_talkerCodesToTalkerIDs.clear();
+ // Get current job number.
+ uint jobNum = getCurrentJobNum();
+ refreshJobListView();
+ // Select the previously-selected job.
+ if (jobNum)
+ {
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item) m_jobListView->setSelected(item, true);
+ }
+}
+
+
+/**
+* Convert a KTTSD job state integer into a display string.
+* @param state KTTSD job state
+* @return Display string for the state.
+*/
+QString KttsJobMgrPart::stateToStr(int state)
+{
+ switch( state )
+ {
+ case KSpeech::jsQueued: return i18n("Queued");
+ case KSpeech::jsSpeakable: return i18n("Waiting");
+ case KSpeech::jsSpeaking: return i18n("Speaking");
+ case KSpeech::jsPaused: return i18n("Paused");
+ case KSpeech::jsFinished: return i18n("Finished");
+ default: return i18n("Unknown");
+ }
+}
+
+/**
+* Get the Job Number of the currently-selected job in the Job List View.
+* @return Job Number of currently-selected job.
+* 0 if no currently-selected job.
+*/
+uint KttsJobMgrPart::getCurrentJobNum()
+{
+ uint jobNum = 0;
+ QListViewItem* item = m_jobListView->selectedItem();
+ if (item)
+ {
+ QString jobNumStr = item->text(jlvcJobNum);
+ jobNum = jobNumStr.toUInt(0, 10);
+ }
+ return jobNum;
+}
+
+/**
+* Get the number of parts in the currently-selected job in the Job List View.
+* @return Number of parts in currently-selected job.
+* 0 if no currently-selected job.
+*/
+int KttsJobMgrPart::getCurrentJobPartCount()
+{
+ int partCount = 0;
+ QListViewItem* item = m_jobListView->selectedItem();
+ if (item)
+ {
+ QString partCountStr = item->text(jlvcPartCount);
+ partCount = partCountStr.toUInt(0, 10);
+ }
+ return partCount;
+}
+
+/**
+* Given a Job Number, returns the Job List View item containing the job.
+* @param jobNum Job Number.
+* @return QListViewItem containing the job or 0 if not found.
+*/
+QListViewItem* KttsJobMgrPart::findItemByJobNum(const uint jobNum)
+{
+ return m_jobListView->findItem(QString::number(jobNum), jlvcJobNum);
+}
+
+/**
+* Refresh display of a single job in the JobListView.
+* @param jobNum Job Number.
+*/
+void KttsJobMgrPart::refreshJob(uint jobNum)
+{
+ QByteArray jobInfo = getTextJobInfo(jobNum);
+ QDataStream stream(jobInfo, IO_ReadOnly);
+ int state;
+ QCString appId;
+ QString talker;
+ int seq;
+ int sentenceCount;
+ int partNum;
+ int partCount;
+ stream >> state;
+ stream >> appId;
+ stream >> talker;
+ stream >> seq;
+ stream >> sentenceCount;
+ stream >> partNum;
+ stream >> partCount;
+ QString talkerID = cachedTalkerCodeToTalkerID(talker);
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item)
+ {
+ item->setText(jlvcTalkerID, talkerID);
+ item->setText(jlvcState, stateToStr(state));
+ item->setText(jlvcPosition, QString::number(seq));
+ item->setText(jlvcSentences, QString::number(sentenceCount));
+ item->setText(jlvcPartNum, QString::number(partNum));
+ item->setText(jlvcPartCount, QString::number(partCount));
+ }
+}
+
+/**
+* Fill the Job List View.
+*/
+void KttsJobMgrPart::refreshJobListView()
+{
+ // kdDebug() << "KttsJobMgrPart::refreshJobListView: Running" << endl;
+ m_jobListView->clear();
+ enableJobActions(false);
+ enableJobPartActions(false);
+ QString jobNumbers = getTextJobNumbers();
+ // kdDebug() << "jobNumbers: " << jobNumbers << endl;
+ QStringList jobNums = QStringList::split(",", jobNumbers);
+ QListViewItem* lastItem = 0;
+ QStringList::ConstIterator endJobNums(jobNums.constEnd());
+ for( QStringList::ConstIterator it = jobNums.constBegin(); it != endJobNums; ++it)
+ {
+ QString jobNumStr = *it;
+ // kdDebug() << "jobNumStr: " << jobNumStr << endl;
+ uint jobNum = jobNumStr.toUInt(0, 10);
+ QByteArray jobInfo = getTextJobInfo(jobNum);
+ QDataStream stream(jobInfo, IO_ReadOnly);
+ int state;
+ QCString appId;
+ QString talkerCode;
+ int seq;
+ int sentenceCount;
+ int partNum;
+ int partCount;
+ stream >> state;
+ stream >> appId;
+ stream >> talkerCode;
+ stream >> seq;
+ stream >> sentenceCount;
+ stream >> partNum;
+ stream >> partCount;
+ QString talkerID = cachedTalkerCodeToTalkerID(talkerCode);
+ // Append to list.
+ if (lastItem)
+ lastItem = new QListViewItem(m_jobListView, lastItem, jobNumStr, appId, talkerID,
+ stateToStr(state), QString::number(seq), QString::number(sentenceCount),
+ QString::number(partNum), QString::number(partCount));
+ else
+ lastItem = new QListViewItem(m_jobListView, jobNumStr, appId, talkerID,
+ stateToStr(state), QString::number(seq), QString::number(sentenceCount),
+ QString::number(partNum), QString::number(partCount));
+ }
+}
+
+/**
+* If nothing selected in Job List View and list not empty, select top item.
+* If nothing selected and list is empty, disable job buttons.
+*/
+void KttsJobMgrPart::autoSelectInJobListView()
+{
+ // If something selected, nothing to do.
+ if (m_jobListView->selectedItem()) return;
+ // If empty, disable job buttons.
+ QListViewItem* item = m_jobListView->firstChild();
+ if (!item)
+ {
+ enableJobActions(false);
+ enableJobPartActions(false);
+ }
+ else
+ // Select first item. Should fire itemSelected event which will enable job buttons.
+ m_jobListView->setSelected(item, true);
+}
+
+/**
+* Return the Talker ID corresponding to a Talker Code, retrieving from cached list if present.
+* @param talkerCode Talker Code.
+* @return Talker ID.
+*/
+QString KttsJobMgrPart::cachedTalkerCodeToTalkerID(const QString& talkerCode)
+{
+ // If in the cache, return that.
+ if (m_talkerCodesToTalkerIDs.contains(talkerCode))
+ return m_talkerCodesToTalkerIDs[talkerCode];
+ else
+ {
+ // Otherwise, retrieve Talker ID from KTTSD and cache it.
+ QString talkerID = talkerCodeToTalkerId(talkerCode);
+ m_talkerCodesToTalkerIDs[talkerCode] = talkerID;
+ return talkerID;
+ }
+}
+
+/**
+* Enables or disables all the job-related buttons.
+* @param enable True to enable the job-related butons. False to disable.
+*/
+void KttsJobMgrPart::enableJobActions(bool enable)
+{
+ if (!m_buttonBox) return;
+ QObjectList *l = m_buttonBox->queryList( "QPushButton", "job_*", true, true );
+ QObjectListIt it( *l ); // iterate over the buttons
+ QObject *obj;
+
+ while ( (obj = it.current()) != 0 ) {
+ // for each found object...
+ ++it;
+ ((QPushButton*)obj)->setEnabled( enable );
+ }
+ delete l; // delete the list, not the objects
+
+ if (enable)
+ {
+ // Later button only enables if currently selected list item is not bottom of list.
+ QListViewItem* item = m_jobListView->selectedItem();
+ if (item)
+ {
+ bool enableLater = item->nextSibling();
+
+ l = m_buttonBox->queryList( "QPushButton", "job_later", false, true );
+ it = QObjectListIt( *l ); // iterate over the buttons
+ if ( (obj = it.current()) != 0 ) {
+ // for each found object...
+ ((QPushButton*)obj)->setEnabled( enableLater );
+ }
+ delete l; // delete the list, not the objects
+ }
+ }
+}
+
+/**
+* Enables or disables all the job part-related buttons.
+* @param enable True to enable the job par-related butons. False to disable.
+*/
+void KttsJobMgrPart::enableJobPartActions(bool enable)
+{
+ if (!m_buttonBox) return;
+ QObjectList *l = m_buttonBox->queryList( "QPushButton", "part_*", true, true );
+ QObjectListIt it( *l ); // iterate over the buttons
+ QObject *obj;
+
+ while ( (obj = it.current()) != 0 ) {
+ // for each found object...
+ ++it;
+ ((QPushButton*)obj)->setEnabled( enable );
+ }
+ delete l; // delete the list, not the objects
+}
+
+/** DCOP Methods connected to DCOP Signals emitted by KTTSD. */
+
+/**
+* This signal is emitted when KTTSD starts or restarts after a call to reinit.
+*/
+ASYNC KttsJobMgrPart::kttsdStarted() { slot_refresh(); }
+
+/**
+* This signal is emitted when the speech engine/plugin encounters a marker in the text.
+* @param appId DCOP application ID of the application that queued the text.
+* @param markerName The name of the marker seen.
+* @see markers
+*/
+ASYNC KttsJobMgrPart::markerSeen(const QCString&, const QString&)
+{
+}
+
+/**
+ * This signal is emitted whenever a sentence begins speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ * @see getTextCount
+ */
+ASYNC KttsJobMgrPart::sentenceStarted(const QCString&, const uint jobNum, const uint seq)
+{
+ // kdDebug() << "KttsJobMgrPart::sentencedStarted: jobNum = " << jobNum << " seq = " << seq << endl;
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item)
+ {
+ item->setText(jlvcState, stateToStr(KSpeech::jsSpeaking));
+ item->setText(jlvcPosition, QString::number(seq));
+ m_currentSentence->setText(getTextJobSentence(jobNum, seq));
+ }
+}
+
+/**
+* This signal is emitted when a sentence has finished speaking.
+* @param appId DCOP application ID of the application that queued the text.
+* @param jobNum Job number of the text job.
+* @param seq Sequence number of the text.
+* @see getTextCount
+*/
+ASYNC KttsJobMgrPart::sentenceFinished(const QCString& /*appId*/, const uint /*jobNum*/, const uint /*seq*/)
+{
+ // kdDebug() << "KttsJobMgrPart::sentencedFinished: jobNum = " << jobNum << endl;
+/*
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item)
+ {
+ item->setText(jlvcState, stateToStr(KSpeech::jsSpeaking));
+ }
+*/
+}
+
+/**
+* This signal is emitted whenever a new text job is added to the queue.
+* @param appId The DCOP senderId of the application that created the job.
+* @param jobNum Job number of the text job.
+*/
+ASYNC KttsJobMgrPart::textSet(const QCString&, const uint jobNum)
+{
+ QByteArray jobInfo = getTextJobInfo(jobNum);
+ QDataStream stream(jobInfo, IO_ReadOnly);
+ int state;
+ QCString appId;
+ QString talkerCode;
+ int seq;
+ int sentenceCount;
+ int partNum;
+ int partCount;
+ stream >> state;
+ stream >> appId;
+ stream >> talkerCode;
+ stream >> seq;
+ stream >> sentenceCount;
+ stream >> partNum;
+ stream >> partCount;
+ QString talkerID = cachedTalkerCodeToTalkerID(talkerCode);
+ QListViewItem* item = new QListViewItem(m_jobListView, m_jobListView->lastItem(),
+ QString::number(jobNum), appId, talkerID,
+ stateToStr(state), QString::number(seq), QString::number(sentenceCount),
+ QString::number(partNum), QString::number(partCount));
+ // Should we select this job?
+ if (m_selectOnTextSet)
+ {
+ m_jobListView->setSelected(item, true);
+ m_selectOnTextSet = false;
+ }
+ // If a job not already selected, select this one.
+ autoSelectInJobListView();
+}
+
+/**
+* This signal is emitted whenever a new part is appended to a text job.
+* @param appId The DCOP senderId of the application that created the job.
+* @param jobNum Job number of the text job.
+* @param partNum Part number of the new part. Parts are numbered starting
+* at 1.
+*/
+ASYNC KttsJobMgrPart::textAppended(const QCString& appId, const uint jobNum, const int /*partNum*/)
+{
+ textSet(appId, jobNum);
+}
+
+/**
+* This signal is emitted whenever speaking of a text job begins.
+* @param appId The DCOP senderId of the application that created the job.
+* @param jobNum Job number of the text job.
+*/
+ASYNC KttsJobMgrPart::textStarted(const QCString&, const uint jobNum)
+{
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item)
+ {
+ item->setText(jlvcState, stateToStr(KSpeech::jsSpeaking));
+ item->setText(jlvcPosition, "1");
+ }
+}
+
+/**
+* This signal is emitted whenever a text job is finished. The job has
+* been marked for deletion from the queue and will be deleted when another
+* job reaches the Finished state. (Only one job in the text queue may be
+* in state Finished at one time.) If @ref startText or @ref resumeText is
+* called before the job is deleted, it will remain in the queue for speaking.
+* @param appId The DCOP senderId of the application that created the job.
+* @param jobNum Job number of the text job.
+*/
+ASYNC KttsJobMgrPart::textFinished(const QCString&, const uint jobNum)
+{
+ // kdDebug() << "KttsJobMgrPart::textFinished: jobNum = " << jobNum << endl;
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item)
+ {
+ item->setText(jlvcState, stateToStr(KSpeech::jsFinished));
+ // Update sentence pointer, since signal may not be emitted for final CR.
+ refreshJob(jobNum);
+ }
+ m_currentSentence->setText(QString::null);
+}
+
+/**
+* This signal is emitted whenever a speaking text job stops speaking.
+* @param appId The DCOP senderId of the application that created the job.
+* @param jobNum Job number of the text job.
+*/
+ASYNC KttsJobMgrPart::textStopped(const QCString&, const uint jobNum)
+{
+ // kdDebug() << "KttsJobMgrPart::textStopped: jobNum = " << jobNum << endl;
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item)
+ {
+ item->setText(jlvcState, stateToStr(KSpeech::jsQueued));
+ item->setText(jlvcPosition, "1");
+ }
+}
+
+/**
+* This signal is emitted whenever a speaking text job is paused.
+* @param appId The DCOP senderId of the application that created the job.
+* @param jobNum Job number of the text job.
+*/
+ASYNC KttsJobMgrPart::textPaused(const QCString&, const uint jobNum)
+{
+ // kdDebug() << "KttsJobMgrPart::textPaused: jobNum = " << jobNum << endl;
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item)
+ {
+ item->setText(jlvcState, stateToStr(KSpeech::jsPaused));
+ }
+}
+
+/**
+* This signal is emitted when a text job, that was previously paused, resumes speaking.
+* @param appId The DCOP senderId of the application that created the job.
+* @param jobNum Job number of the text job.
+*/
+ASYNC KttsJobMgrPart::textResumed(const QCString&, const uint jobNum)
+{
+ QListViewItem* item = findItemByJobNum(jobNum);
+ if (item)
+ {
+ item->setText(jlvcState, stateToStr(KSpeech::jsSpeaking));
+ }
+}
+
+/**
+* This signal is emitted whenever a text job is deleted from the queue.
+* The job is no longer in the queue when this signal is emitted.
+* @param appId The DCOP senderId of the application that created the job.
+* @param jobNum Job number of the text job.
+*/
+ASYNC KttsJobMgrPart::textRemoved(const QCString&, const uint jobNum)
+{
+ QListViewItem* item = findItemByJobNum(jobNum);
+ delete item;
+ autoSelectInJobListView();
+}
+
+KttsJobMgrBrowserExtension::KttsJobMgrBrowserExtension(KttsJobMgrPart *parent)
+ : KParts::BrowserExtension(parent, "KttsJobMgrBrowserExtension")
+{
+}
+
+KttsJobMgrBrowserExtension::~KttsJobMgrBrowserExtension()
+{
+}
diff --git a/kttsd/kttsjobmgr/kttsjobmgr.desktop b/kttsd/kttsjobmgr/kttsjobmgr.desktop
new file mode 100644
index 0000000..f20da0c
--- /dev/null
+++ b/kttsd/kttsjobmgr/kttsjobmgr.desktop
@@ -0,0 +1,49 @@
+[Desktop Entry]
+Type=Service
+Name=kttsjobmgrpart
+Name[pt_BR]=Componente Ger. de Jobs do Ktts
+Name[tr]=Kttsjobmgrpart
+Comment=KDE Text-to-speech Job Manager
+Comment[bg]=Мениджър на задачите за синтез на глас
+Comment[ca]=Gestor de treballs de text a veu de KDE
+Comment[cs]=Správce úloh zvukové syntézy KDE
+Comment[da]=KDE's Tekst-til-tale Job-håndtering
+Comment[de]=KDE-Auftragsverwaltung für Sprachausgabe
+Comment[el]=KDE διαχειριστής εργασιών κειμένου-σε-ομιλία
+Comment[es]=Administrador de trabajos del sintetizador de texto a voz de KDE
+Comment[et]=KDE teksti kõneks muutmise tööde haldur
+Comment[eu]=KDE-ren testutik-hizketarako lan-kudeatzailea
+Comment[fa]=مدیر کار متن به گفتار KDE
+Comment[fi]=KDE Teksti puheeksi -töidenhallintaohjelma
+Comment[fr]=Gestionnaire de tâches de synthèse vocale pour KDE
+Comment[ga]=Bainisteoir Jabanna Téacs-go-Caint KDE
+Comment[gl]=Xestor de Traballos de Texto-para-Fala de KDE
+Comment[hu]=KDE-s kezelőprogram szövegfelolvasáshoz
+Comment[is]=KDE texti-í-tal verkstjóri
+Comment[it]=Gestore dei processi di pronuncia di KDE
+Comment[ja]=KDE テキスト読み上げジョブマネージャ
+Comment[ka]=KDE ტექსტი-გახმოვანების ამოცანათა მმართველი
+Comment[km]=ឧបករណ៍​គ្រប់គ្រង​ការងារ​អត្ថបទ​ដែលត្រូវ​និយាយ​របស់ KDE
+Comment[mk]=Менаџер на задачи во KDE за текст-во-говор
+Comment[ms]=Pengurus Kerja Teks-ke-tutur KDE
+Comment[nb]=Jobbkontroll for KDE tekst-til-tale
+Comment[nds]=KDE-Pleger för Vörleesopgaven
+Comment[ne]=केडीई पाठ वाचक काम प्रबन्धक
+Comment[nl]=KDE Tekst-tot-spraak-taakbeheer
+Comment[pa]=KDE ਪਾਠ ਤੋਂ ਬੋਲੀ ਕੰਮ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer zadań odczytywania tekstu
+Comment[pt]=Gestor de Trabalhos do Texto para Fala do KDE
+Comment[pt_BR]=Gerenciador de Trabalhos de Texto para Fala do KDE
+Comment[ru]=Управление заданиями по синтезу речи
+Comment[sk]=Správca úloh KDE text-na-reč
+Comment[sl]=Upravitelj opravil besedila v govor za KDE
+Comment[sr]=KDE-ов менаџер послова за текст-у-говор
+Comment[sr@Latn]=KDE-ov menadžer poslova za tekst-u-govor
+Comment[sv]=KDE:s text-till-tal jobbhantering
+Comment[ta]=கேடியி உரையில் இருந்து பேச்சு பணி மேலாளர்
+Comment[tg]=Идоракунии фармоишҳо бо воситаи таҳлили овоз
+Comment[tr]=KDE Metinden Konuşmaya Görev Yöneticisi
+Comment[uk]=Менеджер завдань KDE для синтезу мовлення з тексту
+Comment[vi]=Trình quản lý Tác vụ Văn bản sang Tiếng nói KDE
+Comment[zh_TW]=KDE 文字轉語音工作管理員
+ServiceTypes=KParts/ReadOnlyPart
diff --git a/kttsd/kttsjobmgr/kttsjobmgr.h b/kttsd/kttsjobmgr/kttsjobmgr.h
new file mode 100644
index 0000000..6bb4898
--- /dev/null
+++ b/kttsd/kttsjobmgr/kttsjobmgr.h
@@ -0,0 +1,298 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ A KPart to display running jobs in KTTSD and permit user to stop, rewind,
+ advance, change Talker, etc.
+ -------------------
+ Copyright : (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _KTTSJOBMGRPART_H_
+#define _KTTSJOBMGRPART_H_
+
+// KDE includes.
+#include <kparts/browserextension.h>
+#include <klibloader.h>
+
+// KTTS includes.
+#include "kspeech_stub.h"
+#include "kspeechsink.h"
+
+class KAboutData;
+class KInstance;
+class KttsJobMgrBrowserExtension;
+class KListView;
+class QListViewItem;
+class QVBox;
+class KTextEdit;
+
+class KttsJobMgrFactory : public KLibFactory
+{
+ Q_OBJECT
+public:
+ KttsJobMgrFactory() {};
+ virtual ~KttsJobMgrFactory();
+
+ virtual QObject* createObject(QObject* parent = 0, const char* name = 0,
+ const char* classname = "QObject",
+ const QStringList &args = QStringList());
+
+ static KInstance *instance();
+ static KAboutData *aboutData();
+
+private:
+ static KInstance *s_instance;
+};
+
+class KttsJobMgrPart:
+ public KParts::ReadOnlyPart,
+ public KSpeech_stub,
+ virtual public KSpeechSink
+{
+ Q_OBJECT
+public:
+ KttsJobMgrPart(QWidget *parent, const char *name);
+ virtual ~KttsJobMgrPart();
+
+protected:
+ virtual bool openFile();
+ virtual bool closeURL();
+
+ /** DCOP Methods connected to DCOP Signals emitted by KTTSD. */
+
+ /**
+ * This signal is emitted when KTTSD starts or restarts after a call to reinit.
+ */
+ ASYNC kttsdStarted();
+ /**
+ * This signal is emitted when the speech engine/plugin encounters a marker in the text.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param markerName The name of the marker seen.
+ * @see markers
+ */
+ ASYNC markerSeen(const QCString& appId, const QString& markerName);
+ /**
+ * This signal is emitted whenever a sentence begins speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ * @see getTextCount
+ */
+ ASYNC sentenceStarted(const QCString& appId, const uint jobNum, const uint seq);
+ /**
+ * This signal is emitted when a sentence has finished speaking.
+ * @param appId DCOP application ID of the application that queued the text.
+ * @param jobNum Job number of the text job.
+ * @param seq Sequence number of the text.
+ * @see getTextCount
+ */
+ ASYNC sentenceFinished(const QCString& appId, const uint jobNum, const uint seq);
+
+ /**
+ * This signal is emitted whenever a new text job is added to the queue.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ ASYNC textSet(const QCString& appId, const uint jobNum);
+
+ /**
+ * This signal is emitted whenever a new part is appended to a text job.
+ * @param appId The DCOP senderId of the application that created the job.
+ * @param jobNum Job number of the text job.
+ * @param partNum Part number of the new part. Parts are numbered starting
+ * at 1.
+ */
+ ASYNC textAppended(const QCString& appId, const uint jobNum, const int partNum);
+
+ /**
+ * This signal is emitted whenever speaking of a text job begins.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ ASYNC textStarted(const QCString& appId, const uint jobNum);
+ /**
+ * This signal is emitted whenever a text job is finished. The job has
+ * been marked for deletion from the queue and will be deleted when another
+ * job reaches the Finished state. (Only one job in the text queue may be
+ * in state Finished at one time.) If @ref startText or @ref resumeText is
+ * called before the job is deleted, it will remain in the queue for speaking.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ ASYNC textFinished(const QCString& appId, const uint jobNum);
+ /**
+ * This signal is emitted whenever a speaking text job stops speaking.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ ASYNC textStopped(const QCString& appId, const uint jobNum);
+ /**
+ * This signal is emitted whenever a speaking text job is paused.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ ASYNC textPaused(const QCString& appId, const uint jobNum);
+ /**
+ * This signal is emitted when a text job, that was previously paused, resumes speaking.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ ASYNC textResumed(const QCString& appId, const uint jobNum);
+ /**
+ * This signal is emitted whenever a text job is deleted from the queue.
+ * The job is no longer in the queue when this signal is emitted.
+ * @param appId The DCOP senderId of the application that created the job. NULL if kttsd.
+ * @param jobNum Job number of the text job.
+ */
+ ASYNC textRemoved(const QCString& appId, const uint jobNum);
+
+private slots:
+ /**
+ * This slot is connected to the Job List View selectionChanged signal.
+ */
+ void slot_selectionChanged(QListViewItem* item);
+ /**
+ * Slots connected to buttons.
+ */
+ void slot_job_hold();
+ void slot_job_resume();
+ void slot_job_restart();
+ void slot_job_remove();
+ void slot_job_move();
+ void slot_job_change_talker();
+ void slot_speak_clipboard();
+ void slot_speak_file();
+ void slot_refresh();
+ void slot_job_prev_par();
+ void slot_job_prev_sen();
+ void slot_job_next_sen();
+ void slot_job_next_par();
+
+private:
+ /**
+ * @enum JobListViewColumn
+ * Columns in the Job List View.
+ */
+ enum JobListViewColumn
+ {
+ jlvcJobNum = 0, /**< Job Number. */
+ jlvcOwner = 1, /**< AppId of job owner */
+ jlvcTalkerID = 2, /**< Job Talker ID */
+ jlvcState = 3, /**< Job State */
+ jlvcPosition = 4, /**< Current sentence of job. */
+ jlvcSentences = 5, /**< Number of sentences in job. */
+ jlvcPartNum = 6, /**< Current part of the job. */
+ jlvcPartCount = 7 /**< Number of parts in job. */
+ };
+
+ /**
+ * Convert a KTTSD job state integer into a display string.
+ * @param state KTTSD job state
+ * @return Display string for the state.
+ */
+ QString stateToStr(int state);
+
+ /**
+ * Get the Job Number of the currently-selected job in the Job List View.
+ * @return Job Number of currently-selected job.
+ * 0 if no currently-selected job.
+ */
+ uint getCurrentJobNum();
+
+ /**
+ * Get the number of parts in the currently-selected job in the Job List View.
+ * @return Number of parts in currently-selected job.
+ * 0 if no currently-selected job.
+ */
+ int getCurrentJobPartCount();
+
+ /**
+ * Given a Job Number, returns the Job List View item containing the job.
+ * @param jobNum Job Number.
+ * @return QListViewItem containing the job or 0 if not found.
+ */
+ QListViewItem* findItemByJobNum(const uint jobNum);
+
+ /**
+ * Enables or disables all the job-related buttons.
+ * @param enable True to enable the job-related butons. False to disable.
+ */
+ void enableJobActions(bool enable);
+
+ /**
+ * Enables or disables all the job part-related buttons.
+ * @param enable True to enable the job par-related butons. False to disable.
+ */
+ void enableJobPartActions(bool enable);
+
+ /**
+ * Refresh display of a single job in the JobListView.
+ * @param jobNum Job Number.
+ */
+ void refreshJob(uint jobNum);
+
+ /**
+ * Fill the Job List View.
+ */
+ void refreshJobListView();
+
+ /**
+ * If nothing selected in Job List View and list not empty, select top item.
+ * If nothing selected and list is empty, disable job buttons.
+ */
+ void autoSelectInJobListView();
+
+ /**
+ * Return the Talker ID corresponding to a Talker Code, retrieving from cached list if present.
+ * @param talkerCode Talker Code.
+ * @return Talker ID.
+ */
+ QString cachedTalkerCodeToTalkerID(const QString& talkerCode);
+
+ /**
+ * Job ListView.
+ */
+ KListView* m_jobListView;
+ KttsJobMgrBrowserExtension *m_extension;
+
+ /**
+ * Current sentence box.
+ */
+ KTextEdit* m_currentSentence;
+
+ /**
+ * Box containing buttons.
+ */
+ QVBox* m_buttonBox;
+
+ /**
+ * This flag is set to True whenever we want to select the next job that
+ * is announced in a textSet signal.
+ */
+ bool m_selectOnTextSet;
+
+ /**
+ * Cache mapping Talker Codes to Talker IDs.
+ */
+ QMap<QString,QString> m_talkerCodesToTalkerIDs;
+};
+
+class KttsJobMgrBrowserExtension : public KParts::BrowserExtension
+{
+ Q_OBJECT
+ friend class KttsJobMgrPart;
+public:
+ KttsJobMgrBrowserExtension(KttsJobMgrPart *parent);
+ virtual ~KttsJobMgrBrowserExtension();
+};
+
+#endif // _KTTSJOBMGRPART_H_
+
diff --git a/kttsd/kttsmgr/Makefile.am b/kttsd/kttsmgr/Makefile.am
new file mode 100644
index 0000000..747408d
--- /dev/null
+++ b/kttsd/kttsmgr/Makefile.am
@@ -0,0 +1,34 @@
+# Include paths.
+INCLUDES = \
+ $(KTTS_KSPEECH_INCLUDE) \
+ $(all_includes)
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# APPLICATION SECTION
+#########################################################################
+# This is the program that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+bin_PROGRAMS = kttsmgr
+
+kspeech_DIR = $(KTTS_KSPEECH_DIR)
+kspeechsink_DIR = $(KTTS_KSPEECH_DIR)
+
+# The source, library search path, and link libraries.
+kttsmgr_SOURCES = \
+ kspeech.stub \
+ kspeechsink.skel \
+ kttsmgr.cpp
+
+kttsmgr_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+kttsmgr_LDADD = \
+ $(LIB_KUTILS) \
+ $(LIB_KDEUI)
+
+# Header files that should not be installed.
+noinst_HEADERS = kttsmgr.h
+
+# K Menu entry.
+xdg_apps_DATA = kttsmgr.desktop
diff --git a/kttsd/kttsmgr/kttsmgr.cpp b/kttsd/kttsmgr/kttsmgr.cpp
new file mode 100644
index 0000000..80b66b9
--- /dev/null
+++ b/kttsd/kttsmgr/kttsmgr.cpp
@@ -0,0 +1,334 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KTTS Manager Program
+ --------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qimage.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kuniqueapplication.h>
+#include <kcmultidialog.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <ksystemtray.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kaboutapplication.h>
+#include <dcopclient.h>
+#include <kdeversion.h>
+
+// KTTSMgr includes.
+#include "kspeech.h"
+#include "kttsmgr.h"
+
+static const KCmdLineOptions options[] =
+{
+ { "s", 0, 0 },
+ { "systray", I18N_NOOP("Start minimized in system tray"), 0 },
+ { "a", 0, 0 },
+ { "autoexit", I18N_NOOP("Exit when speaking is finished and minimized in system tray"), 0 },
+ KCmdLineLastOption
+};
+
+int main (int argc, char *argv[])
+{
+ KGlobal::locale()->setMainCatalogue("kttsd");
+
+ KAboutData aboutdata("kttsmgr", I18N_NOOP("KTTSMgr"),
+ "0.3.5.2", I18N_NOOP("Text-to-Speech Manager"),
+ KAboutData::License_GPL, "(C) 2002, José Pablo Ezequiel Fernández");
+ aboutdata.addAuthor("José Pablo Ezequiel Fernández",I18N_NOOP("Original Author"),"pupeno@pupeno.com");
+ aboutdata.addAuthor("Gary Cramblitt", I18N_NOOP("Maintainer"),"garycramblitt@comcast.net");
+ aboutdata.addAuthor("Gunnar Schmi Dt", I18N_NOOP("Contributor"),"gunnar@schmi-dt.de");
+ aboutdata.addAuthor("Olaf Schmidt", I18N_NOOP("Contributor"),"ojschmidt@kde.org");
+ aboutdata.addAuthor("Paul Giannaros", I18N_NOOP("Contributor"), "ceruleanblaze@gmail.com");
+ aboutdata.addCredit("Jorge Luis Arzola", I18N_NOOP("Testing"), "arzolacub@hotmail.com");
+ aboutdata.addCredit("David Powell", I18N_NOOP("Testing"), "achiestdragon@gmail.com");
+ KCmdLineArgs::init( argc, argv, &aboutdata );
+
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KUniqueApplication::addCmdLineOptions();
+
+ if(!KUniqueApplication::start())
+ {
+ kdDebug() << "kttsmgr is already running" << endl;
+ return (0);
+ }
+
+ KUniqueApplication app;
+
+#if KDE_VERSION >= KDE_MAKE_VERSION (3,3,90)
+ QPixmap icon = KGlobal::iconLoader()->loadIcon("kttsd", KIcon::Panel);
+ aboutdata.setProgramLogo(icon.convertToImage());
+#endif
+
+ // The real work of KTTS Manager is done in the KControl Module kcmkttsd.
+ KCMultiDialog dlg(KCMultiDialog::Plain, i18n("KDE Text-to-Speech Manager"), 0, "kttsmgrdlg", false);
+ dlg.addModule("kcmkttsd");
+
+ dlg.setIcon(KGlobal::iconLoader()->loadIcon("kttsd", KIcon::Small));
+
+ // Get SysTray and ShowMainWindow options.
+ KConfig* config = new KConfig("kttsdrc");
+ config->setGroup("General");
+ bool embedInSysTray = config->readBoolEntry("EmbedInSysTray", true);
+ // Can only hide main window if we are in the system tray, otherwise, no way
+ // for user to do anything.
+ bool showMainWindowOnStartup = true;
+ if (embedInSysTray)
+ showMainWindowOnStartup = config->readBoolEntry("ShowMainWindowOnStartup", true);
+
+ // If --systray option specified, start minimized in system tray.
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ if (args->isSet("systray"))
+ {
+ embedInSysTray = true;
+ showMainWindowOnStartup = false;
+ }
+
+ KttsMgrTray* tray = 0;
+ if (embedInSysTray)
+ {
+ tray = new KttsMgrTray(&dlg);
+ tray->show();
+ }
+ else app.setMainWidget(&dlg);
+
+ if (showMainWindowOnStartup)
+#if KDE_VERSION < KDE_MAKE_VERSION (3,3,0)
+ dlg.show();
+#else
+ {
+ if (embedInSysTray)
+ tray->setActive();
+ else
+ dlg.show();
+ }
+#endif
+ int result = app.exec();
+ delete tray;
+ return result;
+}
+
+/* KttsToolTip class */
+
+KttsToolTip::KttsToolTip ( QWidget* parent ) : QToolTip(parent)
+{
+}
+
+/*virtual*/ void KttsToolTip::maybeTip ( const QPoint & p )
+{
+ Q_UNUSED(p);
+
+ if (!parentWidget()->inherits("KttsMgrTray"))
+ return;
+
+ KttsMgrTray* kttsMgrTray = dynamic_cast<KttsMgrTray*>(parentWidget());
+
+ QRect r(kttsMgrTray->geometry());
+ if ( !r.isValid() )
+ return;
+
+ QString status = "<qt><b>KTTSMgr</b> - ";
+ status += i18n("<qt>Text-to-Speech Manager");
+ status += "<br/><br/>";
+ status += kttsMgrTray->getStatus();
+ status += "</qt>";
+
+ tip(r, status);
+}
+
+/* KttsMgrTray class */
+
+KttsMgrTray::KttsMgrTray(QWidget *parent):
+ DCOPStub("kttsd", "KSpeech"),
+ DCOPObject("kkttsmgr_kspeechsink"),
+ KSystemTray(parent, "kttsmgrsystemtray")
+{
+ QPixmap icon = KGlobal::iconLoader()->loadIcon("kttsd", KIcon::Small);
+ setPixmap (icon);
+
+ // QToolTip::add(this, i18n("Text-to-speech manager"));
+ m_toolTip = new KttsToolTip(this);
+
+ int id;
+ id = contextMenu()->idAt(0);
+ if (id != -1) contextMenu()->changeTitle(id, icon, "KTTSMgr");
+
+ id = contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("klipper", KIcon::Small),
+ i18n("&Speak Clipboard Contents"), this, SLOT(speakClipboardSelected()));
+ id = contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("stop", KIcon::Small),
+ i18n("&Hold"), this, SLOT(holdSelected()));
+ id = contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("exec", KIcon::Small),
+ i18n("Resume"), this, SLOT(resumeSelected()));
+ id = contextMenu()->insertSeparator();
+ id = contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("contents", KIcon::Small),
+ i18n("KTTS &Handbook"), this, SLOT(helpSelected()));
+ id = contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("kttsd", KIcon::Small),
+ i18n("&About KTTSMgr"), this, SLOT(aboutSelected()));
+
+ connect(this, SIGNAL(quitSelected()), this, SLOT(quitSelected()));
+ // If --autoexit option given, exit when speaking stops.
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ if (args->isSet("autoexit"))
+ {
+ connectDCOPSignal("kttsd", "KSpeech",
+ "textFinished(QCString,uint)",
+ "textFinished(QCString,uint)",
+ false);
+ // Install an event filter so we can check when KTTSMgr becomes inconified to the systray.
+ parent->installEventFilter(this);
+ }
+}
+
+KttsMgrTray::~KttsMgrTray()
+{
+ delete m_toolTip;
+}
+
+void KttsMgrTray::textFinished(const QCString& /*appId*/, uint /*jobNum*/)
+{
+ // kdDebug() << "KttsMgrTray::textFinished: running" << endl;
+ exitWhenFinishedSpeaking();
+}
+
+/*virtual*/ bool KttsMgrTray::eventFilter( QObject* /*o*/, QEvent* e )
+{
+ if ( e->type() == QEvent::Hide ) exitWhenFinishedSpeaking();
+ return false;
+}
+
+void KttsMgrTray::exitWhenFinishedSpeaking()
+{
+ // kdDebug() << "KttsMgrTray::exitWhenFinishedSpeaking: running" << endl;
+ if ( parentWidget()->isShown() ) return;
+ QString jobNums = getTextJobNumbers();
+ QStringList jobNumsList = QStringList::split(jobNums, ",");
+ uint jobNumsListCount = jobNumsList.count();
+ // Since there can only be 2 Finished jobs at a time, more than 2 jobs means at least
+ // one job is not Finished.
+ if (jobNumsListCount > 2) return;
+ // Exit if all jobs are Finished or there are no jobs.
+ for (uint ndx=0; ndx < jobNumsListCount; ++ndx)
+ {
+ if (getTextJobState(jobNumsList[ndx].toInt()) != KSpeech::jsFinished) return;
+ }
+ kapp->quit();
+}
+
+/**
+* Convert a KTTSD job state integer into a display string.
+* @param state KTTSD job state
+* @return Display string for the state.
+*/
+QString KttsMgrTray::stateToStr(int state)
+{
+ switch( state )
+ {
+ case KSpeech::jsQueued: return i18n("Queued");
+ case KSpeech::jsSpeakable: return i18n("Waiting");
+ case KSpeech::jsSpeaking: return i18n("Speaking");
+ case KSpeech::jsPaused: return i18n("Paused");
+ case KSpeech::jsFinished: return i18n("Finished");
+ default: return i18n("Unknown");
+ }
+}
+
+QString KttsMgrTray::getStatus()
+{
+ if (!isKttsdRunning()) return i18n("Text-to-Speech System is not running");
+ uint jobCount = getTextJobCount();
+ QString status = i18n("1 job", "%n jobs", jobCount);
+ if (jobCount > 0)
+ {
+ uint job = getCurrentTextJob();
+ int jobState = 0;
+ if (job != 0)
+ {
+ // kdDebug() << "KttsMgrTray::getStatus: job = " << job << endl;
+ jobState = getTextJobState(job);
+ int sentenceCount = getTextCount(job);
+ uint seq = moveRelTextSentence(0, job);
+ status += i18n(", current job %1 at sentence %2 of %3 sentences"
+ ).arg(stateToStr(jobState)).arg(seq).arg(sentenceCount);
+ }
+ }
+ return status;
+}
+
+void KttsMgrTray::speakClipboardSelected()
+{
+ if (!isKttsdRunning())
+ {
+ QString error;
+ if (KApplication::startServiceByDesktopName("kttsd", QStringList(), &error) != 0)
+ kdError() << "Starting KTTSD failed with message " << error << endl;
+ }
+ speakClipboard();
+}
+
+void KttsMgrTray::aboutSelected()
+{
+ KAboutApplication aboutDlg(kapp->aboutData(), 0, "kttsmgraboutdlg", true);
+ aboutDlg.exec();
+}
+
+void KttsMgrTray::helpSelected()
+{
+ kapp->invokeHelp(QString::null,"kttsd");
+}
+
+void KttsMgrTray::quitSelected()
+{
+ // kdDebug() << "Running KttsMgrTray::quitSelected" << endl;
+ kapp->quit();
+}
+
+void KttsMgrTray::holdSelected()
+{
+ if (isKttsdRunning())
+ {
+ uint jobNum = getCurrentTextJob();
+ pauseText(jobNum);
+ }
+}
+
+void KttsMgrTray::resumeSelected()
+{
+ if (isKttsdRunning())
+ {
+ uint jobNum = getCurrentTextJob();
+ resumeText(jobNum);
+ }
+}
+
+bool KttsMgrTray::isKttsdRunning()
+{
+ DCOPClient *client = kapp->dcopClient();
+ return (client->isApplicationRegistered("kttsd"));
+}
+
+#include "kttsmgr.moc"
diff --git a/kttsd/kttsmgr/kttsmgr.desktop b/kttsd/kttsmgr/kttsmgr.desktop
new file mode 100644
index 0000000..318d7a3
--- /dev/null
+++ b/kttsd/kttsmgr/kttsmgr.desktop
@@ -0,0 +1,98 @@
+[Desktop Entry]
+Type=Application
+Name=kttsmgr
+Name[pt_BR]=Gerenciador ktts
+Name[tr]=Kttsmgr
+GenericName=Text-to-Speech Manager
+GenericName[bg]=Синтез на глас
+GenericName[ca]=Gestor de text a veu
+GenericName[cs]=Správce zvukové syntézy
+GenericName[da]=Tekst-til-tale håndtering
+GenericName[de]=Sprachausgabeverwaltung
+GenericName[el]=Διαχειριστής κειμένου-σε-ομιλία
+GenericName[es]=Administrador de texto a voz
+GenericName[et]=Teksti kõneks muutmise haldur
+GenericName[eu]=Testutik hizketarako kudeatzailea
+GenericName[fa]=مدیر متن به گفتار
+GenericName[fi]=Teksti puheeksi -hallintaohjelma
+GenericName[fr]=Gestionnaire de synthèse vocale
+GenericName[ga]=Bainisteoir Téacs-go-Caint
+GenericName[gl]=Xestor de Texto-para-Fala
+GenericName[he]=מנהל טקסט לדיבור
+GenericName[hu]=Szövegfelolvasás-kezelő
+GenericName[is]=Texti-í-tal stjóri
+GenericName[it]=Gestore della pronuncia
+GenericName[ja]=テキスト読み上げマネージャ
+GenericName[ka]=ტექსტი-გახმოვანების მმართველი
+GenericName[km]=ឧបករណ៍​គ្រប់គ្រង​អត្ថបទ​ដែល​ត្រូវ​និយាយ
+GenericName[mk]=Менаџер за текст-во-говор
+GenericName[ms]=Pengurus Teks-ke-Tutur
+GenericName[mt]=Manaġer Test-għal-Vuċi
+GenericName[nb]=Styring for tekst-til-tale
+GenericName[nds]=Vörleespleger
+GenericName[ne]=पाठ वाचक प्रबन्धक
+GenericName[nl]=Tekst-tot-spraak-beheerder
+GenericName[pa]=ਪਾਠ ਤੋਂ ਬੋਲੀ ਮੈਨੇਜਰ
+GenericName[pl]=Menedżer odczytywania tekstu
+GenericName[pt]=Gestor do Texto para Fala
+GenericName[pt_BR]=Gerenciador de Conversão de Texto para Fala do KDE
+GenericName[ru]=Управление синтезом речи
+GenericName[sk]=Správca text-na-reč
+GenericName[sl]=Upravitelj besedila v govor
+GenericName[sr]=Менаџер за текст у говор
+GenericName[sr@Latn]=Menadžer za tekst u govor
+GenericName[sv]=Text-till-tal hantering
+GenericName[ta]=உரையில் இருந்து பேச்சு மேலாளர்
+GenericName[tg]=Идоракунии таҳлили овоз
+GenericName[tr]=Metinden Konuşmaya Yöneticisi
+GenericName[uk]=Менеджер для синтезу мовлення з тексту
+GenericName[vi]=Trình quản lý Văn bản sang Tiếng nói
+GenericName[zh_TW]=文字轉語音管理員
+Icon=kttsd
+Exec=kttsmgr -caption "%c" %i %u
+Comment=KDE Text-to-speech Manager
+Comment[bg]=Мениджър на синтезатора на глас
+Comment[ca]=Gestor de text a veu de KDE
+Comment[cs]=Správce hlasové syntézy KDE
+Comment[da]=KDE's Tekst-til-tale håndtering
+Comment[de]=KDE Verwaltung für Sprachausgabe
+Comment[el]=KDE διαχειριστής κειμένου-σε-ομιλία
+Comment[es]=Administrador de texto a voz de KDE
+Comment[et]=KDE teksti kõneks muutmise haldur
+Comment[eu]=KDE-ren testutik hizketarako kudeatzailea
+Comment[fa]=مدیر متن به گفتار KDE
+Comment[fi]=KDE Teksti puheeksi -hallintaohjelma
+Comment[fr]=Gestionnaire de synthèse vocale pour KDE
+Comment[ga]=Bainisteoir Téacs-go-Caint KDE
+Comment[gl]=Xestor de Texto-para-fala de KDE
+Comment[he]=מנהל טקסט לדיבור של KDE
+Comment[hu]=KDE-s szövegfelolvasás-kezelő
+Comment[is]=KDE texti-í-tal stjóri
+Comment[it]=Gestore della pronuncia di KDE
+Comment[ja]=KDE テキスト読み上げマネージャ
+Comment[ka]=KDE ტექსტი-გახმოვანების მმართველი
+Comment[km]=ឧបករណ៍​គ្រប់គ្រង​អត្ថបទ​ដែល​ត្រូវ​និយាយ​របស់ KDE
+Comment[mk]=Менаџер на KDE за текст-во-говор
+Comment[ms]=Pengurus Teks-ke-tutur KDE
+Comment[nb]=Styring for KDEs tekst-til-tale
+Comment[nds]=Vörleespleger för KDE
+Comment[ne]=केडीई पाठ वाचक प्रबन्धक
+Comment[nl]=KDE Tekst-tot-spraak-beheer
+Comment[pa]=KDE ਪਾਠ ਤੋਂ ਬੋਲੀ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer odczytywania tekstu dla KDE
+Comment[pt]=Gestor do Texto para Fala do KDE
+Comment[pt_BR]=Gerenciador de Conversão de Texto para Fala do KDE
+Comment[ru]=Менеджер движков синтеза речи
+Comment[sk]=KDE text-na-reč manažér
+Comment[sl]=Upravitelj besedila v govor v KDE
+Comment[sr]=KDE-ов менаџер за текст у говор
+Comment[sr@Latn]=KDE-ov menadžer za tekst u govor
+Comment[sv]=KDE:s text-till-tal hantering
+Comment[ta]=கேடியி உரையில் இருந்து பேச்சு மேலாளர்
+Comment[tg]=Идоракунандаи микшерҳои таҳлили овоз
+Comment[tr]=KDE Metinden Konuşmaya yöneticisi
+Comment[uk]=Менеджер KDE для синтезу мовлення з тексту
+Comment[vi]=Trình quản lý Văn bản sang Tiếng nói KDE
+Comment[zh_TW]=KDE 文字轉語音管理員
+Terminal=false
+Categories=Qt;KDE;Utility;Accessibility;
diff --git a/kttsd/kttsmgr/kttsmgr.h b/kttsd/kttsmgr/kttsmgr.h
new file mode 100644
index 0000000..e13233a
--- /dev/null
+++ b/kttsd/kttsmgr/kttsmgr.h
@@ -0,0 +1,86 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KTTS Manager Program
+ --------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef KTTSMGR_H
+#define KTTSMGR_H
+
+// Qt includes.
+#include <qevent.h>
+#include <qtooltip.h>
+
+// KDE includes.
+#include <ksystemtray.h>
+
+// KTTS includes.
+#include "kspeech_stub.h"
+#include "kspeechsink.h"
+
+class KttsToolTip: public QToolTip
+{
+ public:
+ KttsToolTip ( QWidget* parent );
+
+ protected:
+ virtual void maybeTip ( const QPoint & p );
+};
+
+class KttsMgrTray: public KSystemTray, public KSpeech_stub, virtual public KSpeechSink
+{
+ Q_OBJECT
+
+ public:
+ KttsMgrTray(QWidget *parent=0);
+ ~KttsMgrTray();
+
+ void setExitWhenFinishedSpeaking();
+ QString getStatus();
+
+ protected:
+ // ASYNC textStarted(const QCString& appId, uint jobNum);
+ ASYNC textFinished(const QCString& appId, uint jobNum);
+ virtual bool eventFilter( QObject* o, QEvent* e );
+
+ private slots:
+
+ void speakClipboardSelected();
+ void holdSelected();
+ void resumeSelected();
+ void aboutSelected();
+ void helpSelected();
+ void quitSelected();
+
+ private:
+ /**
+ * Convert a KTTSD job state integer into a display string.
+ * @param state KTTSD job state
+ * @return Display string for the state.
+ */
+ QString stateToStr(int state);
+
+ bool isKttsdRunning();
+ void exitWhenFinishedSpeaking();
+ KttsToolTip* m_toolTip;
+};
+
+#endif // KTTSMGR_H
diff --git a/kttsd/libkttsd/Makefile.am b/kttsd/libkttsd/Makefile.am
new file mode 100644
index 0000000..3b2c099
--- /dev/null
+++ b/kttsd/libkttsd/Makefile.am
@@ -0,0 +1,45 @@
+# Include paths.
+INCLUDES = $(all_includes)
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# LIBRARY SECTION
+#########################################################################
+# This is the library that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+lib_LTLIBRARIES = libkttsd.la
+
+# The source, library search path, and link libraries.
+libkttsd_la_SOURCES = \
+ pluginproc.cpp \
+ pluginconf.cpp \
+ testplayer.cpp \
+ stretcher.cpp \
+ talkercode.cpp \
+ filterproc.cpp \
+ filterconf.cpp \
+ utils.cpp \
+ selecttalkerdlg.cpp \
+ selecttalkerwidget.ui \
+ notify.cpp
+
+libkttsd_la_LDFLAGS = -version-info 1:0:0 $(all_libraries) -no-undefined
+libkttsd_la_LIBADD = $(LIB_KIO)
+
+# Header files that should not be installed.
+noinst_HEADERS = \
+ pluginproc.h \
+ pluginconf.h \
+ player.h \
+ testplayer.h \
+ stretcher.h \
+ talkercode.h \
+ utils.h \
+ kdeexportfix.h \
+ selecttalkerdlg.h
+
+# This library is installed as a service.
+servicetypes_DATA = kttsd_synthplugin.desktop
+servicetypesdir = $(kde_servicetypesdir)
diff --git a/kttsd/libkttsd/filterconf.cpp b/kttsd/libkttsd/filterconf.cpp
new file mode 100644
index 0000000..43e62bc
--- /dev/null
+++ b/kttsd/libkttsd/filterconf.cpp
@@ -0,0 +1,166 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Filter Configuration class.
+ This is the interface definition for text filter configuration dialogs.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// C++ library includes.
+#include <stdlib.h>
+#include <sys/param.h>
+
+// Qt includes.
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qstring.h>
+
+// KDE includes.
+#include <kglobal.h>
+#include <klocale.h>
+
+// PluginConf includes.
+#include "filterconf.h"
+#include "filterconf.moc"
+
+/**
+* Constructor
+*/
+KttsFilterConf::KttsFilterConf( QWidget *parent, const char *name) : QWidget(parent, name){
+ // kdDebug() << "KttsFilterConf::KttsFilterConf: Running" << endl;
+ QString systemPath(getenv("PATH"));
+ // kdDebug() << "Path is " << systemPath << endl;
+ KGlobal::locale()->insertCatalogue("kttsd");
+ m_path = QStringList::split(":", systemPath);
+}
+
+/**
+* Destructor.
+*/
+KttsFilterConf::~KttsFilterConf(){
+ // kdDebug() << "KttsFilterConf::~KttsFilterConf: Running" << endl;
+}
+
+/**
+* This method is invoked whenever the module should read its
+* configuration (most of the times from a config file) and update the
+* user interface. This happens when the user clicks the "Reset" button in
+* the control center, to undo all of his changes and restore the currently
+* valid settings. Note that kttsmgr calls this when the plugin is
+* loaded, so it not necessary to call it in your constructor.
+* The plugin should read its configuration from the specified group
+* in the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* loading your configuration.
+*/
+void KttsFilterConf::load(KConfig* /*config*/, const QString& /*configGroup*/){
+ // kdDebug() << "KttsFilterConf::load: Running" << endl;
+}
+
+/**
+* This function gets called when the user wants to save the settings in
+* the user interface, updating the config files or wherever the
+* configuration is stored. The method is called when the user clicks "Apply"
+* or "Ok". The plugin should save its configuration in the specified
+* group of the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* saving your configuration.
+*/
+void KttsFilterConf::save(KConfig* /*config*/, const QString& /*configGroup*/){
+ // kdDebug() << "KttsFilterConf::save: Running" << endl;
+}
+
+/**
+* This function is called to set the settings in the module to sensible
+* default values. It gets called when hitting the "Default" button. The
+* default values should probably be the same as the ones the application
+* uses when started without a config file. Note that defaults should
+* be applied to the on-screen widgets; not to the config file.
+*/
+void KttsFilterConf::defaults(){
+ // kdDebug() << "KttsFilterConf::defaults: Running" << endl;
+}
+
+/**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+bool KttsFilterConf::supportsMultiInstance() { return false; }
+
+/**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+QString KttsFilterConf::userPlugInName() { return QString::null; }
+
+/**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * @return True if this filter is a SBD.
+ */
+bool KttsFilterConf::isSBD() { return false; }
+
+/**
+* Return the full path to any program in the $PATH environmental variable
+* @param name The name of the file to search for.
+* @returns The path to the file on success, a blank QString
+* if its not found.
+*/
+QString KttsFilterConf::getLocation(const QString &name) {
+ // Iterate over the path and see if 'name' exists in it. Return the
+ // full path to it if it does. Else return an empty QString.
+ if (QFile::exists(name)) return name;
+ // kdDebug() << "KttsFilterConf::getLocation: Searching for " << name << " in the path.." << endl;
+ // kdDebug() << m_path << endl;
+ for(QStringList::iterator it = m_path.begin(); it != m_path.end(); ++it) {
+ QString fullName = *it;
+ fullName += "/";
+ fullName += name;
+ // The user either has the directory of the file in the path...
+ if(QFile::exists(fullName)) {
+ // kdDebug() << "KttsFilterConf:getLocation: " << fullName << endl;
+ return fullName;
+ }
+ // ....Or the file itself
+ else if(QFileInfo(*it).baseName().append(QString(".").append(QFileInfo(*it).extension())) == name) {
+ // kdDebug() << "KttsFilterConf:getLocation: " << fullName << endl;
+ return fullName;
+ }
+ }
+ return "";
+}
+
+/*static*/ QString KttsFilterConf::realFilePath(const QString &filename)
+{
+ char realpath_buffer[MAXPATHLEN + 1];
+ memset(realpath_buffer, 0, MAXPATHLEN + 1);
+
+ /* If the path contains symlinks, get the real name */
+ if (realpath( QFile::encodeName(filename).data(), realpath_buffer) != 0) {
+ //succes, use result from realpath
+ return QFile::decodeName(realpath_buffer);
+ }
+ return filename;
+}
diff --git a/kttsd/libkttsd/filterconf.h b/kttsd/libkttsd/filterconf.h
new file mode 100644
index 0000000..42055d8
--- /dev/null
+++ b/kttsd/libkttsd/filterconf.h
@@ -0,0 +1,149 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Filter Configuration class.
+ This is the interface definition for text filter configuration dialogs.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _FILTERCONF_H_
+#define _FILTERCONF_H_
+
+// Qt includes.
+#include <qwidget.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+
+class KDE_EXPORT KttsFilterConf : public QWidget{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ KttsFilterConf( QWidget *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor
+ */
+ virtual ~KttsFilterConf();
+
+ /**
+ * This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. Note that KTTSMGR calls this when the plugin is
+ * loaded, so it not necessary to call it in your constructor.
+ * The plugin should read its configuration from the specified group
+ * in the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * loading your configuration.
+ *
+ * When a plugin is first added to KTTSMGR, @e load will be called with
+ * a Null @e configGroup. In this case, the plugin will not have
+ * any instance-specific parameters to load, but it may still wish
+ * to load parameters that apply to all instances of the plugin.
+ */
+ virtual void load(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok". The plugin should save its configuration in the specified
+ * group of the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * saving your configuration.
+ */
+ virtual void save(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file. Note that defaults should
+ * be applied to the on-screen widgets; not to the config file.
+ */
+ virtual void defaults();
+
+ /**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+ virtual bool supportsMultiInstance();
+
+ /**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+ virtual QString userPlugInName();
+
+ /**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * @return True if this filter is a SBD.
+ */
+ virtual bool isSBD();
+
+ static QString realFilePath(const QString &filename);
+
+ public slots:
+ /**
+ * This slot is used internally when the configuration is changed. It is
+ * typically connected to signals from the widgets of the configuration
+ * and should emit the @ref changed signal.
+ */
+ void configChanged(){
+ // kdDebug() << "KttsFilterConf::configChanged: Running"<< endl;
+ emit changed(true);
+ };
+
+ signals:
+ /**
+ * This signal indicates that the configuration has been changed.
+ * It should be emitted whenever user changes something in the configuration widget.
+ */
+ void changed(bool);
+
+ protected:
+ /**
+ * Searches the $PATH variable for any file. If that file exists in the PATH, or
+ * is contained in any directory in the PATH, it returns the full path to it.
+ * @param name The name of the file to search for.
+ * @returns The path to the file on success, a blank QString
+ * if its not found.
+ */
+ QString getLocation(const QString &name);
+
+ /// The system path in a QStringList.
+ QStringList m_path;
+};
+
+#endif //_FILTERCONF_H_
diff --git a/kttsd/libkttsd/filterproc.cpp b/kttsd/libkttsd/filterproc.cpp
new file mode 100644
index 0000000..178dec2
--- /dev/null
+++ b/kttsd/libkttsd/filterproc.cpp
@@ -0,0 +1,153 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Filter Processing class.
+ This is the interface definition for text filters.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// KDE includes.
+// #include <kdebug.h>
+
+// FilterProc includes.
+#include "filterproc.h"
+
+/**
+ * Constructor.
+ */
+KttsFilterProc::KttsFilterProc( QObject *parent, const char *name) :
+ QObject(parent, name)
+{
+ // kdDebug() << "KttsFilterProc::KttsFilterProc: Running" << endl;
+}
+
+/**
+ * Destructor.
+ */
+KttsFilterProc::~KttsFilterProc()
+{
+ // kdDebug() << "KttsFilterProc::~KttsFilterProc: Running" << endl;
+}
+
+/**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+bool KttsFilterProc::init(KConfig* /*config*/, const QString& /*configGroup*/){
+ // kdDebug() << "PlugInProc::init: Running" << endl;
+ return false;
+}
+
+/**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * If so, the filter should implement @ref setSbRegExp() .
+ * @return True if this filter is a SBD.
+ */
+/*virtual*/ bool KttsFilterProc::isSBD() { return false; }
+
+/**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+/*virtual*/ bool KttsFilterProc::supportsAsync() { return false; }
+
+/**
+ * Convert input, returning output. Runs synchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+/*virtual*/ QString KttsFilterProc::convert(const QString& inputText, TalkerCode* /*talkerCode*/,
+ const QCString& /*appId*/)
+{
+ return inputText;
+}
+
+/**
+ * Convert input. Runs asynchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ * @return False if the filter cannot perform the conversion.
+ *
+ * When conversion is completed, emits signal @ref filteringFinished. Calling
+ * program may then call @ref getOutput to retrieve converted text. Calling
+ * program must call @ref ackFinished to acknowledge the conversion.
+ */
+/*virtual*/ bool KttsFilterProc::asyncConvert(const QString& /*inputText*/,
+ TalkerCode* /*talkerCode*/, const QCString& /*appId*/) { return false; }
+
+/**
+ * Waits for a previous call to asyncConvert to finish.
+ */
+/*virtual*/ void KttsFilterProc::waitForFinished() { }
+
+/**
+ * Returns the state of the Filter.
+ */
+/*virtual*/ int KttsFilterProc::getState() { return fsIdle; }
+
+/**
+ * Returns the filtered output.
+ */
+/*virtual*/ QString KttsFilterProc::getOutput() { return QString::null; }
+
+/**
+ * Acknowledges the finished filtering.
+ */
+/*virtual*/ void KttsFilterProc::ackFinished() { }
+
+/**
+ * Stops filtering. The filteringStopped signal will emit when filtering
+ * has in fact stopped and state returns to fsIdle;
+ */
+/*virtual*/ void KttsFilterProc::stopFiltering() { }
+
+/**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+/*virtual*/ bool KttsFilterProc::wasModified() { return true; }
+
+/**
+ * Set Sentence Boundary Regular Expression.
+ * This method will only be called if the application overrode the default.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+/*virtual*/ void KttsFilterProc::setSbRegExp(const QString& /*re*/) { }
+
+#include "filterproc.moc"
diff --git a/kttsd/libkttsd/filterproc.h b/kttsd/libkttsd/filterproc.h
new file mode 100644
index 0000000..ef7972c
--- /dev/null
+++ b/kttsd/libkttsd/filterproc.h
@@ -0,0 +1,179 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Filter Processing class.
+ This is the interface definition for text filters.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _FILTERPROC_H_
+#define _FILTERPROC_H_
+
+// Qt includes.
+#include <qobject.h>
+#include <qstringlist.h>
+
+// KDE includes.
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+
+class TalkerCode;
+class KConfig;
+
+class KDE_EXPORT KttsFilterProc : virtual public QObject
+{
+ Q_OBJECT
+
+public:
+ enum FilterState {
+ fsIdle = 0, // Not doing anything. Ready to filter.
+ fsFiltering = 1, // Filtering.
+ fsStopping = 2, // Stop of filtering is in progress.
+ fsFinished = 3 // Filtering finished.
+ };
+
+ /**
+ * Constructor.
+ */
+ KttsFilterProc( QObject *parent, const char *name );
+
+ /**
+ * Destructor.
+ */
+ virtual ~KttsFilterProc();
+
+ /**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Returns True if this filter is a Sentence Boundary Detector.
+ * If so, the filter should implement @ref setSbRegExp() .
+ * @return True if this filter is a SBD.
+ */
+ virtual bool isSBD();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., supports asyncConvert method.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref filteringFinished when filtering is completed.
+ * If the plugin returns True, it must also implement @ref stopFiltering .
+ * It must also emit @ref filteringStopped when filtering has been stopped.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Convert input, returning output. Runs synchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+ virtual QString convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+ /**
+ * Convert input. Runs asynchronously.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ * @return False if the filter cannot perform the conversion.
+ *
+ * When conversion is completed, emits signal @ref filteringFinished. Calling
+ * program may then call @ref getOutput to retrieve converted text. Calling
+ * program must call @ref ackFinished to acknowledge the conversion.
+ */
+ virtual bool asyncConvert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+ /**
+ * Waits for a previous call to asyncConvert to finish.
+ */
+ virtual void waitForFinished();
+
+ /**
+ * Returns the state of the Filter.
+ */
+ virtual int getState();
+
+ /**
+ * Returns the filtered output.
+ */
+ virtual QString getOutput();
+
+ /**
+ * Acknowledges the finished filtering.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Stops filtering. The filteringStopped signal will emit when filtering
+ * has in fact stopped and state returns to fsIdle;
+ */
+ virtual void stopFiltering();
+
+ /**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+ virtual bool wasModified();
+
+ /**
+ * Set Sentence Boundary Regular Expression.
+ * This method will only be called if the application overrode the default.
+ *
+ * @param re The sentence delimiter regular expression.
+ */
+ virtual void setSbRegExp(const QString& re);
+
+signals:
+ /**
+ * Emitted when asynchronous filtering has completed.
+ */
+ void filteringFinished();
+
+ /**
+ * Emitted when stopFiltering has been called and filtering has in fact stopped.
+ */
+ void filteringStopped();
+
+ /**
+ * If an error occurs, Filter should signal the error and return input as output in
+ * convert method. If Filter should not be called in the future, perhaps because
+ * it could not find its configuration file, return False for keepGoing.
+ * @param keepGoing False if the filter should not be called in the future.
+ * @param msg Error message.
+ */
+ void error(bool keepGoing, const QString &msg);
+};
+
+#endif // _FILTERPROC_H_
diff --git a/kttsd/libkttsd/kdeexportfix.h b/kttsd/libkttsd/kdeexportfix.h
new file mode 100644
index 0000000..7c80d9c
--- /dev/null
+++ b/kttsd/libkttsd/kdeexportfix.h
@@ -0,0 +1,27 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ kdelibs < 3.3.2 had a bug in the KDE_EXPORT macro. This file fixes this
+ by undefining it.
+ -------------------
+ Copyright : (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _KDEEXPORTFIX_H_
+#define _KDEEXPORTFIX_H_
+
+#include <kdeversion.h>
+#if KDE_VERSION < KDE_MAKE_VERSION (3,3,2)
+#undef KDE_EXPORT
+#define KDE_EXPORT
+#endif
+
+#endif // _KDEEXPORTFIX_H_
diff --git a/kttsd/libkttsd/kttsd_synthplugin.desktop b/kttsd/libkttsd/kttsd_synthplugin.desktop
new file mode 100644
index 0000000..c6367af
--- /dev/null
+++ b/kttsd/libkttsd/kttsd_synthplugin.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=KTTSD
+Name[zh_TW]=KTTSd
+Type=ServiceType
+X-KDE-ServiceType=KTTSD/SynthPlugin
+
+[PropertyDef::X-KDE-Languages]
+Type=QStringList
diff --git a/kttsd/libkttsd/notify.cpp b/kttsd/libkttsd/notify.cpp
new file mode 100644
index 0000000..fd28587
--- /dev/null
+++ b/kttsd/libkttsd/notify.cpp
@@ -0,0 +1,177 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Notification Action constants and utility functions.
+ -------------------
+ Copyright : (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ Current Maintainer: 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+
+// Qt includes.
+#include <qstring.h>
+#include <qstringlist.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <klocale.h>
+#include <kstaticdeleter.h>
+
+// KTTS includes.
+#include "notify.h"
+
+static QStringList* s_actionNames = 0;
+static KStaticDeleter<QStringList> s_actionNames_sd;
+
+static QStringList* s_actionDisplayNames = 0;
+static KStaticDeleter<QStringList> s_actionDisplayNames_sd;
+
+static void notifyaction_init()
+{
+ if ( !s_actionNames )
+ {
+ s_actionNames_sd.setObject(s_actionNames, new QStringList);
+ s_actionNames->append( "SpeakEventName" );
+ s_actionNames->append( "SpeakMsg" );
+ s_actionNames->append( "DoNotSpeak" );
+ s_actionNames->append( "SpeakCustom" );
+
+ s_actionDisplayNames_sd.setObject(s_actionDisplayNames, new QStringList);
+ s_actionDisplayNames->append( i18n("Speak event name") );
+ s_actionDisplayNames->append( i18n("Speak the notification message") );
+ s_actionDisplayNames->append( i18n("Do not speak the notification") );
+ s_actionDisplayNames->append( i18n("Speak custom text:") );
+ }
+}
+
+/*static*/ int NotifyAction::count()
+{
+ notifyaction_init();
+ return s_actionNames->count();
+}
+
+/*static*/ QString NotifyAction::actionName( const int action )
+{
+ notifyaction_init();
+ return (*s_actionNames)[ action ];
+}
+
+/*static*/ int NotifyAction::action( const QString& actionName )
+{
+ notifyaction_init();
+ return s_actionNames->findIndex( actionName );
+}
+
+/*static*/ QString NotifyAction::actionDisplayName( const int action )
+{
+ notifyaction_init();
+ return (*s_actionDisplayNames)[ action ];
+}
+
+/*static*/ QString NotifyAction::actionDisplayName( const QString& actionName )
+{
+ notifyaction_init();
+ return (*s_actionDisplayNames)[ action( actionName ) ];
+}
+
+// --------------------------------------------------------------------
+
+static QStringList* s_presentNames = 0;
+static KStaticDeleter<QStringList> s_presentNames_sd;
+
+static QStringList* s_presentDisplayNames = 0;
+static KStaticDeleter<QStringList> s_presentDisplayNames_sd;
+
+static void notifypresent_init()
+{
+ if ( !s_presentNames )
+ {
+ s_presentNames_sd.setObject( s_presentNames, new QStringList );
+ s_presentNames->append( "None" );
+ s_presentNames->append( "Dialog" );
+ s_presentNames->append( "Passive" );
+ s_presentNames->append( "DialogAndPassive" );
+ s_presentNames->append( "All" );
+
+ s_presentDisplayNames_sd.setObject( s_presentDisplayNames, new QStringList );
+ s_presentDisplayNames->append( i18n("none") );
+ s_presentDisplayNames->append( i18n("notification dialogs") );
+ s_presentDisplayNames->append( i18n("passive popups") );
+ s_presentDisplayNames->append( i18n("notification dialogs and passive popups") );
+ s_presentDisplayNames->append( i18n("all notifications" ) );
+ }
+}
+
+/*static*/ int NotifyPresent::count()
+{
+ notifypresent_init();
+ return s_presentNames->count();
+}
+
+/*static*/ QString NotifyPresent::presentName( const int present )
+{
+ notifypresent_init();
+ return (*s_presentNames)[ present ];
+}
+
+/*static*/ int NotifyPresent::present( const QString& presentName )
+{
+ notifypresent_init();
+ return s_presentNames->findIndex( presentName );
+}
+
+/*static*/ QString NotifyPresent::presentDisplayName( const int present )
+{
+ notifypresent_init();
+ return (*s_presentDisplayNames)[ present ];
+}
+
+/*static*/ QString NotifyPresent::presentDisplayName( const QString& presentName )
+{
+ notifypresent_init();
+ return (*s_presentDisplayNames)[ present( presentName ) ];
+}
+
+// --------------------------------------------------------------------
+
+/**
+ * Retrieves the displayable name for an event source.
+ */
+/*static*/ QString NotifyEvent::getEventSrcName(const QString& eventSrc, QString& iconName)
+{
+ QString configFilename = eventSrc + QString::fromLatin1( "/eventsrc" );
+ KConfig* config = new KConfig( configFilename, true, false, "data" );
+ config->setGroup( QString::fromLatin1( "!Global!" ) );
+ QString appDesc = config->readEntry( "Comment", i18n("No description available") );
+ iconName = config->readEntry( "IconName" );
+ delete config;
+ return appDesc;
+}
+
+/**
+ * Retrieves the displayable name for an event from an event source.
+ */
+/*static*/ QString NotifyEvent::getEventName(const QString& eventSrc, const QString& event)
+{
+ QString eventName;
+ QString configFilename = eventSrc + QString::fromLatin1( "/eventsrc" );
+ KConfig* config = new KConfig( configFilename, true, false, "data" );
+ if ( config->hasGroup( event ) )
+ {
+ config->setGroup( event );
+ eventName = config->readEntry( QString::fromLatin1( "Comment" ),
+ config->readEntry( QString::fromLatin1( "Name" )));
+ }
+ delete config;
+ return eventName;
+}
+
diff --git a/kttsd/libkttsd/notify.h b/kttsd/libkttsd/notify.h
new file mode 100644
index 0000000..2a8162d
--- /dev/null
+++ b/kttsd/libkttsd/notify.h
@@ -0,0 +1,85 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Notification Action constants and utility functions.
+ -------------------
+ Copyright : (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ Current Maintainer: 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _NOTIFYACTION_H
+#define _NOTIFYACTION_H
+
+#include <kdemacros.h>
+
+class QString;
+
+class KDE_EXPORT NotifyAction
+{
+
+public:
+
+ enum NotifyActions
+ {
+ SpeakEventName,
+ SpeakMsg,
+ DoNotSpeak,
+ SpeakCustom
+ };
+
+ static int count();
+ static QString actionName( const int action );
+ static int action( const QString& actionName );
+ static QString actionDisplayName( const int action );
+ static QString actionDisplayName( const QString& actionName );
+};
+
+// --------------------------------------------------------------------
+
+class KDE_EXPORT NotifyPresent
+{
+
+public:
+
+ enum NotifyPresentations
+ {
+ None,
+ Dialog,
+ Passive,
+ DialogAndPassive,
+ All
+ };
+
+ static int count();
+ static QString presentName( const int present );
+ static int present( const QString& presentName );
+ static QString presentDisplayName( const int present );
+ static QString presentDisplayName( const QString& presentName );
+};
+
+// --------------------------------------------------------------------
+
+class KDE_EXPORT NotifyEvent
+{
+
+public:
+ /**
+ * Retrieves the displayable name for an event source.
+ */
+ static QString getEventSrcName(const QString& eventSrc, QString& iconName);
+
+ /**
+ * Retrieves the displayable name for an event from an event source.
+ */
+ static QString getEventName(const QString& eventSrc, const QString& event);
+};
+
+#endif // _NOTIFYACTION_H
diff --git a/kttsd/libkttsd/player.h b/kttsd/libkttsd/player.h
new file mode 100644
index 0000000..ff4d240
--- /dev/null
+++ b/kttsd/libkttsd/player.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ begin : Sun Feb 17 2002
+ copyright : (C) 2002 - 2004 by Scott Wheeler
+ email : wheeler@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PLAYER_H
+#define PLAYER_H
+
+#include <qobject.h>
+#include <qstringlist.h>
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+#include "kglobal.h"
+#include "klocale.h"
+
+// #include "filehandle.h"
+
+class KDE_EXPORT Player : virtual public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual ~Player() {}
+
+// virtual void play(const FileHandle &file = FileHandle::null()) = 0;
+ virtual void startPlay(const QString& file) = 0;
+ virtual void pause() = 0;
+ virtual void stop() = 0;
+
+ virtual void setVolume(float volume = 1.0) = 0;
+ virtual float volume() const = 0;
+
+ virtual bool playing() const = 0;
+ virtual bool paused() const = 0;
+
+ virtual int totalTime() const = 0;
+ virtual int currentTime() const = 0;
+ virtual int position() const = 0; // in this case not really the percent
+
+ virtual void seek(int seekTime) = 0;
+ virtual void seekPosition(int position) = 0;
+
+ virtual QStringList getPluginList( const QCString& classname ) {
+ Q_UNUSED(classname);
+ return QStringList();
+ }
+ virtual void setSinkName(const QString &sinkName) { Q_UNUSED(sinkName); }
+ virtual bool requireVersion(uint major, uint minor, uint micro) {
+ Q_UNUSED(major);
+ Q_UNUSED(minor);
+ Q_UNUSED(micro);
+ return true;
+ }
+ virtual void setDebugLevel(uint level) { Q_UNUSED(level); }
+ virtual void setPeriodSize(uint periodSize) { Q_UNUSED(periodSize); }
+ virtual void setPeriods(uint periods) {Q_UNUSED(periods); }
+
+protected:
+ Player(QObject* parent = 0, const char* name = 0, const QStringList& args=QStringList() ) :
+ QObject(parent, name) {
+ Q_UNUSED(args);
+ }
+
+};
+
+#endif
diff --git a/kttsd/libkttsd/pluginconf.cpp b/kttsd/libkttsd/pluginconf.cpp
new file mode 100644
index 0000000..d2fb4b6
--- /dev/null
+++ b/kttsd/libkttsd/pluginconf.cpp
@@ -0,0 +1,245 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ This file is the templates for the configuration plug ins.
+ -------------------
+ Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// C++ library includes.
+#include <stdlib.h>
+#include <sys/param.h>
+
+// Qt includes.
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qstring.h>
+
+// KDE includes.
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+// PluginConf includes.
+#include "pluginconf.h"
+#include "pluginconf.moc"
+
+/**
+* Constructor
+*/
+PlugInConf::PlugInConf( QWidget *parent, const char *name) : QWidget(parent, name){
+ kdDebug() << "PlugInConf::PlugInConf: Running" << endl;
+ KGlobal::locale()->insertCatalogue("kttsd");
+ QString systemPath(getenv("PATH"));
+ // kdDebug() << "Path is " << systemPath << endl;
+ m_path = QStringList::split(":", systemPath);
+ m_player = 0;
+}
+
+/**
+* Destructor.
+*/
+PlugInConf::~PlugInConf(){
+ kdDebug() << "PlugInConf::~PlugInConf: Running" << endl;
+ delete m_player;
+}
+
+/**
+* This method is invoked whenever the module should read its
+* configuration (most of the times from a config file) and update the
+* user interface. This happens when the user clicks the "Reset" button in
+* the control center, to undo all of his changes and restore the currently
+* valid settings. Note that kttsmgr calls this when the plugin is
+* loaded, so it not necessary to call it in your constructor.
+* The plugin should read its configuration from the specified group
+* in the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* loading your configuration.
+*/
+void PlugInConf::load(KConfig* /*config*/, const QString& /*configGroup*/){
+ kdDebug() << "PlugInConf::load: Running" << endl;
+}
+
+/**
+* This function gets called when the user wants to save the settings in
+* the user interface, updating the config files or wherever the
+* configuration is stored. The method is called when the user clicks "Apply"
+* or "Ok". The plugin should save its configuration in the specified
+* group of the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* saving your configuration.
+*/
+void PlugInConf::save(KConfig* /*config*/, const QString& /*configGroup*/){
+ kdDebug() << "PlugInConf::save: Running" << endl;
+}
+
+/**
+* This function is called to set the settings in the module to sensible
+* default values. It gets called when hitting the "Default" button. The
+* default values should probably be the same as the ones the application
+* uses when started without a config file. Note that defaults should
+* be applied to the on-screen widgets; not to the config file.
+*/
+void PlugInConf::defaults(){
+ kdDebug() << "PlugInConf::defaults: Running" << endl;
+}
+
+/**
+* Indicates whether the plugin supports multiple instances. Return
+* False if only one instance of the plugin can run at a time.
+* @return True if multiple instances are possible.
+*
+* It is assumed that most plugins can support multiple instances.
+* A plugin must override this method and return false if it
+* cannot support multiple instances.
+*/
+bool PlugInConf::supportsMultiInstance() { return true; }
+
+/**
+* This function informs the plugin of the desired language to be spoken
+* by the plugin. The plugin should attempt to adapt itself to the
+* specified language code, choosing sensible defaults if necessary.
+* If the passed-in code is QString::null, no specific language has
+* been chosen.
+* @param lang The desired language code or Null if none.
+*
+* If the plugin is unable to support the desired language, that is OK.
+*/
+void PlugInConf::setDesiredLanguage(const QString& /*lang*/ ) { }
+
+/**
+* Return fully-specified talker code for the configured plugin. This code
+* uniquely identifies the configured instance of the plugin and distinquishes
+* one instance from another. If the plugin has not been fully configured,
+* i.e., cannot yet synthesize, return QString::null.
+* @return Fully-specified talker code.
+*/
+QString PlugInConf::getTalkerCode() { return QString::null; }
+
+/**
+* Return a list of all the languages currently supported by the plugin.
+* Note that as the user configures your plugin, the language choices may become
+* narrower. For example, once the user has picked a voice file, the language
+* may be determined. If your plugin has just been added and no configuration
+* choices have yet been made, return a list of all possible languages the
+* plugin might support.
+* If your plugin cannot yet determine the languages supported, return Null.
+* If your plugin can support any language, return Null.
+* @return A QStringList of supported language codes, or Null if unknown.
+*/
+QStringList PlugInConf::getSupportedLanguages() { return QStringList(); }
+
+/**
+* Return the full path to any program in the $PATH environmental variable
+* @param name The name of the file to search for.
+* @returns The path to the file on success, a blank QString
+* if its not found.
+*/
+QString PlugInConf::getLocation(const QString &name) {
+ // Iterate over the path and see if 'name' exists in it. Return the
+ // full path to it if it does. Else return an empty QString.
+
+ // If it's a file or a symlink pointing to a file, that's cool.
+ QFileInfo fileinfo(name);
+ if (fileinfo.isFile() || (fileinfo.isSymLink() && QFileInfo(fileinfo.readLink()).isFile()))
+ return name;
+ kdDebug() << "PluginConf::getLocation: Searching for " << name << " in the path.." << endl;
+ kdDebug() << m_path << endl;
+ for(QStringList::iterator it = m_path.begin(); it != m_path.end(); ++it) {
+ QString fullName = *it;
+
+ fullName += "/";
+ fullName += name;
+ fileinfo.setFile(fullName);
+ // The user either has the directory of the file in the path...
+ if(fileinfo.isFile() || (fileinfo.isSymLink() && QFileInfo(fileinfo.readLink()).isFile())) {
+ return fullName;
+// kdDebug() << "PluginConf:getLocation: " << fullName << endl;
+ }
+ // ....Or the file itself in the path (slightly freaky but hey.)
+ else if(QFileInfo(*it).baseName().append(QString(".").append(QFileInfo(*it).extension())) == name) {
+ return fullName;
+// kdDebug() << "PluginConf:getLocation: " << fullName << endl;
+ }
+ }
+ return "";
+}
+
+/**
+* Breaks a language code into the language code and country code (if any).
+* @param languageCode Language code.
+* @return countryCode Just the country code part (if any).
+* @return Just the language code part.
+*/
+QString PlugInConf::splitLanguageCode(const QString& languageCode, QString& countryCode)
+{
+ QString locale = languageCode;
+ QString langCode;
+ QString charSet;
+ KGlobal::locale()->splitLocale(locale, langCode, countryCode, charSet);
+ return langCode;
+}
+
+/*static*/ QString PlugInConf::realFilePath(const QString &filename)
+{
+ char realpath_buffer[MAXPATHLEN + 1];
+ memset(realpath_buffer, 0, MAXPATHLEN + 1);
+
+ /* If the path contains symlinks, get the real name */
+ if (realpath( QFile::encodeName(filename).data(), realpath_buffer) != 0) {
+ // succes, use result from realpath
+ return QFile::decodeName(realpath_buffer);
+ }
+ return filename;
+}
+
+/*static*/ QString PlugInConf::testMessage(const QString& languageCode)
+{
+ QString key = "Name[" + languageCode + "]";
+ QString result;
+ QString def;
+ QFile file(locate("data", "kttsd/kcmkttsd_testmessage.desktop"));
+ if (file.open(IO_ReadOnly))
+ {
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ while ( !stream.atEnd() ) {
+ QString line = stream.readLine(); // line of text excluding '\n'
+ QStringList keyAndValue = QStringList::split("=", line);
+ if (keyAndValue.count() == 2)
+ {
+ if (keyAndValue[0] == key)
+ {
+ result = keyAndValue[1];
+ break;
+ }
+ if (keyAndValue[0] == "Name") def = keyAndValue[1];
+ }
+ }
+ file.close();
+ }
+ if (result.isEmpty())
+ {
+ result = def;
+ if (result.isEmpty()) result = "The text-to-speech system seems to be functioning properly.";
+ }
+ return result;
+}
+
+/**
+* Player object that can be used by the plugin for testing playback of synthed files.
+*/
+void PlugInConf::setPlayer(TestPlayer* player) { m_player = player; }
+TestPlayer* PlugInConf::getPlayer() { return m_player; }
+
diff --git a/kttsd/libkttsd/pluginconf.h b/kttsd/libkttsd/pluginconf.h
new file mode 100644
index 0000000..4c4647c
--- /dev/null
+++ b/kttsd/libkttsd/pluginconf.h
@@ -0,0 +1,378 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ This file is the template for the configuration plug ins.
+ -------------------
+ Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _PLUGINCONF_H_
+#define _PLUGINCONF_H_
+
+// Qt includes.
+#include <qwidget.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+
+// KTTS includes.
+#include "testplayer.h"
+
+/**
+* @interface PlugInConf
+*
+* pluginconf - the KDE Text-to-Speech Deamon Plugin Configuration API.
+*
+* @version 1.0 Draft 2
+*
+* This class defines the interface that plugins to KTTSMGR must implement.
+*
+* @warning The pluginconf interface is still being developed and is likely
+* to change in the future.
+*
+* A KTTSD Plugin interfaces between KTTSD and a speech engine.
+* A PlugInConf provides an on-screen widget for configuring the plugin for use
+* with KTTSD.
+*
+* @section guidelines General Guidelines
+*
+* - The configuration widget should be no larger than TODO pixels.
+* - Do not supply Load, Save, Cancel, or OK buttons. Those are provided by KTTSMGR.
+* - Try to supply a Test button so that users can test the configuration before
+* saving it.
+* - Your configuration widget will be running inside a KPart.
+* - Whenever the user changes something in your on-screen widget, emit the
+* @ref changed signal.
+* - If a plugin can automatically configure itself, i.e., locate voice files,
+* set default values, etc., it should do so when it is first added to KTTSMGR.
+*
+* @section multiinstance Multiple Instances
+*
+* If it is possible to run multiple simultaneous instances of your synthesis engine,
+* return True from the @ref supportsMultiInstance method. The user will be able to
+* configure multiple instances of your plugin, each with a different set of
+* talker attributes.
+*
+* If you cannot run multiple simultaneous instances of your synthesis engine,
+* or your plugin has a fixed set of talker attributes (only one language, voice,
+* gender, volume, and speed), return False from @ref supportsMultiInstance.
+*
+* @section language Language Support
+*
+* Some plugins support only one language. For them, return the appropriate language
+* code when @ref getSupportedLanguages is called.
+*
+* If your plugin can support multiple languages, your task is a little more
+* complicated. The best way to handle this is to install a @e voices file with
+* your plugin that lists all the supported languages, voice files, genders, etc.
+* that are possible. When your plugin is added to KTTSMGR,
+* @ref getSupportedLanguages will be called. Return a list of all the possible
+* languages supported, even if the user hasn't yet picked a voice file in your
+* configuration, or even told your where the voice files are.
+*
+* There are three ways that users and applications pick a language code for your
+* plugin:
+* - The user picks a code from among the languages you returned in
+* @ref getSupportedLanguages, or
+* - The user picks your plugin and uses your configuration widget to pick a voice
+* file or other configuration option that determines the language, or
+* - An application requests a plugin with specific language support.
+*
+* If possible, avoid making the user pick a language code in your plugin.
+*
+* In the first and third cases, the chosen language code will be passed to your
+* plugin when @ref setDesiredLanguage is called. If you can satisfy this
+* language code, good, but it is possible that once the user has begun
+* configuring your plugin, you find that you cannot support the desired
+* language. Perhaps a needed voice file is missing. That is OK.
+* You'll inform KTTSMGR of the actual language code when KTTSMGR
+* calls @ref getTalkerCode (see below). Note that you should not limit the
+* users choices based on the @ref setDesiredLanguage. A user might start
+* out configuring your plugin for one language, and then change his or her
+* mind to a different language.
+*
+* Also note that language codes may also include an appended country code.
+* For example, "en_GB" for British English. When @ref getSupportedLanguages is
+* called, you should return as specific a list as possible. For example,
+* if your plugin supports both American and British English, your returned
+* list would include "en_GB" and "en_US". When @ref setDesiredLanguage is
+* called, a country code may or may not be included. If included and your
+* plugin supports the language, but not the specific country variant,
+* your plugin should nevertheless attempt to satisfy the request, returning
+* the actual supported language and country when @ref getTalkerCode is called.
+*
+* @section talkercodes Talker Codes
+*
+* Review the section on Talkers in kspeech.h.
+*
+* When your plugin is added to the KTTSMGR, @ref getSupportedLanguages
+* will be called followed by @ref setDesiredLanguage and @ref load.
+* Note that the configuration file will most likely be empty when
+* @ref load is called.
+
+* Next, @ref getTalkerCode
+* will be called. If your plugin can automatically configure itself to the desired
+* language, it should do so and return a fully-specified talker code. If your
+* plugin is not yet ready and requires user help, return QString::null. Note that
+* @ref setDesiredLanguage may be Null, in which case, you should allow the
+* user to configure your plugin to any of your supported languages.
+*
+* When your plugin has been configured enough to begin synthesis, return a
+* fully-specified talker code in @ref getTalkerCode().
+*
+* Here is guidance for what you should return for each of the talker attributes
+* when @ref getTalkerCode is called:
+*
+* - @e lang. If user has completed configuring your plugin, i.e., it is
+* ready to begin synthesizing, return the ISO 639-1 language code
+* for the language it can synthesize. If your plugin is not yet
+* fully configured, you should return QString::null for the entire
+* talker code. If your plugin supports a specific national version
+* of a language, that should also be included using the ISO 3166
+* country code separated from the language code by underscore (_).
+* For example, if your plugin synthesizes American English, you would
+* return "en_US". If British English, "en_BR". And if
+* non-specific English, just "en".
+* - @e synthesizer. The name of your plugin. Keep short, but long enough to
+* distinquish different implementations. For example,
+* Festival Int, Flite, Hadifix. Use only letters, numbers
+* spaces, and underscores (_) in your plugin name.
+* - @e gender. May be "male", "female", or "neutral".
+* - @e name. The voice code. If your plugin does not support voices,
+* return "fixed".
+* - @e volume. May be "medium", "loud", or "soft". If your plugin does not support
+* configurable volume, return "medium".
+* - @e rate. May be "medium", "fast", or "slow". If your plugin does not support
+* configurable speed, return "medium".
+*
+* The order of the attributes you return does not matter. Here is an example of
+* a fully-specified talker code.
+*
+* lang="en" name="Kal" gender="male" volume="soft" rate="fast"
+* synthesizer="Festival Interactive"
+*
+* Do not return translated values for the Talker Code attributes. All English.
+*
+* Each time your plugin emits the @ref changed signal, @ref getTalkerCode will be called.
+* The configuration dialog OK button will be disabled until you return a non-null
+* Talker Code.
+*
+* It is possible that your plugin does not know the language supported. The generic
+* Command plugin is example of such a case, since the user enters an arbitrary command.
+* In this case, return the value from the @ref setDesiredLanguage call. It is possible
+* that @ref setDesiredLanguage is Null. That is OK. In this case, KTTSMGR will prompt
+* the user for the language code.
+*
+* @section loadandsavemethods Load and Save Methods
+*
+* The @ref load and @ref save methods are called by KTTSMGR so that your plugin
+* can load and save configuration options from the configuration file.
+* These methods have two parameters, a @e config object and a @e configGroup string.
+*
+* Plugins that do not support multiple instances (return False from
+* @ref supportsMultiInstance), should simply call config->setGroup(configGroup)
+* before loading or saving their configuration.
+*
+* If your plugin supports multiple instances, it is slightly more complicated.
+* Typically, there will be configuration options that apply to all instances
+* of the plugin and there will be options that apply only to the specific
+* configured instance of the plugin. To load or save the instance-specific
+* options, call config->setGroup(configGroup). For options that apply
+* to all instances of the plugin, call config->setGroup() with a group name
+* that contains your plugin's name. For example,
+* config->setGroup("Festival Defaults").
+*
+* For example, when first added to KTTSMGR, the Festival plugin needs to know the path to
+* the directory containing all the installed voice files. It is best for a plugin
+* to try to locate these resources automatically, but if it can't find them,
+* when the user has told it where they are, it is a good idea to save this information
+* in the all-instances group. In this way, the next time the plugin
+* is added to KTTSMGR, or another instance is added, it will be able to find them
+* automatically.
+*
+* @ref setDesiredLanguage is always called just prior to @ref load, therefore
+* it is not necessary to save the language code, unless your plugin needs it in
+* order to synthesize speech.
+*/
+
+class KDE_EXPORT PlugInConf : public QWidget{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ PlugInConf( QWidget *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor
+ */
+ virtual ~PlugInConf();
+
+ /**
+ * This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. Note that KTTSMGR calls this when the plugin is
+ * loaded, so it not necessary to call it in your constructor.
+ * The plugin should read its configuration from the specified group
+ * in the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * loading your configuration.
+ *
+ * When a plugin is first added to KTTSMGR, @e load will be called with
+ * a Null @e configGroup. In this case, the plugin will not have
+ * any instance-specific parameters to load, but it may still wish
+ * to load parameters that apply to all instances of the plugin.
+ *
+ * @see loadandsavemethods
+ */
+ virtual void load(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok". The plugin should save its configuration in the specified
+ * group of the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * saving your configuration.
+ *
+ * @ref setDesiredLanguage is always called just prior to @ref load, therefore
+ * it is not necessary to save the language code, unless your plugin needs it in
+ * order to synthesize speech.
+ */
+ virtual void save(KConfig *config, const QString &configGroup);
+
+ /**
+ * This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file. Note that defaults should
+ * be applied to the on-screen widgets; not to the config file.
+ */
+ virtual void defaults();
+
+ /**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can run at a time, or
+ * if your plugin is limited to a single language, voice, gender, volume,
+ * and speed.
+ * @return True if multiple instances are possible.
+ */
+ virtual bool supportsMultiInstance();
+
+ /**
+ * This function informs the plugin of the desired language to be spoken
+ * by the plugin. The plugin should attempt to adapt itself to the
+ * specified language code, choosing sensible defaults if necessary.
+ * If the passed-in code is QString::null, no specific language has
+ * been chosen.
+ * @param lang The desired language code or Null if none.
+ *
+ * If the plugin is unable to support the desired language, that is OK.
+ * Language codes are given by ISO 639-1 and are in lowercase.
+ * The code may also include an ISO 3166 country code in uppercase
+ * separated from the language code by underscore (_). For
+ * example, en_GB. If your plugin supports the given language, but
+ * not the given country, treat it as though the country
+ * code were not specified, i.e., adapt to the given language.
+ */
+ virtual void setDesiredLanguage(const QString &lang);
+
+ /**
+ * Return fully-specified talker code for the configured plugin. This code
+ * uniquely identifies the configured instance of the plugin and distinquishes
+ * one instance from another. If the plugin has not been fully configured,
+ * i.e., cannot yet synthesize, return QString::null.
+ * @return Fully-specified talker code.
+ */
+ virtual QString getTalkerCode();
+
+ /**
+ * Return a list of all the languages possibly supported by the plugin.
+ * If your plugin can support any language, return Null.
+ * @return A QStringList of supported language and optional country
+ * codes, or Null if any.
+ *
+ * The languge codes are given in ISO 639-1. Lowercase should be used.
+ * If your plugin supports various national forms of a language, ISO 3166
+ * country codes should also be include in upperase and separated from
+ * the language code with underscore (_). Examples:
+ * en
+ * en_US
+ * en_GB
+ * es
+ * es_CL
+ * The list you return should be as specific as practicable.
+ */
+ virtual QStringList getSupportedLanguages();
+
+ /**
+ * Player object that can be used by the plugin for testing playback of synthed files.
+ */
+ void setPlayer(TestPlayer* player);
+ TestPlayer* getPlayer();
+
+ static QString realFilePath(const QString &filename);
+
+ static QString testMessage(const QString& languageCode);
+
+ public slots:
+ /**
+ * This slot is used internally when the configuration is changed. It is
+ * typically connected to signals from the widgets of the configuration
+ * and should emit the @ref changed signal.
+ */
+ void configChanged(){
+ kdDebug() << "PlugInConf::configChanged: Running"<< endl;
+ emit changed(true);
+ };
+
+ signals:
+ /**
+ * This signal indicates that the configuration has been changed.
+ * It should be emitted whenever user changes something in the configuration widget.
+ */
+ void changed(bool);
+
+ protected:
+ /**
+ * Searches the $PATH variable for any file. If that file exists in the PATH, or
+ * is contained in any directory in the PATH, it returns the full path to it.
+ * @param name The name of the file to search for.
+ * @returns The path to the file on success, a blank QString
+ * if its not found.
+ */
+ QString getLocation(const QString &name);
+
+ /**
+ * Breaks a language code into the language code and country code (if any).
+ * @param languageCode Language code.
+ * @return countryCode Just the country code part (if any).
+ * @return Just the language code part.
+ */
+ QString splitLanguageCode(const QString& languageCode, QString& countryCode);
+
+ /// The system path in a QStringList.
+ QStringList m_path;
+
+ TestPlayer* m_player;
+};
+
+#endif //_PLUGINCONF_H_
diff --git a/kttsd/libkttsd/pluginproc.cpp b/kttsd/libkttsd/pluginproc.cpp
new file mode 100644
index 0000000..5c835a6
--- /dev/null
+++ b/kttsd/libkttsd/pluginproc.cpp
@@ -0,0 +1,292 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ This file is the template for the processing plug ins.
+ -------------------
+ Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qstring.h>
+#include <qtextcodec.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+
+// PlugInProc includes.
+#include "pluginproc.h"
+#include "pluginproc.moc"
+
+/**
+* Constructor
+*/
+PlugInProc::PlugInProc( QObject *parent, const char *name) : QObject(parent, name){
+ // kdDebug() << "PlugInProc::PlugInProc: Running" << endl;
+}
+
+/**
+* Destructor
+*/
+PlugInProc::~PlugInProc(){
+ // kdDebug() << "PlugInProc::~PlugInProc: Running" << endl;
+}
+
+/**
+* Initializate the speech plugin.
+*/
+bool PlugInProc::init(KConfig* /*config*/, const QString& /*configGroup*/){
+ // kdDebug() << "PlugInProc::init: Running" << endl;
+ return false;
+}
+
+/**
+* Say a text. Synthesize and audibilize it.
+* @param text The text to be spoken.
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void PlugInProc::sayText(const QString& /*text*/){
+ // kdDebug() << "PlugInProc::sayText: Running" << endl;
+}
+
+/**
+* Synthesize text into an audio file, but do not send to the audio device.
+* @param text The text to be synthesized.
+* @param suggestedFilename Full pathname of file to create. The plugin
+* may ignore this parameter and choose its own
+* filename. KTTSD will query the generated
+* filename using getFilename().
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void PlugInProc::synthText(const QString& /*text*/, const QString& /*suggestedFilename*/) { }
+
+/**
+* Get the generated audio filename from synthText.
+* @return Name of the audio file the plugin generated.
+* Null if no such file.
+*
+* The plugin must not re-use the filename.
+*/
+QString PlugInProc::getFilename() { return QString::null; }
+
+/**
+* Stop current operation (saying or synthesizing text).
+* This function only makes sense in asynchronus modes.
+* The plugin should return to the psIdle state.
+*/
+void PlugInProc::stopText(){
+ // kdDebug() << "PlugInProc::stopText: Running" << endl;
+}
+
+/**
+* Return the current state of the plugin.
+* This function only makes sense in asynchronous mode.
+* @return The pluginState of the plugin.
+*
+* @ref pluginState
+*/
+pluginState PlugInProc::getState() { return psIdle; }
+
+/**
+* Acknowledges a finished state and resets the plugin state to psIdle.
+*
+* If the plugin is not in state psFinished, nothing happens.
+* The plugin may use this call to do any post-processing cleanup,
+* for example, blanking the stored filename (but do not delete the file).
+* Calling program should call getFilename prior to ackFinished.
+*/
+void PlugInProc::ackFinished() { }
+
+/**
+* Returns True if the plugin supports asynchronous processing,
+* i.e., returns immediately from sayText or synthText.
+* @return True if this plugin supports asynchronous processing.
+*/
+bool PlugInProc::supportsAsync() { return false; }
+
+/**
+* Returns True if the plugin supports synthText method,
+* i.e., is able to synthesize text to a sound file without
+* audibilizing the text.
+* @return True if this plugin supports synthText method.
+*/
+bool PlugInProc::supportsSynth() { return false; }
+
+/**
+* Returns the name of an XSLT stylesheet that will convert a valid SSML file
+* into a format that can be processed by the synth. For example,
+* The Festival plugin returns a stylesheet that will convert SSML into
+* SABLE. Any tags the synth cannot handle should be stripped (leaving
+* their text contents though). The default stylesheet strips all
+* tags and converts the file to plain text.
+* @return Name of the XSLT file.
+*/
+QString PlugInProc::getSsmlXsltFilename()
+{
+ return KGlobal::dirs()->resourceDirs("data").last() + "kttsd/xslt/SSMLtoPlainText.xsl";
+}
+
+/**
+* Given the name of a codec, returns the QTextCodec for the name.
+* Handles the following "special" codec names:
+* Local The user's current Locale codec.
+* Latin1 Latin1 (ISO 8859-1)
+* Unicode UTF-16
+* @param codecName Name of desired codec.
+* @return The codec object. Calling program must not delete this object
+* as it is a reference to an existing QTextCodec object.
+*
+* Caution: Do not pass translated codec names to this routine.
+*/
+/*static*/ QTextCodec* PlugInProc::codecNameToCodec(const QString &codecName)
+{
+ QTextCodec* codec = 0;
+ if (codecName == "Local")
+ codec = QTextCodec::codecForLocale();
+ else if (codecName == "Latin1")
+ codec = QTextCodec::codecForName("ISO8859-1");
+ else if (codecName == "Unicode")
+ codec = QTextCodec::codecForName("utf16");
+ else
+ codec = QTextCodec::codecForName(codecName.latin1());
+ if (!codec)
+ {
+ kdDebug() << "PluginProc::codecNameToCodec: Invalid codec name " << codecName << endl;
+ kdDebug() << "PluginProc::codecNameToCodec: Defaulting to ISO 8859-1" << endl;
+ codec = QTextCodec::codecForName("ISO8859-1");
+ }
+ return codec;
+}
+
+/**
+* Builds a list of codec names, suitable for display in a QComboBox.
+* The list includes the 3 special codec names (translated) at the top:
+* Local The user's current Locale codec.
+* Latin1 Latin1 (ISO 8859-1)
+* Unicode UTF-16
+*/
+/*static*/ QStringList PlugInProc::buildCodecList()
+{
+ // kdDebug() << "PlugInConf::buildCodecList: Running" << endl;
+ QStringList codecList;
+ QString local = i18n("Local")+" (";
+ local += QTextCodec::codecForLocale()->name();
+ local += ")";
+ codecList.append(local);
+ codecList.append(i18n("Latin1"));
+ codecList.append(i18n("Unicode"));
+ for (int i = 0; (QTextCodec::codecForIndex(i)); ++i )
+ codecList.append(QTextCodec::codecForIndex(i)->name());
+ return codecList;
+}
+
+/**
+* Given the name of a codec, returns index into the codec list.
+* Handles the following "special" codec names:
+* Local The user's current Locale codec.
+* Latin1 Latin1 (ISO 8859-1)
+* Unicode UTF-16
+* @param codecName Name of the codec.
+* @param codecList List of codec names. The first 3 entries may be translated names.
+* @return QTextCodec object. Caller must not delete this object.
+*
+* Caution: Do not pass translated codec names to this routine in codecName parameter.
+*/
+/*static*/ int PlugInProc::codecNameToListIndex(const QString &codecName, const QStringList &codecList)
+{
+ int codec;
+ if (codecName == "Local")
+ codec = PlugInProc::Local;
+ else if (codecName == "Latin1")
+ codec = PlugInProc::Latin1;
+ else if (codecName == "Unicode")
+ codec = PlugInProc::Unicode;
+ else {
+ codec = PlugInProc::Local;
+ const uint codecListCount = codecList.count();
+ for (uint i = PlugInProc::UseCodec; i < codecListCount; ++i )
+ if (codecName == codecList[i])
+ codec = i;
+ }
+ return codec;
+}
+
+/**
+* Given index into codec list, returns the codec object.
+* @param codecNum Index of the codec.
+* @param codecList List of codec names. The first 3 entries may be translated names.
+* @return QTextCodec object. Caller must not delete this object.
+*/
+/*static*/ QTextCodec* PlugInProc::codecIndexToCodec(int codecNum, const QStringList &codecList)
+{
+ QTextCodec* codec = 0;
+ switch (codecNum) {
+ case PlugInProc::Local:
+ codec = QTextCodec::codecForLocale();
+ break;
+ case PlugInProc::Latin1:
+ codec = QTextCodec::codecForName("ISO8859-1");
+ break;
+ case PlugInProc::Unicode:
+ codec = QTextCodec::codecForName("utf16");
+ break;
+ default:
+ codec = QTextCodec::codecForName(codecList[codecNum].latin1());
+ break;
+ }
+ if (!codec)
+ {
+ kdDebug() << "PlugInProc::codecIndexToCodec: Invalid codec index " << codecNum << endl;
+ kdDebug() << "PlugInProc::codecIndexToCodec: Defaulting to ISO 8859-1" << endl;
+ codec = QTextCodec::codecForName("ISO8859-1");
+ }
+ return codec;
+}
+
+/**
+* Given index into codec list, returns the codec Name.
+* Handles the following "special" codec names:
+* Local The user's current Locale codec.
+* Latin1 Latin1 (ISO 8859-1)
+* Unicode UTF-16
+* @param codecNum Index of the codec.
+* @param codecList List of codec names. The first 3 entries may be translated names.
+* @return Untranslated name of the codec.
+*/
+/*static*/ QString PlugInProc::codecIndexToCodecName(int codecNum, const QStringList &codecList)
+{
+ QString codecName;
+ switch (codecNum) {
+ case PlugInProc::Local:
+ codecName = "Local";
+ break;
+ case PlugInProc::Latin1:
+ codecName = "Latin1";
+ break;
+ case PlugInProc::Unicode:
+ codecName = "Unicode";
+ break;
+ default:
+ if ((uint)codecNum < codecList.count())
+ codecName = codecList[codecNum];
+ else
+ {
+ kdDebug() << "PlugInProc::codecIndexToCodec: Invalid codec index " << codecNum << endl;
+ kdDebug() << "PlugInProc::codecIndexToCodec: Defaulting to ISO 8859-1" << endl;
+ codecName = "ISO8859-1";
+ }
+ }
+ return codecName;
+}
diff --git a/kttsd/libkttsd/pluginproc.h b/kttsd/libkttsd/pluginproc.h
new file mode 100644
index 0000000..c271ad3
--- /dev/null
+++ b/kttsd/libkttsd/pluginproc.h
@@ -0,0 +1,466 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ This file is the template for the processing plug ins.
+ -------------------
+ Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández
+ Copyright : (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _PLUGINPROC_H_
+#define _PLUGINPROC_H_
+
+#include <qobject.h>
+#include <qstring.h>
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+#include <kconfig.h>
+
+/**
+* @interface PlugInProc
+*
+* pluginproc - the KDE Text-to-Speech Deamon Plugin API.
+*
+* @version 1.0 Draft 1
+*
+* This class defines the interface that plugins to KTTSD must implement.
+*
+* @warning The pluginproc interface is still being developed and is likely
+* to change in the future.
+*
+* A KTTSD Plugin interfaces between KTTSD and a speech engine. It provides the methods
+* used by KTTSD to synthesize and/or audibilize text into speech.
+*
+* @section Goals
+*
+* The ideal plugin has the following features (listed most important to least important):
+* - It can synthesize text into an audio file without sending the audio to
+* the audio device. If the plugin can do this, the @ref supportsSynth function
+* should return True.
+* - When @ref stopText is called, is able to immediately stop an in-progress
+* synthesis or saying operation.
+* - It can operate asynchronously, i.e., returns immediately from a
+* @ref sayText or @ref synthText call and emits signals @ref sayFinished or
+* @ref synthFinished when completed. If the plugin can do this, the @ref supportsAsync
+* function should return True.
+*
+* As a plugin author, your goal is to provide all 3 of these features. However,
+* the speech engine you are working with might not be able to support all three
+* features.
+*
+* If a plugin cannot do all 3 of the features above, the next best combinations
+* are (from best to worst):
+*
+* - @ref supportsSynth returns True, @ref supportsAsync returns False, and
+* @stopText is able to immediately stop synthesis.
+* - @ref supportsSynth returns True, @ref supportsAsync returns False, and
+* @stopText returns immediately without stopping synthesis.
+* - @ref supportsAsync returns True, @ref supportsSynth returns False, and
+* @ref stopText is able to immediately stop saying.
+* - Both @ref supportsSynth and @ref supportsAsync both return False, and
+* @ref stopText is able to immediately stop saying.
+* - @ref supportsAsync returns True, @ref supportsSynth returns False, and
+* @ref stopText returns immediately without stopping saying.
+* - Both @ref supportsSynth and @ref supportsAsync both return False, and
+* @ref stopText returns immediately without stopping saying.
+*
+* Notice that aynchronous support is not essential because KTTSD is able to
+* provide aynchronous support by running the plugin in a separate thread.
+* The ability to immediately stop audio output (or support separate synthesis
+* only) is more important.
+*
+* @section Minimum Implementations
+*
+* All plugins should implement @ref init in order to initialize the speech engine,
+* set language codes, etc.
+*
+* If @ref supportsSynth return False, a plugin must implement @ref sayText .
+*
+* If @ref supportsSynth returns True, a plugin must implement the following methods:
+* - @ref synthText
+* - @ref getFilename
+* - @ref ackFinished
+* The plugin need not implement @ref sayText .
+*
+* If @ref supportsAsync returns True, the plugin must implement @ref getState .
+*
+* If @ref supportsAsync returns True, and @ref supportsSynth returns True,
+* a plugin must emit @ref synthFinished signal when synthesis is completed.
+*
+* If @ref supportsAsync returns True, and @ref supportsSynth returns False,
+* a plugin must emit @ref sayFinished signal when saying is completed.
+*
+* If @ref supportsAsync returns False, do not emit signals @ref sayFinished
+* or @ref synthFinished .
+*
+* @section Implementation Guidelines
+*
+* In no case, will a plugin need to perform more than one @ref sayText or
+* @ref synthText at a time. In other words, in asynchronous mode, KTTSD will
+* not call @ref sayText or @ref synthText again until @ref @getState returns
+* psFinished.
+*
+* If @ref supportsAsync returns False, KTTSD will run the plugin in a separate
+* QThread. As a consequence, the plugin must not make use of the KDE Library,
+* when @ref sayText or @ref synthText is called,
+* with the exception of KProcess and family (KProcIO, KShellProcess).
+* This restriction comes about because the KDE Libraries make use of the
+* main Qt event loop, which unfortunately, runs only in the main thread.
+* This restriction will likely be lifted in Qt 4 and later.
+*
+* Since the KDE library is not available from the @ref sayText and @ref synthText methods,
+* it is best if the plugin reads configuration settings in the @ref init method.
+* The KConfig object is passed as an argument to @ref init .
+*
+* If the synthesis engine requires a long initialization time (more than a second),
+* it is best if the plugin loads the speech engine from the @ref init method.
+* Otherwise, it will be more memory efficient to wait until @ref sayText or
+* @ref synthText is called, because it is possible that the plugin will be created
+* and initialized, but never used.
+*
+* All plugins, whether @ref supportsAsync returns True or not, should try to
+* implement @ref stopText . If a plugin returns False from @ref supportsAsync,
+* @ref stopText will be called from the main thread, while @ref sayText and/or
+* @ref synthText will be called from a separate thread. Hence, it will be
+* possible for @ref stopText to be called while @ref sayText or @ref synthText is
+* running. Keep this in mind when implementing the code.
+*
+* If the plugin returns True from @ref supportsAsync, you will of course
+* need to deal with similar issues. If you have to use QThreads
+* to implement asynchronous support, do not be concerned about emitting
+* the @ref sayFinished or @ref synthFinished signals from your threads, since
+* KTTSD will convert the received signals into postEvents and
+* return immediately.
+*
+* If it is not possible for @ref stopText to stop an in-progress operation, it
+* must not wait for the operation to complete, since this would block KTTSD.
+* Instead, simply return immediately. Usually, KTTSD will perform other operations
+* while waiting for the plugin to complete its operation. (See threadedplugin.cpp.)
+*
+* If the @ref stopText implementation returns before the operation has actually
+* completed, it must emit the @ref stopped() signal when it is actually completed.
+*
+* If a plugin returns True from @ref supportsAsync, and @ref stopText is called,
+* when the plugin has stopped or completed the operation, it must return psIdle
+* on the next call to @ref getState ; not psFinished. The following state diagram
+* might be helpful to understand this:
+*
+ @verbatim
+ psIdle <<----------------------------------------------------------
+ / \ ^
+ psSaying psSynthing --- stopText called and operation completed -->> ^
+ \ / ^
+ psFinished --- ackFinished called ------------------------------->> ^
+ @endverbatim
+*
+* If your plugin can't immediately stop an in-progress operation, the easiest
+* way to handle this is to set a flag when stopText is called, and then in your
+* getState() implementation, if the operation has completed, change the
+* psFinished state to psIdle, if the flag is set. See the flite plugin for
+* example code.
+*
+* If a plugin returns True from @ref supportsSynth, KTTSD will pass a suggested
+* filename in the @ref synthText call. The plugin should synthesize the text
+* into an audio file with the suggested name. If the synthesis engine does not
+* permit this, i.e., it will pick a filename of its own, that is OK. In either
+* case, the actual filename produced should be returned in @ref getFilename .
+* In no case may the plugin re-use this filename once @ref getFilename has been
+* called. If for some reason the synthesis engine cannot support this, the
+* plugin should copy the file to the suggested filename. The file must not be
+* locked when @ref getFilename is called. The file will be deleted when
+* KTTSD is finished using it.
+*
+* The preferred audio file format is wave, since this is the only format
+* guaranteed to be supported by KDE (aRts). Other formats may or may not be
+* supported on a user's machine.
+*
+* The plugin destructor should take care of terminating the speech engine.
+*
+* @section Error-handling Error Handling
+*
+* Plugins may emit the @ref error signal when an error occurs.
+*
+* When an error occurs, plugins should attempt to recover as best they can and
+* continue accepting @ref sayText or @ref synthText calls. For example,
+* if a speech engine emits an error in response to certain characters embedded
+* in synthesizing text, the plugin should discard the text and
+* emit signal @ref error with True as the first argument and the speech
+* engine's error message as the second argument. The plugin should then
+* treat the operation as a completed operation, i.e., return psFinished when
+* @ref getState is called.
+*
+* If the speech engine crashes, the plugin should emit signal @ref error with
+* True as the first argument and then attempt to restart the speech engine.
+* The plugin will need to implement some protection against an infinite
+* restart loop and emit the @ref error signal with False as the first argument
+* if this occurs.
+*
+* If a plugin emits the @ref error signal with False as the first argument,
+* KTTSD will no longer call the plugin.
+*
+* @section PlugInConf
+*
+* The plugin should implement a configuration dialog where the user can specify
+* options specific to the speech engine. This dialog is displayed in the KDE
+* Control Center and also in the KTTS Manager (kttsmgr). See pluginconf.h.
+*
+* If the user changes any of the settings while the plugin is created,
+* the plugin will be destroyed and re-created.
+*/
+
+class QTextCodec;
+
+enum pluginState
+{
+ psIdle = 0, /**< Plugin is not doing anything. */
+ psSaying = 1, /**< Plugin is synthesizing and audibilizing. */
+ psSynthing = 2, /**< Plugin is synthesizing. */
+ psFinished = 3 /**< Plugin has finished synthesizing. Audio file is ready. */
+};
+
+class KDE_EXPORT PlugInProc : virtual public QObject{
+ Q_OBJECT
+
+ public:
+ enum CharacterCodec {
+ Local = 0,
+ Latin1 = 1,
+ Unicode = 2,
+ UseCodec = 3
+ };
+
+ /**
+ * Constructor.
+ */
+ PlugInProc( QObject *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor.
+ * Plugin must terminate the speech engine.
+ */
+ virtual ~PlugInProc();
+
+ /**
+ * Initialize the speech engine.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ *
+ * Sample code for reading configuration:
+ *
+ @verbatim
+ config->setGroup(configGroup);
+ m_fliteExePath = config->readEntry("FliteExePath", "flite");
+ kdDebug() << "FliteProc::init: path to flite: " << m_fliteExePath << endl;
+ config->setGroup(configGroup);
+ @endverbatim
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Say a text. Synthesize and audibilize it.
+ * @param text The text to be spoken.
+ *
+ * If the plugin supports asynchronous operation, it should return immediately
+ * and emit sayFinished signal when synthesis and audibilizing is finished.
+ * It must also implement the @ref getState method, which must return
+ * psFinished, when saying is completed.
+ */
+ virtual void sayText(const QString &text);
+
+ /**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately
+ * and emit @ref synthFinished signal when synthesis is completed.
+ * It must also implement the @ref getState method, which must return
+ * psFinished, when synthesis is completed.
+ */
+ virtual void synthText(const QString &text, const QString &suggestedFilename);
+
+ /**
+ * Get the generated audio filename from call to @ref synthText.
+ * @return Name of the audio file the plugin generated.
+ * Null if no such file.
+ *
+ * The plugin must not re-use or delete the filename. The file may not
+ * be locked when this method is called. The file will be deleted when
+ * KTTSD is finished using it.
+ */
+ virtual QString getFilename();
+
+ /**
+ * Stop current operation (saying or synthesizing text).
+ * Important: This function may be called from a thread different from the
+ * one that called sayText or synthText.
+ * If the plugin cannot stop an in-progress @ref sayText or
+ * @ref synthText operation, it must not block waiting for it to complete.
+ * Instead, return immediately.
+ *
+ * If a plugin returns before the operation has actually been stopped,
+ * the plugin must emit the @ref stopped signal when the operation has
+ * actually stopped.
+ *
+ * The plugin should change to the psIdle state after stopping the
+ * operation.
+ */
+ virtual void stopText();
+
+ /**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @see pluginState
+ */
+ virtual pluginState getState();
+
+ /**
+ * Acknowledges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref sayFinished or @ref synthFinished signals when
+ * saying or synthesis is completed.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Returns True if the plugin supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ *
+ * If the plugin returns True, it must also implement the following methods:
+ * - @ref synthText
+ * - @ref getFilename
+ * - @ref ackFinished
+ *
+ * If the plugin returns True, it need not implement @ref sayText .
+ */
+ virtual bool supportsSynth();
+
+ /**
+ * Returns the name of an XSLT stylesheet that will convert a valid SSML file
+ * into a format that can be processed by the synth. For example,
+ * The Festival plugin returns a stylesheet that will convert SSML into
+ * SABLE. Any tags the synth cannot handle should be stripped (leaving
+ * their text contents though). The default stylesheet strips all
+ * tags and converts the file to plain text.
+ * @return Name of the XSLT file.
+ */
+ virtual QString getSsmlXsltFilename();
+
+ /**
+ * Given the name of a codec, returns the QTextCodec for the name.
+ * Handles the following "special" codec names:
+ * Local The user's current Locale codec.
+ * Latin1 Latin1 (ISO 8859-1)
+ * Unicode UTF-16
+ * @param codecName Name of desired codec.
+ * @return The codec object. Calling program must not delete this object
+ * as it is a reference to an existing QTextCodec object.
+ *
+ * Caution: Do not pass translated codec names to this routine.
+ */
+ static QTextCodec* codecNameToCodec(const QString &codecName);
+
+ /**
+ * Builds a list of codec names, suitable for display in a QComboBox.
+ * The list includes the 3 special codec names (translated) at the top:
+ * Local The user's current Locale codec.
+ * Latin1 Latin1 (ISO 8859-1)
+ * Unicode UTF-16
+ */
+ static QStringList buildCodecList();
+
+ /**
+ * Given the name of a codec, returns index into the codec list.
+ * Handles the following "special" codec names:
+ * Local The user's current Locale codec.
+ * Latin1 Latin1 (ISO 8859-1)
+ * Unicode UTF-16
+ * @param codecName Name of the codec.
+ * @param codecList List of codec names. The first 3 entries may be translated names.
+ * @return QTextCodec object. Caller must not delete this object.
+ *
+ * Caution: Do not pass translated codec names to this routine in codecName parameter.
+ */
+ static int codecNameToListIndex(const QString &codecName, const QStringList &codecList);
+
+ /**
+ * Given index into codec list, returns the codec object.
+ * @param codecNum Index of the codec.
+ * @param codecList List of codec names. The first 3 entries may be translated names.
+ * @return QTextCodec object. Caller must not delete this object.
+ */
+ static QTextCodec* codecIndexToCodec(int codecNum, const QStringList &codecList);
+
+ /**
+ * Given index into codec list, returns the codec Name.
+ * Handles the following "special" codec names:
+ * Local The user's current Locale codec.
+ * Latin1 Latin1 (ISO 8859-1)
+ * Unicode UTF-16
+ * @param codecNum Index of the codec.
+ * @param codecList List of codec names. The first 3 entries may be translated names.
+ * @return Untranslated name of the codec.
+ */
+ static QString codecIndexToCodecName(int codecNum, const QStringList &codecList);
+
+ signals:
+ /**
+ * Emitted when synthText() finishes and plugin supports asynchronous mode.
+ */
+ void synthFinished();
+ /**
+ * Emitted when sayText() finishes and plugin supports asynchronous mode.
+ */
+ void sayFinished();
+ /**
+ * Emitted when stopText() has been called and plugin stops asynchronously.
+ */
+ void stopped();
+ /**
+ * Emitted if an error occurs.
+ * @param keepGoing True if the plugin can continue processing.
+ * False if the plugin cannot continue, for example,
+ * the speech engine could not be started.
+ * @param msg Error message.
+ *
+ * When an error occurs, plugins should attempt to recover as best they can
+ * and continue accepting @ref sayText or @ref synthText calls. For example,
+ * if the speech engine emits an error while synthesizing text, the plugin
+ * should return True along with error message.
+ *
+ * @see Error-handling
+ *
+ */
+ void error(bool keepGoing, const QString &msg);
+};
+
+#endif // _PLUGINPROC_H_
diff --git a/kttsd/libkttsd/selecttalkerdlg.cpp b/kttsd/libkttsd/selecttalkerdlg.cpp
new file mode 100644
index 0000000..d74339e
--- /dev/null
+++ b/kttsd/libkttsd/selecttalkerdlg.cpp
@@ -0,0 +1,365 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Description:
+ A dialog for user to select a Talker, either by specifying
+ selected Talker attributes, or by specifying all attributes
+ of an existing configured Talker.
+
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qhbox.h>
+#include <qgroupbox.h>
+
+// KDE includes.
+#include <kcombobox.h>
+#include <ktrader.h>
+#include <kpushbutton.h>
+#include <klistview.h>
+#include <klineedit.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "utils.h"
+#include "selecttalkerdlg.h"
+#include "selecttalkerdlg.moc"
+
+SelectTalkerDlg::SelectTalkerDlg(
+ QWidget* parent,
+ const char* name,
+ const QString& caption,
+ const QString& talkerCode,
+ bool runningTalkers) :
+
+ KDialogBase(
+ parent,
+ name,
+ true,
+ caption,
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok)
+{
+ m_widget = new SelectTalkerWidget( this );
+ // TODO: How do I do this in a general way and still get KDialogBase to properly resize?
+ m_widget->setMinimumSize( QSize(700,500) );
+ // setInitialSize( QSize(700,600) );
+ setMainWidget( m_widget );
+ m_runningTalkers = runningTalkers;
+ m_talkerCode = TalkerCode( talkerCode, false );
+
+ // Fill combo boxes.
+ KComboBox* cb = m_widget->genderComboBox;
+ cb->insertItem( QString::null );
+ cb->insertItem( TalkerCode::translatedGender("male") );
+ cb->insertItem( TalkerCode::translatedGender("female") );
+ cb->insertItem( TalkerCode::translatedGender("neutral") );
+
+ cb = m_widget->volumeComboBox;
+ cb->insertItem( QString::null );
+ cb->insertItem( TalkerCode::translatedVolume("medium") );
+ cb->insertItem( TalkerCode::translatedVolume("loud") );
+ cb->insertItem( TalkerCode::translatedVolume("soft") );
+
+ cb = m_widget->rateComboBox;
+ cb->insertItem( QString::null );
+ cb->insertItem( TalkerCode::translatedRate("medium") );
+ cb->insertItem( TalkerCode::translatedRate("fast") );
+ cb->insertItem( TalkerCode::translatedRate("slow") );
+
+ cb = m_widget->synthComboBox;
+ cb->insertItem( QString::null );
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/SynthPlugin");
+ for(unsigned int i=0; i < offers.count() ; ++i)
+ cb->insertItem(offers[i]->name());
+
+ // Fill List View with list of Talkers.
+ m_widget->talkersListView->setSorting( -1 );
+ loadTalkers( m_runningTalkers );
+
+ // Set initial radio button state.
+ if ( talkerCode.isEmpty() )
+ m_widget->useDefaultRadioButton->setChecked(true);
+ else
+ {
+ QString dummy;
+ if (talkerCode == TalkerCode::normalizeTalkerCode(talkerCode, dummy))
+ m_widget->useSpecificTalkerRadioButton->setChecked(true);
+ else
+ m_widget->useClosestMatchRadioButton->setChecked(true);
+ }
+
+ applyTalkerCodeToControls();
+ enableDisableControls();
+
+ connect(m_widget->useDefaultRadioButton, SIGNAL(clicked()),
+ this, SLOT(configChanged()));
+ connect(m_widget->useClosestMatchRadioButton, SIGNAL(clicked()),
+ this, SLOT(configChanged()));
+ connect(m_widget->useSpecificTalkerRadioButton, SIGNAL(clicked()),
+ this, SLOT(configChanged()));
+
+ connect(m_widget->languageBrowseButton, SIGNAL(clicked()),
+ this, SLOT(slotLanguageBrowseButton_clicked()));
+
+ connect(m_widget->synthComboBox, SIGNAL(activated(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->genderComboBox, SIGNAL(activated(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->volumeComboBox, SIGNAL(activated(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->rateComboBox, SIGNAL(activated(const QString&)),
+ this, SLOT(configChanged()));
+
+ connect(m_widget->synthCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(configChanged()));
+ connect(m_widget->genderCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(configChanged()));
+ connect(m_widget->volumeCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(configChanged()));
+ connect(m_widget->rateCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(configChanged()));
+
+ connect(m_widget->talkersListView, SIGNAL(selectionChanged()),
+ this, SLOT(slotTalkersListView_selectionChanged()));
+
+ m_widget->talkersListView->setMinimumHeight( 120 );
+}
+
+SelectTalkerDlg::~SelectTalkerDlg() { }
+
+QString SelectTalkerDlg::getSelectedTalkerCode()
+{
+ return m_talkerCode.getTalkerCode();
+}
+
+QString SelectTalkerDlg::getSelectedTranslatedDescription()
+{
+ return m_talkerCode.getTranslatedDescription();
+}
+
+void SelectTalkerDlg::slotLanguageBrowseButton_clicked()
+{
+ // Create a QHBox to host KListView.
+ QHBox* hBox = new QHBox(m_widget, "SelectLanguage_hbox");
+ // Create a KListView and fill with all known languages.
+ KListView* langLView = new KListView(hBox, "SelectLanguage_lview");
+ langLView->addColumn(i18n("Language"));
+ langLView->addColumn(i18n("Code"));
+ langLView->setSelectionMode(QListView::Single);
+ QStringList allLocales = KGlobal::locale()->allLanguagesTwoAlpha();
+ QString locale;
+ QString language;
+ // Blank line so user can select no language.
+ // Note: Don't use QString::null, which gets displayed at bottom of list, rather than top.
+ QListViewItem* item = new KListViewItem(langLView, "", "");
+ if (m_talkerCode.languageCode().isEmpty()) item->setSelected(true);
+ int allLocalesCount = allLocales.count();
+ for (int ndx=0; ndx < allLocalesCount; ++ndx)
+ {
+ locale = allLocales[ndx];
+ language = TalkerCode::languageCodeToLanguage(locale);
+ item = new KListViewItem(langLView, language, locale);
+ if (m_talkerCode.fullLanguageCode() == locale) item->setSelected(true);
+ }
+ // Sort by language.
+ langLView->setSorting(0);
+ langLView->sort();
+ // Display the box in a dialog.
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Select Languages"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_widget,
+ "SelectLanguage_dlg",
+ true,
+ true);
+ dlg->setMainWidget(hBox);
+ dlg->setHelp("", "kttsd");
+ dlg->setInitialSize(QSize(300, 500), false);
+ // TODO: This isn't working. Furthermore, item appears selected but is not.
+ langLView->ensureItemVisible(langLView->selectedItem());
+ int dlgResult = dlg->exec();
+ language = QString::null;
+ if (dlgResult == QDialog::Accepted)
+ {
+ if (langLView->selectedItem())
+ {
+ language = langLView->selectedItem()->text(0);
+ m_talkerCode.setFullLanguageCode( langLView->selectedItem()->text(1) );
+ }
+ }
+ delete dlg;
+ m_widget->languageLineEdit->setText(language);
+ m_widget->languageCheckBox->setChecked( !language.isEmpty() );
+ configChanged();
+}
+
+void SelectTalkerDlg::slotTalkersListView_selectionChanged()
+{
+ QListViewItem* item = m_widget->talkersListView->selectedItem();
+ if ( !item ) return;
+ if (!m_widget->useSpecificTalkerRadioButton->isChecked()) return;
+ configChanged();
+}
+
+void SelectTalkerDlg::configChanged()
+{
+ applyControlsToTalkerCode();
+ applyTalkerCodeToControls();
+ enableDisableControls();
+}
+
+void SelectTalkerDlg::applyTalkerCodeToControls()
+{
+ bool preferred = false;
+ QString code = m_talkerCode.getTalkerCode();
+
+ // TODO: Need to display translated Synth names.
+ KttsUtils::setCbItemFromText(m_widget->synthComboBox,
+ TalkerCode::stripPrefer( m_talkerCode.plugInName(), preferred) );
+ m_widget->synthCheckBox->setEnabled( !m_talkerCode.plugInName().isEmpty() );
+ m_widget->synthCheckBox->setChecked( preferred );
+
+ KttsUtils::setCbItemFromText(m_widget->genderComboBox,
+ TalkerCode::translatedGender( TalkerCode::stripPrefer( m_talkerCode.gender(), preferred ) ) );
+ m_widget->genderCheckBox->setEnabled( !m_talkerCode.gender().isEmpty() );
+ m_widget->genderCheckBox->setChecked( preferred );
+
+ KttsUtils::setCbItemFromText(m_widget->volumeComboBox,
+ TalkerCode::translatedVolume( TalkerCode::stripPrefer( m_talkerCode.volume(), preferred ) ) );
+ m_widget->volumeCheckBox->setEnabled( !m_talkerCode.volume().isEmpty() );
+ m_widget->volumeCheckBox->setChecked( preferred );
+
+ KttsUtils::setCbItemFromText(m_widget->rateComboBox,
+ TalkerCode::translatedRate( TalkerCode::stripPrefer( m_talkerCode.rate(), preferred ) ) );
+ m_widget->rateCheckBox->setEnabled( !m_talkerCode.rate().isEmpty() );
+ m_widget->rateCheckBox->setChecked( preferred );
+
+ // Select closest matching specific Talker.
+ int talkerIndex = TalkerCode::findClosestMatchingTalker(m_talkers, m_talkerCode.getTalkerCode(), false);
+ KListView* lv = m_widget->talkersListView;
+ QListViewItem* item = lv->firstChild();
+ if ( item )
+ {
+ while ( talkerIndex > 0 )
+ {
+ item = item->nextSibling();
+ --talkerIndex;
+ }
+ lv->setSelected( item, true );
+ }
+}
+
+void SelectTalkerDlg::applyControlsToTalkerCode()
+{
+ if ( m_widget->useDefaultRadioButton->isChecked() )
+ m_talkerCode = TalkerCode(QString::null, false);
+ else if ( m_widget->useClosestMatchRadioButton->isChecked() )
+ {
+ // Language already stored in talker code.
+
+ QString t = m_widget->synthComboBox->currentText();
+ if ( !t.isEmpty() && m_widget->synthCheckBox->isChecked() ) t.prepend("*");
+ m_talkerCode.setPlugInName( t );
+
+ t = TalkerCode::untranslatedGender( m_widget->genderComboBox->currentText() );
+ if ( !t.isEmpty() && m_widget->genderCheckBox->isChecked() ) t.prepend("*");
+ m_talkerCode.setGender( t );
+
+ t = TalkerCode::untranslatedVolume( m_widget->volumeComboBox->currentText() );
+ if ( !t.isEmpty() && m_widget->volumeCheckBox->isChecked() ) t.prepend("*");
+ m_talkerCode.setVolume( t );
+
+ t = TalkerCode::untranslatedRate( m_widget->rateComboBox->currentText() );
+ if ( !t.isEmpty() && m_widget->rateCheckBox->isChecked() ) t.prepend("*");
+ m_talkerCode.setRate( t );
+ }
+ else if (m_widget->useSpecificTalkerRadioButton->isChecked() )
+ {
+ QListViewItem* item = m_widget->talkersListView->selectedItem();
+ if ( item )
+ {
+ int itemIndex = -1;
+ while ( item )
+ {
+ item = item->itemAbove();
+ itemIndex++;
+ }
+ m_talkerCode = TalkerCode( &(m_talkers[itemIndex]), false );
+ }
+ }
+}
+
+void SelectTalkerDlg::loadTalkers(bool /*runningTalkers*/)
+{
+ m_talkers.clear();
+ KListView* lv = m_widget->talkersListView;
+ lv->clear();
+ QListViewItem* item;
+ KConfig* config = new KConfig("kttsdrc");
+ config->setGroup("General");
+ QStringList talkerIDsList = config->readListEntry("TalkerIDs", ',');
+ if (!talkerIDsList.isEmpty())
+ {
+ QStringList::ConstIterator itEnd(talkerIDsList.constEnd());
+ for( QStringList::ConstIterator it = talkerIDsList.constBegin(); it != itEnd; ++it )
+ {
+ QString talkerID = *it;
+ config->setGroup("Talker_" + talkerID);
+ QString talkerCode = config->readEntry("TalkerCode", QString::null);
+ // Parse and normalize the talker code.
+ TalkerCode talker = TalkerCode(talkerCode, true);
+ m_talkers.append(talker);
+ QString desktopEntryName = config->readEntry("DesktopEntryName", QString::null);
+ QString synthName = TalkerCode::TalkerDesktopEntryNameToName(desktopEntryName);
+ // Display in List View using translated strings.
+ item = new KListViewItem(lv, item);
+ QString fullLanguageCode = talker.fullLanguageCode();
+ QString language = TalkerCode::languageCodeToLanguage(fullLanguageCode);
+ item->setText(tlvcLanguage, language);
+ // Don't update the Synthesizer name with plugInName. The former is a translated
+ // name; the latter an English name.
+ // if (!plugInName.isEmpty()) talkerItem->setText(tlvcSynthName, plugInName);
+ if (!synthName.isEmpty())
+ item->setText(tlvcSynthName, synthName);
+ if (!talker.voice().isEmpty())
+ item->setText(tlvcVoice, talker.voice());
+ if (!talker.gender().isEmpty())
+ item->setText(tlvcGender, TalkerCode::translatedGender(talker.gender()));
+ if (!talker.volume().isEmpty())
+ item->setText(tlvcVolume, TalkerCode::translatedVolume(talker.volume()));
+ if (!talker.rate().isEmpty())
+ item->setText(tlvcRate, TalkerCode::translatedRate(talker.rate()));
+ }
+ }
+ delete config;
+}
+
+void SelectTalkerDlg::enableDisableControls()
+{
+ bool enableClosest = ( m_widget->useClosestMatchRadioButton->isChecked() );
+ bool enableSpecific = ( m_widget->useSpecificTalkerRadioButton->isChecked() );
+ m_widget->closestMatchGroupBox->setEnabled( enableClosest );
+ m_widget->talkersListView->setEnabled( enableSpecific );
+}
diff --git a/kttsd/libkttsd/selecttalkerdlg.h b/kttsd/libkttsd/selecttalkerdlg.h
new file mode 100644
index 0000000..bc236e2
--- /dev/null
+++ b/kttsd/libkttsd/selecttalkerdlg.h
@@ -0,0 +1,110 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Description:
+ A dialog for user to select a Talker, either by specifying
+ selected Talker attributes, or by specifying all attributes
+ of an existing configured Talker.
+
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _SELECTTALKERDLG_H_
+#define _SELECTTALKERDLG_H_
+
+// Qt includes.
+#include <qvaluelist.h>
+
+// KDE includes.
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <kdemacros.h>
+
+// KTTS includes.
+#include "talkercode.h"
+#include "selecttalkerwidget.h"
+
+class KDE_EXPORT SelectTalkerDlg : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor.
+ * @param parent The parent for this dialog.
+ * @param name Name for this dialog.
+ * @param caption Displayed title for this dialog.
+ * @param talkerCode A suggested starting Talker Code.
+ * @param runningTalkers If true, lists configured and Applied Talkers in the running
+ * KTTSD. If false, lists Talkers in the KTTSMgr Talker tab
+ * (which may not yet have been Applied).
+ */
+ SelectTalkerDlg(
+ QWidget* parent = 0,
+ const char* name = "selecttalkerdialog",
+ const QString& caption = i18n("Select Talker"),
+ const QString& talkerCode = QString::null,
+ bool runningTalkers = false);
+
+ /**
+ * Destructor.
+ */
+ ~SelectTalkerDlg();
+
+ /**
+ * Returns the Talker Code user chose. QString::null if default Talker chosen.
+ * Note that if user did not choose a specific Talker, this will be a partial Talker Code.
+ */
+ QString getSelectedTalkerCode();
+ /**
+ * Returns the Talker user chose in a translated displayable format.
+ */
+ QString getSelectedTranslatedDescription();
+
+ private slots:
+ void slotLanguageBrowseButton_clicked();
+ void slotTalkersListView_selectionChanged();
+ void configChanged();
+
+ private:
+ enum TalkerListViewColumn
+ {
+ tlvcLanguage,
+ tlvcSynthName,
+ tlvcVoice,
+ tlvcGender,
+ tlvcVolume,
+ tlvcRate
+ };
+
+ void applyTalkerCodeToControls();
+ void applyControlsToTalkerCode();
+ void loadTalkers(bool runningTalkers);
+ void enableDisableControls();
+
+ // Main dialog widget.
+ SelectTalkerWidget* m_widget;
+ // True if list of Talkers should be taken from config file.
+ bool m_runningTalkers;
+ // Current Talker Code.
+ TalkerCode m_talkerCode;
+ // List of parsed talker codes for the configured Talkers.
+ TalkerCode::TalkerCodeList m_talkers;
+};
+
+#endif // _SELECTTALKERDLG_H_
diff --git a/kttsd/libkttsd/selecttalkerwidget.ui b/kttsd/libkttsd/selecttalkerwidget.ui
new file mode 100644
index 0000000..adcc8a9
--- /dev/null
+++ b/kttsd/libkttsd/selecttalkerwidget.ui
@@ -0,0 +1,572 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>SelectTalkerWidget</class>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SelectTalkerWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>558</width>
+ <height>447</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Select Talker</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>useDefaultRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Use default Talker</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, will use the default Talker, which is the topmost Talker listed in the Talkers tab.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>useClosestMatchRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string>Use closest &amp;matching Talker having</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, will use a configured Talker most closely matching the attributes you choose. Attributes with checks next to them will be preferred over unchecked attributes. Language is always preferred.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer15</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>closestMatchGroupBox</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="3" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>preferredLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Checked items are preferred over unchecked items.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout11_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>synthLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Synthesizer:</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>synthComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>synthComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>synthCheckBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="2">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>genderLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Gender:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>genderCheckBox</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>genderComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>genderCheckBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="Line" row="0" column="1" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>volumeLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Volume:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>volumeCheckBox</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>volumeComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>volumeCheckBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="2">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>rateLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Rate:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>rateCheckBox</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>rateComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>rateCheckBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Language:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>languageLineEdit</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>languageLineEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="paletteForegroundColor">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank, the filter applies to all text jobs of any language.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>languageBrowseButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to select one or more languages. This filter will be applied to text jobs of those languages.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>languageCheckBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>useSpecificTalkerRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string>Use specific &amp;Talker</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, will use the specific Talker (if it is still configured), otherwise the Talker most closely matching.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer15_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Language</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Speech Synthesizer</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Voice</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Gender</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Volume</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Rate</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>talkersListView</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="resizeMode">
+ <enum>LastColumn</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of all the configured Talkers. A Talker is a speech synthesizer that has been configured with a language, voice, gender, speaking rate, and volume. Talkers higher in the list have higher priority. The topmost Talker will be used when no talker attributes have been specified by an application.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>useDefaultRadioButton</tabstop>
+ <tabstop>useClosestMatchRadioButton</tabstop>
+ <tabstop>synthComboBox</tabstop>
+ <tabstop>synthCheckBox</tabstop>
+ <tabstop>genderComboBox</tabstop>
+ <tabstop>genderCheckBox</tabstop>
+ <tabstop>volumeComboBox</tabstop>
+ <tabstop>volumeCheckBox</tabstop>
+ <tabstop>rateComboBox</tabstop>
+ <tabstop>rateCheckBox</tabstop>
+ <tabstop>languageLineEdit</tabstop>
+ <tabstop>languageBrowseButton</tabstop>
+ <tabstop>languageCheckBox</tabstop>
+ <tabstop>useSpecificTalkerRadioButton</tabstop>
+ <tabstop>talkersListView</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="0"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/libkttsd/stretcher.cpp b/kttsd/libkttsd/stretcher.cpp
new file mode 100644
index 0000000..d3a3984
--- /dev/null
+++ b/kttsd/libkttsd/stretcher.cpp
@@ -0,0 +1,99 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Description:
+ Speeds up or slows down an audio file by stretching the audio stream.
+ Uses the sox program to do the stretching.
+
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// KDE includes.
+#include <kprocess.h>
+#include <kdebug.h>
+
+// Stretcher includes.
+#include "stretcher.h"
+#include "stretcher.moc"
+
+/**
+ * Constructor.
+ */
+Stretcher::Stretcher(QObject *parent, const char *name) :
+ QObject(parent, name)
+{
+ m_state = 0;
+ m_stretchProc = 0;
+}
+
+/**
+ * Destructor.
+ */
+Stretcher::~Stretcher()
+{
+ delete m_stretchProc;
+}
+
+/**
+ * Stretch the given input file to an output file.
+ * @param inFilename Name of input audio file.
+ * @param outFilename Name of output audio file.
+ * @param stretchFactor Amount to stretch. 2.0 is twice as slow. 0.5 is twice as fast.
+ * @return False if an error occurs.
+ */
+bool Stretcher::stretch(const QString &inFilename, const QString &outFilename, float stretchFactor)
+{
+ if (m_stretchProc) return false;
+ m_outFilename = outFilename;
+ m_stretchProc = new KProcess;
+ QString stretchStr = QString("%1").arg(stretchFactor, 0, 'f', 3);
+ *m_stretchProc << "sox" << inFilename << outFilename << "stretch" << stretchStr;
+ connect(m_stretchProc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*)));
+ if (!m_stretchProc->start(KProcess::NotifyOnExit, KProcess::NoCommunication))
+ {
+ kdDebug() << "Stretcher::stretch: Error starting audio stretcher process. Is sox installed?" << endl;
+ return false;
+ }
+ m_state = ssStretching;
+ return true;
+}
+
+void Stretcher::slotProcessExited(KProcess*)
+{
+ m_stretchProc->deleteLater();
+ m_stretchProc = 0;
+ m_state = ssFinished;
+ emit stretchFinished();
+}
+
+/**
+ * Returns the state of the Stretcher.
+ */
+int Stretcher::getState() { return m_state; }
+
+/**
+ * Returns the output filename (as given in call to stretch).
+ */
+QString Stretcher::getOutFilename() { return m_outFilename; }
+
+/**
+ * Acknowledges the finished stretching.
+ */
+void Stretcher::ackFinished() { m_state = ssIdle; }
+
diff --git a/kttsd/libkttsd/stretcher.h b/kttsd/libkttsd/stretcher.h
new file mode 100644
index 0000000..e4d8686
--- /dev/null
+++ b/kttsd/libkttsd/stretcher.h
@@ -0,0 +1,97 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Description:
+ Speeds up or slows down an audio file by stretching the audio stream.
+ Uses the sox program to do the stretching.
+
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _STRETCHER_H_
+#define _STRETCHER_H_
+
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+
+class KProcess;
+
+class KDE_EXPORT Stretcher : public QObject{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor.
+ */
+ Stretcher(QObject *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor.
+ */
+ ~Stretcher();
+
+ enum StretcherState {
+ ssIdle = 0, // Not doing anything. Ready to stretch.
+ ssStretching = 1, // Stretching.
+ ssFinished = 2 // Stretching finished.
+ };
+
+ /**
+ * Stretch the given input file to an output file.
+ * @param inFilename Name of input audio file.
+ * @param outFilename Name of output audio file.
+ * @param stretchFactor Amount to stretch. 2.0 is twice as slow. 0.5 is twice as fast.
+ */
+ bool stretch(const QString &inFilename, const QString &outFilename, float stretchFactor);
+
+ /**
+ * Returns the state of the Stretcher.
+ */
+ int getState();
+
+ /**
+ * Returns the output filename (as given in call to stretch).
+ */
+ QString getOutFilename();
+
+ /**
+ * Acknowledges the finished stretching.
+ */
+ void ackFinished();
+
+ signals:
+ /**
+ * Emitted whenever stretching is completed.
+ */
+ void stretchFinished();
+
+ private slots:
+ void slotProcessExited(KProcess* proc);
+
+ private:
+ // Stretcher state.
+ int m_state;
+
+ // Sox process.
+ KProcess* m_stretchProc;
+
+ // Output file name.
+ QString m_outFilename;
+};
+
+#endif // _STRETCHER_H_
diff --git a/kttsd/libkttsd/talkercode.cpp b/kttsd/libkttsd/talkercode.cpp
new file mode 100644
index 0000000..d25cf7f
--- /dev/null
+++ b/kttsd/libkttsd/talkercode.cpp
@@ -0,0 +1,517 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Convenience object for manipulating Talker Codes.
+ For an explanation of what a Talker Code is, see kspeech.h.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// KDE includes.
+#include <kglobal.h>
+#include <klocale.h>
+#include <ktrader.h>
+#include <kdebug.h>
+
+// TalkerCode includes.
+#include "talkercode.h"
+
+/**
+ * Constructor.
+ */
+TalkerCode::TalkerCode(const QString &code/*=QString::null*/, bool normal /*=false*/)
+{
+ if (!code.isEmpty())
+ parseTalkerCode(code);
+ if (normal) normalize();
+}
+
+/**
+ * Copy Constructor.
+ */
+TalkerCode::TalkerCode(TalkerCode* talker, bool normal /*=false*/)
+{
+ m_languageCode = talker->languageCode();
+ m_countryCode = talker->countryCode();
+ m_voice = talker->voice();
+ m_gender = talker->gender();
+ m_volume = talker->volume();
+ m_rate = talker->rate();
+ m_plugInName = talker->plugInName();
+ if (normal) normalize();
+}
+
+/**
+ * Destructor.
+ */
+TalkerCode::~TalkerCode() { }
+
+/**
+ * Properties.
+ */
+QString TalkerCode::languageCode() const { return m_languageCode; }
+QString TalkerCode::countryCode() const { return m_countryCode; }
+QString TalkerCode::voice() const { return m_voice; }
+QString TalkerCode::gender() const { return m_gender; }
+QString TalkerCode::volume() const { return m_volume; }
+QString TalkerCode::rate() const { return m_rate; }
+QString TalkerCode::plugInName() const { return m_plugInName; }
+
+void TalkerCode::setLanguageCode(const QString &languageCode) { m_languageCode = languageCode; }
+void TalkerCode::setCountryCode(const QString &countryCode) { m_countryCode = countryCode; }
+void TalkerCode::setVoice(const QString &voice) { m_voice = voice; }
+void TalkerCode::setGender(const QString &gender) { m_gender = gender; }
+void TalkerCode::setVolume(const QString &volume) { m_volume = volume; }
+void TalkerCode::setRate(const QString &rate) { m_rate = rate; }
+void TalkerCode::setPlugInName(const QString plugInName) { m_plugInName = plugInName; }
+
+/**
+ * Sets the language code and country code (if given).
+ */
+void TalkerCode::setFullLanguageCode(const QString &fullLanguageCode)
+{
+ splitFullLanguageCode(fullLanguageCode, m_languageCode, m_countryCode);
+}
+
+/**
+ * Returns the language code plus country code (if any).
+ */
+QString TalkerCode::fullLanguageCode() const
+{
+ if (!m_countryCode.isEmpty())
+ return m_languageCode + "_" + m_countryCode;
+ else
+ return m_languageCode;
+}
+
+/**
+ * The Talker Code returned in XML format.
+ */
+QString TalkerCode::getTalkerCode() const
+{
+ QString code;
+ QString languageCode = m_languageCode;
+ if (!m_countryCode.isEmpty()) languageCode += "_" + m_countryCode;
+ if (!languageCode.isEmpty()) code = "lang=\"" + languageCode + "\" ";
+ if (!m_voice.isEmpty()) code += "name=\"" + m_voice + "\" ";
+ if (!m_gender.isEmpty()) code += "gender=\"" + m_gender + "\" ";
+ if (!code.isEmpty()) code = "<voice " + code + "/>";
+ QString prosody;
+ if (!m_volume.isEmpty()) prosody = "volume=\"" + m_volume + "\" ";
+ if (!m_rate.isEmpty()) prosody += "rate=\"" + m_rate + "\" ";
+ if (!prosody.isEmpty()) code += "<prosody " + prosody + "/>";
+ if (!m_plugInName.isEmpty()) code += "<kttsd synthesizer=\"" + m_plugInName + "\" />";
+ return code;
+}
+
+/**
+ * The Talker Code translated for display.
+ */
+QString TalkerCode::getTranslatedDescription() const
+{
+ QString code;
+ bool prefer;
+ QString fullLangCode = fullLanguageCode();
+ if (!fullLangCode.isEmpty()) code = languageCodeToLanguage( fullLangCode );
+ // TODO: The PlugInName is always English. Need a way to convert this to a translated
+ // name (possibly via DesktopEntryNameToName, but to do that, we need the desktopEntryName
+ // from the config file).
+ if (!m_plugInName.isEmpty()) code += " " + stripPrefer(m_plugInName, prefer);
+ if (!m_voice.isEmpty()) code += " " + stripPrefer(m_voice, prefer);
+ if (!m_gender.isEmpty()) code += " " + translatedGender(stripPrefer(m_gender, prefer));
+ if (!m_volume.isEmpty()) code += " " + translatedVolume(stripPrefer(m_volume, prefer));
+ if (!m_rate.isEmpty()) code += " " + translatedRate(stripPrefer(m_rate, prefer));
+ code = code.stripWhiteSpace();
+ if (code.isEmpty()) code = i18n("default");
+ return code;
+}
+
+/**
+ * Normalizes the Talker Code by filling in defaults.
+ */
+void TalkerCode::normalize()
+{
+ if (m_voice.isEmpty()) m_voice = "fixed";
+ if (m_gender.isEmpty()) m_gender = "neutral";
+ if (m_volume.isEmpty()) m_volume = "medium";
+ if (m_rate.isEmpty()) m_rate = "medium";
+}
+
+/**
+ * Given a talker code, normalizes it into a standard form and also returns
+ * the language code.
+ * @param talkerCode Unnormalized talker code.
+ * @return fullLanguageCode Language code from the talker code (including country code if any).
+ * @return Normalized talker code.
+ */
+/*static*/ QString TalkerCode::normalizeTalkerCode(const QString &talkerCode, QString &fullLanguageCode)
+{
+ TalkerCode tmpTalkerCode(talkerCode);
+ tmpTalkerCode.normalize();
+ fullLanguageCode = tmpTalkerCode.fullLanguageCode();
+ return tmpTalkerCode.getTalkerCode();
+}
+
+/**
+ * Given a language code that might contain a country code, splits the code into
+ * the two letter language code and country code.
+ * @param fullLanguageCode Language code to be split.
+ * @return languageCode Just the language part of the code.
+ * @return countryCode The country code part (if any).
+ *
+ * If the input code begins with an asterisk, it is ignored and removed from the returned
+ * languageCode.
+ */
+/*static*/ void TalkerCode::splitFullLanguageCode(const QString &lang, QString &languageCode, QString &countryCode)
+{
+ QString language = lang;
+ if (language.left(1) == "*") language = language.mid(1);
+ QString charSet;
+ KGlobal::locale()->splitLocale(language, languageCode, countryCode, charSet);
+}
+
+/**
+ * Given a full language code and plugin name, returns a normalized default talker code.
+ * @param fullLanguageCode Language code.
+ * @param plugInName Name of the Synthesizer plugin.
+ * @return Full normalized talker code.
+ *
+ * Example returned from defaultTalkerCode("en", "Festival")
+ * <voice lang="en" name="fixed" gender="neutral"/>
+ * <prosody volume="medium" rate="medium"/>
+ * <kttsd synthesizer="Festival" />
+ */
+/*static*/ QString TalkerCode::defaultTalkerCode(const QString &fullLanguageCode, const QString &plugInName)
+{
+ TalkerCode tmpTalkerCode;
+ tmpTalkerCode.setFullLanguageCode(fullLanguageCode);
+ tmpTalkerCode.setPlugInName(plugInName);
+ tmpTalkerCode.normalize();
+ return tmpTalkerCode.getTalkerCode();
+}
+
+/**
+ * Converts a language code plus optional country code to language description.
+ */
+/*static*/ QString TalkerCode::languageCodeToLanguage(const QString &languageCode)
+{
+ QString twoAlpha;
+ QString countryCode;
+ QString language;
+ if (languageCode == "other")
+ language = i18n("Other");
+ else
+ {
+ splitFullLanguageCode(languageCode, twoAlpha, countryCode);
+ language = KGlobal::locale()->twoAlphaToLanguageName(twoAlpha);
+ }
+ if (!countryCode.isEmpty())
+ {
+ QString countryName = KGlobal::locale()->twoAlphaToCountryName(countryCode);
+ // Some abbreviations to save screen space.
+ if (countryName == i18n("full country name", "United States of America"))
+ countryName = i18n("abbreviated country name", "USA");
+ if (countryName == i18n("full country name", "United Kingdom"))
+ countryName = i18n("abbreviated country name", "UK");
+ language += " (" + countryName + ")";
+ }
+ return language;
+}
+
+/**
+ * These functions return translated Talker Code attributes.
+ */
+/*static*/ QString TalkerCode::translatedGender(const QString &gender)
+{
+ if (gender == "male")
+ return i18n("male");
+ else if (gender == "female")
+ return i18n("female");
+ else if (gender == "neutral")
+ return i18n("neutral gender", "neutral");
+ else return gender;
+}
+/*static*/ QString TalkerCode::untranslatedGender(const QString &gender)
+{
+ if (gender == i18n("male"))
+ return "male";
+ else if (gender == i18n("female"))
+ return "female";
+ else if (gender == i18n("neutral gender", "neutral"))
+ return "neutral";
+ else return gender;
+}
+/*static*/ QString TalkerCode::translatedVolume(const QString &volume)
+{
+ if (volume == "medium")
+ return i18n("medium sound", "medium");
+ else if (volume == "loud")
+ return i18n("loud sound", "loud");
+ else if (volume == "soft")
+ return i18n("soft sound", "soft");
+ else return volume;
+}
+/*static*/ QString TalkerCode::untranslatedVolume(const QString &volume)
+{
+ if (volume == i18n("medium sound", "medium"))
+ return "medium";
+ else if (volume == i18n("loud sound", "loud"))
+ return "loud";
+ else if (volume == i18n("soft sound", "soft"))
+ return "soft";
+ else return volume;
+}
+/*static*/ QString TalkerCode::translatedRate(const QString &rate)
+{
+ if (rate == "medium")
+ return i18n("medium speed", "medium");
+ else if (rate == "fast")
+ return i18n("fast speed", "fast");
+ else if (rate == "slow")
+ return i18n("slow speed", "slow");
+ else return rate;
+}
+/*static*/ QString TalkerCode::untranslatedRate(const QString &rate)
+{
+ if (rate == i18n("medium speed", "medium"))
+ return "medium";
+ else if (rate == i18n("fast speed", "fast"))
+ return "fast";
+ else if (rate == i18n("slow speed", "slow"))
+ return "slow";
+ else return rate;
+}
+
+/**
+ * Given a talker code, parses out the attributes.
+ * @param talkerCode The talker code.
+ */
+void TalkerCode::parseTalkerCode(const QString &talkerCode)
+{
+ QString fullLanguageCode;
+ if (talkerCode.contains("\""))
+ {
+ fullLanguageCode = talkerCode.section("lang=", 1, 1);
+ fullLanguageCode = fullLanguageCode.section('"', 1, 1);
+ }
+ else
+ fullLanguageCode = talkerCode;
+ QString languageCode;
+ QString countryCode;
+ splitFullLanguageCode(fullLanguageCode, languageCode, countryCode);
+ m_languageCode = languageCode;
+ if (fullLanguageCode.left(1) == "*") countryCode = "*" + countryCode;
+ m_countryCode = countryCode;
+ m_voice = talkerCode.section("name=", 1, 1);
+ m_voice = m_voice.section('"', 1, 1);
+ m_gender = talkerCode.section("gender=", 1, 1);
+ m_gender = m_gender.section('"', 1, 1);
+ m_volume = talkerCode.section("volume=", 1, 1);
+ m_volume = m_volume.section('"', 1, 1);
+ m_rate = talkerCode.section("rate=", 1, 1);
+ m_rate = m_rate.section('"', 1, 1);
+ m_plugInName = talkerCode.section("synthesizer=", 1, 1);
+ m_plugInName = m_plugInName.section('"', 1, 1);
+}
+
+/**
+ * Given a list of parsed talker codes and a desired talker code, finds the closest
+ * matching talker in the list.
+ * @param talkers The list of parsed talker codes.
+ * @param talker The desired talker code.
+ * @param assumeDefaultLang If true, and desired talker code lacks a language code,
+ * the default language is assumed.
+ * @return Index into talkers of the closest matching talker.
+ */
+/*static*/ int TalkerCode::findClosestMatchingTalker(
+ const TalkerCodeList& talkers,
+ const QString& talker,
+ bool assumeDefaultLang)
+{
+ // kdDebug() << "TalkerCode::findClosestMatchingTalker: matching on talker code " << talker << endl;
+ // If nothing to match on, winner is top in the list.
+ if (talker.isEmpty()) return 0;
+ // Parse the given talker.
+ TalkerCode parsedTalkerCode(talker);
+ // If no language code specified, use the language code of the default talker.
+ if (assumeDefaultLang)
+ {
+ if (parsedTalkerCode.languageCode().isEmpty()) parsedTalkerCode.setLanguageCode(
+ talkers[0].languageCode());
+ }
+ // The talker that matches on the most priority attributes wins.
+ int talkersCount = int(talkers.count());
+ QMemArray<int> priorityMatch(talkersCount);
+ for (int ndx = 0; ndx < talkersCount; ++ndx)
+ {
+ priorityMatch[ndx] = 0;
+ // kdDebug() << "Comparing language code " << parsedTalkerCode.languageCode() << " to " << m_loadedPlugIns[ndx].parsedTalkerCode.languageCode() << endl;
+ if (parsedTalkerCode.languageCode() == talkers[ndx].languageCode())
+ {
+ ++priorityMatch[ndx];
+ // kdDebug() << "TalkerCode::findClosestMatchingTalker: Match on language " << parsedTalkerCode.languageCode() << endl;
+ }
+ if (parsedTalkerCode.countryCode().left(1) == "*")
+ if (parsedTalkerCode.countryCode().mid(1) ==
+ talkers[ndx].countryCode())
+ ++priorityMatch[ndx];
+ if (parsedTalkerCode.voice().left(1) == "*")
+ if (parsedTalkerCode.voice().mid(1) == talkers[ndx].voice())
+ ++priorityMatch[ndx];
+ if (parsedTalkerCode.gender().left(1) == "*")
+ if (parsedTalkerCode.gender().mid(1) == talkers[ndx].gender())
+ ++priorityMatch[ndx];
+ if (parsedTalkerCode.volume().left(1) == "*")
+ if (parsedTalkerCode.volume().mid(1) == talkers[ndx].volume())
+ ++priorityMatch[ndx];
+ if (parsedTalkerCode.rate().left(1) == "*")
+ if (parsedTalkerCode.rate().mid(1) == talkers[ndx].rate())
+ ++priorityMatch[ndx];
+ if (parsedTalkerCode.plugInName().left(1) == "*")
+ if (parsedTalkerCode.plugInName().mid(1) ==
+ talkers[ndx].plugInName())
+ ++priorityMatch[ndx];
+ }
+ // Determine the maximum number of priority attributes that were matched.
+ int maxPriority = -1;
+ for (int ndx = 0; ndx < talkersCount; ++ndx)
+ {
+ if (priorityMatch[ndx] > maxPriority) maxPriority = priorityMatch[ndx];
+ }
+ // Find the talker(s) that matched on most priority attributes.
+ int winnerCount = 0;
+ int winner = -1;
+ for (int ndx = 0; ndx < talkersCount; ++ndx)
+ {
+ if (priorityMatch[ndx] == maxPriority)
+ {
+ ++winnerCount;
+ winner = ndx;
+ }
+ }
+ // kdDebug() << "Priority phase: winnerCount = " << winnerCount
+ // << " winner = " << winner
+ // << " maxPriority = " << maxPriority << endl;
+ // If a tie, the one that matches on the most priority and preferred attributes wins.
+ // If there is still a tie, the one nearest the top of the kttsmgr display
+ // (first configured) will be chosen.
+ if (winnerCount > 1)
+ {
+ QMemArray<int> preferredMatch(talkersCount);
+ for (int ndx = 0; ndx < talkersCount; ++ndx)
+ {
+ preferredMatch[ndx] = 0;
+ if (priorityMatch[ndx] == maxPriority)
+ {
+ if (parsedTalkerCode.countryCode().left(1) != "*")
+ if (!talkers[ndx].countryCode().isEmpty())
+ if (parsedTalkerCode.countryCode() == talkers[ndx].countryCode())
+ ++preferredMatch[ndx];
+ if (parsedTalkerCode.voice().left(1) != "*")
+ if (parsedTalkerCode.voice() == talkers[ndx].voice())
+ ++preferredMatch[ndx];
+ if (parsedTalkerCode.gender().left(1) != "*")
+ if (parsedTalkerCode.gender() == talkers[ndx].gender())
+ ++preferredMatch[ndx];
+ if (parsedTalkerCode.volume().left(1) != "*")
+ if (parsedTalkerCode.volume() == talkers[ndx].volume())
+ ++preferredMatch[ndx];
+ if (parsedTalkerCode.rate().left(1) != "*")
+ if (parsedTalkerCode.rate() == talkers[ndx].rate())
+ ++preferredMatch[ndx];
+ if (parsedTalkerCode.plugInName().left(1) != "*")
+ if (parsedTalkerCode.plugInName() ==
+ talkers[ndx].plugInName())
+ ++preferredMatch[ndx];
+ }
+ }
+ // Determine the maximum number of preferred attributes that were matched.
+ int maxPreferred = -1;
+ for (int ndx = 0; ndx < talkersCount; ++ndx)
+ {
+ if (preferredMatch[ndx] > maxPreferred) maxPreferred = preferredMatch[ndx];
+ }
+ winner = -1;
+ winnerCount = 0;
+ // Find the talker that matched on most priority and preferred attributes.
+ // Work bottom to top so topmost wins in a tie.
+ for (int ndx = talkersCount-1; ndx >= 0; --ndx)
+ {
+ if (priorityMatch[ndx] == maxPriority)
+ {
+ if (preferredMatch[ndx] == maxPreferred)
+ {
+ ++winnerCount;
+ winner = ndx;
+ }
+ }
+ }
+ // kdDebug() << "Preferred phase: winnerCount = " << winnerCount
+ // << " winner = " << winner
+ // << " maxPreferred = " << maxPreferred << endl;
+ }
+ // If no winner found, use the first talker.
+ if (winner < 0) winner = 0;
+ // kdDebug() << "TalkerCode::findClosestMatchingTalker: returning winner = " << winner << endl;
+ return winner;
+}
+
+/*static*/ QString TalkerCode::stripPrefer( const QString& code, bool& preferred)
+{
+ if ( code.left(1) == "*" )
+ {
+ preferred = true;
+ return code.mid(1);
+ } else {
+ preferred = false;
+ return code;
+ }
+}
+
+/**
+* Uses KTrader to convert a translated Synth Plugin Name to DesktopEntryName.
+* @param name The translated plugin name. From Name= line in .desktop file.
+* @return DesktopEntryName. The name of the .desktop file (less .desktop).
+* QString::null if not found.
+*/
+/*static*/ QString TalkerCode::TalkerNameToDesktopEntryName(const QString& name)
+{
+ if (name.isEmpty()) return QString::null;
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/SynthPlugin");
+ for (uint ndx = 0; ndx < offers.count(); ++ndx)
+ if (offers[ndx]->name() == name) return offers[ndx]->desktopEntryName();
+ return QString::null;
+}
+
+/**
+* Uses KTrader to convert a DesktopEntryName into a translated Synth Plugin Name.
+* @param desktopEntryName The DesktopEntryName.
+* @return The translated Name of the plugin, from Name= line in .desktop file.
+*/
+/*static*/ QString TalkerCode::TalkerDesktopEntryNameToName(const QString& desktopEntryName)
+{
+ if (desktopEntryName.isEmpty()) return QString::null;
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/SynthPlugin",
+ QString("DesktopEntryName == '%1'").arg(desktopEntryName));
+
+ if (offers.count() == 1)
+ return offers[0]->name();
+ else
+ return QString::null;
+}
+
diff --git a/kttsd/libkttsd/talkercode.h b/kttsd/libkttsd/talkercode.h
new file mode 100644
index 0000000..45469af
--- /dev/null
+++ b/kttsd/libkttsd/talkercode.h
@@ -0,0 +1,197 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Object containing a Talker Code and providing convenience
+ functions for manipulating Talker Codes.
+ For an explanation of what a Talker Code is, see speech.h.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _TALKERCODE_H_
+#define _TALKERCODE_H_
+
+// Qt includes.
+#include <qstring.h>
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+#include <qvaluelist.h>
+
+class KDE_EXPORT TalkerCode
+{
+ public:
+ /**
+ * Constructor.
+ */
+ TalkerCode(const QString &code=QString::null, bool normal=false);
+ /**
+ * Copy Constructor.
+ */
+ TalkerCode(TalkerCode* talker, bool normal=false);
+
+ /**
+ * Destructor.
+ */
+ ~TalkerCode();
+
+ typedef QValueList<TalkerCode> TalkerCodeList;
+
+ /**
+ * Properties.
+ */
+ QString languageCode() const; /* lang="xx" */
+ QString countryCode() const; /* lang="yy_xx */
+ QString voice() const; /* name="xxx" */
+ QString gender() const; /* gender="xxx" */
+ QString volume() const; /* volume="xxx" */
+ QString rate() const; /* rate="xxx" */
+ QString plugInName() const; /* synthesizer="xxx" */
+
+ /**
+ * Returns the language code plus country code (if any).
+ */
+ QString fullLanguageCode() const;
+
+ void setLanguageCode(const QString &languageCode);
+ void setCountryCode(const QString &countryCode);
+ void setVoice(const QString &voice);
+ void setGender(const QString &gender);
+ void setVolume(const QString &volume);
+ void setRate(const QString &rate);
+ void setPlugInName(const QString plugInName);
+
+ /**
+ * Sets the language code and country code (if given).
+ */
+ void setFullLanguageCode(const QString &fullLanguageCode);
+
+ /**
+ * The Talker Code returned in XML format.
+ */
+ QString getTalkerCode() const;
+
+ /**
+ * The Talker Code translated for display.
+ */
+ QString getTranslatedDescription() const;
+
+ /**
+ * Normalizes the Talker Code by filling in defaults.
+ */
+ void normalize();
+
+ /**
+ * Given a talker code, normalizes it into a standard form and also returns
+ * the full language code.
+ * @param talkerCode Unnormalized talker code.
+ * @return fullLanguageCode Language code from the talker code (including country code if any).
+ * @return Normalized talker code.
+ */
+ static QString normalizeTalkerCode(const QString &talkerCode, QString &fullLanguageCode);
+
+ /**
+ * Given a language code that might contain a country code, splits the code into
+ * the two letter language code and country code.
+ * @param fullLanguageCode Language code to be split.
+ * @return languageCode Just the language part of the code.
+ * @return countryCode The country code part (if any).
+ *
+ * If the input code begins with an asterisk, it is ignored and removed from the returned
+ * languageCode.
+ */
+ static void splitFullLanguageCode(const QString &lang, QString &languageCode, QString &countryCode);
+
+ /**
+ * Given a language code and plugin name, returns a normalized default talker code.
+ * @param fullLanguageCode Language code.
+ * @param plugInName Name of the Synthesizer plugin.
+ * @return Full normalized talker code.
+ *
+ * Example returned from defaultTalkerCode("en", "Festival")
+ * <voice lang="en" name="fixed" gender="neutral"/>
+ * <prosody volume="medium" rate="medium"/>
+ * <kttsd synthesizer="Festival" />
+ */
+ static QString defaultTalkerCode(const QString &fullLanguageCode, const QString &plugInName);
+
+ /**
+ * Converts a language code plus optional country code to language description.
+ */
+ static QString languageCodeToLanguage(const QString &languageCode);
+
+ /**
+ * These functions return translated Talker Code attributes.
+ */
+ static QString translatedGender(const QString &gender);
+ static QString translatedVolume(const QString &volume);
+ static QString translatedRate(const QString &rate);
+ static QString untranslatedGender(const QString &gender);
+ static QString untranslatedVolume(const QString &volume);
+ static QString untranslatedRate(const QString &rate);
+
+ /**
+ * Given a list of parsed talker codes and a desired talker code, finds the closest
+ * matching talker in the list.
+ * @param talkers The list of parsed talker codes.
+ * @param talker The desired talker code.
+ * @param assumeDefaultLang If true, and desired talker code lacks a language code,
+ * the default language is assumed.
+ * @return Index into talkers of the closest matching talker.
+ */
+ static int findClosestMatchingTalker(
+ const TalkerCodeList& talkers,
+ const QString& talker,
+ bool assumeDefaultLang = true);
+
+ /**
+ * Strips leading * from a code.
+ */
+ static QString stripPrefer( const QString& code, bool& preferred);
+
+ /**
+ * Uses KTrader to convert a translated Synth Plugin Name to DesktopEntryName.
+ * @param name The translated plugin name. From Name= line in .desktop file.
+ * @return DesktopEntryName. The name of the .desktop file (less .desktop).
+ * QString::null if not found.
+ */
+ static QString TalkerNameToDesktopEntryName(const QString& name);
+
+ /**
+ * Uses KTrader to convert a DesktopEntryName into a translated Synth Plugin Name.
+ * @param desktopEntryName The DesktopEntryName.
+ * @return The translated Name of the plugin, from Name= line in .desktop file.
+ */
+ static QString TalkerDesktopEntryNameToName(const QString& desktopEntryName);
+
+ private:
+ /**
+ * Given a talker code, parses out the attributes.
+ * @param talkerCode The talker code.
+ */
+ void parseTalkerCode(const QString &talkerCode);
+
+ QString m_languageCode; /* lang="xx" */
+ QString m_countryCode; /* lang="yy_xx */
+ QString m_voice; /* name="xxx" */
+ QString m_gender; /* gender="xxx" */
+ QString m_volume; /* volume="xxx" */
+ QString m_rate; /* rate="xxx" */
+ QString m_plugInName; /* synthesizer="xxx" */
+};
+
+#endif // _TALKERCODE_H_
diff --git a/kttsd/libkttsd/testplayer.cpp b/kttsd/libkttsd/testplayer.cpp
new file mode 100644
index 0000000..06d05a7
--- /dev/null
+++ b/kttsd/libkttsd/testplayer.cpp
@@ -0,0 +1,209 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Player Object for playing synthesized audio files. Plays them
+ synchronously.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qfile.h>
+
+// KDE includes.
+#include <kapplication.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+#include <kparts/componentfactory.h>
+#include <ktrader.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "player.h"
+#include "stretcher.h"
+#include "pluginconf.h"
+
+// TestPlayer includes.
+#include "testplayer.h"
+
+/**
+ * Constructor.
+ */
+TestPlayer::TestPlayer(QObject *parent, const char *name,
+ const int playerOption, const float audioStretchFactor, const QString &sinkName) :
+ QObject(parent, name)
+{
+ m_playerOption = playerOption;
+ m_audioStretchFactor = audioStretchFactor;
+ m_stretcher = 0;
+ m_player = 0;
+ m_sinkName = sinkName;
+}
+
+/**
+ * Destructor.
+ */
+TestPlayer::~TestPlayer()
+{
+ delete m_stretcher;
+ delete m_player;
+}
+
+/**
+ * Sets which audio player to use.
+ * 0 = aRts
+ * 1 = gstreamer
+ * 2 = ALSA
+ * 3 = aKode
+ */
+void TestPlayer::setPlayerOption(const int playerOption) { m_playerOption = playerOption; }
+
+/**
+ * Sets the audio stretch factor (Speed adjustment).
+ * 1.0 = normal
+ * 0.5 = twice as fast
+ * 2.0 = twice as slow
+ */
+void TestPlayer::setAudioStretchFactor(const float audioStretchFactor)
+ { m_audioStretchFactor = audioStretchFactor; }
+
+void TestPlayer::setSinkName(const QString &sinkName) { m_sinkName = sinkName; }
+
+/**
+ * Plays the specifified audio file and waits for completion.
+ * The audio file speed is adjusted according to the stretch factor.
+ * @param waveFile Name of the audio file to play.
+ */
+void TestPlayer::play(const QString &waveFile)
+{
+ // kdDebug() << "TestPlayer::play: running" << endl;
+ // Create a Stretcher object to adjust the audio Speed.
+ QString playFile = waveFile;
+ QString tmpFile;
+ if (m_audioStretchFactor != 1.0)
+ {
+ tmpFile = makeSuggestedFilename();
+ // kdDebug() << "TestPlayer::play: stretching file " << playFile << " by " << m_audioStretchFactor
+ // << " to file " << tmpFile << endl;
+ m_stretcher = new Stretcher();
+ if (m_stretcher->stretch(playFile, tmpFile, m_audioStretchFactor))
+ {
+ while (m_stretcher->getState() != Stretcher::ssFinished) qApp->processEvents();
+ playFile = m_stretcher->getOutFilename();
+ }
+ delete m_stretcher;
+ m_stretcher = 0;
+ }
+
+ // Create player object based on player option.
+ // kdDebug() << "TestPlayer::play: creating Player object with playerOption " << m_playerOption << endl;
+ m_player = createPlayerObject(m_playerOption);
+ // If player object could not be created, avoid crash is the best we can do!
+ if (!m_player) return;
+ // kdDebug() << "TestPlayer::play: starting playback." << endl;
+ m_player->startPlay(playFile);
+
+ // TODO: The following hunk of code would ideally be unnecessary. We would just
+ // return at this point and let take care of
+ // cleaning up the play object. However, because we've been called from DCOP,
+ // this seems to be necessary. The call to processEvents is problematic because
+ // it can cause re-entrancy.
+ while (m_player->playing()) qApp->processEvents();
+ // kdDebug() << "TestPlayer::play: stopping playback." << endl;
+ m_player->stop();
+ delete m_player;
+ m_player = 0;
+ if (!tmpFile.isEmpty()) QFile::remove(tmpFile);
+}
+
+/**
+ * Creates and returns a player object based on user option.
+ */
+Player* TestPlayer::createPlayerObject(int playerOption)
+{
+ Player* player = 0;
+ QString plugInName;
+ switch(playerOption)
+ {
+ case 1 :
+ {
+ plugInName = "kttsd_gstplugin";
+ break;
+ }
+ case 2 :
+ {
+ plugInName = "kttsd_alsaplugin";
+ break;
+ }
+ case 3 :
+ {
+ plugInName = "kttsd_akodeplugin";
+ break;
+ }
+ default:
+ {
+ plugInName = "kttsd_artsplugin";
+ break;
+ }
+ }
+ KTrader::OfferList offers = KTrader::self()->query(
+ "KTTSD/AudioPlugin", QString("DesktopEntryName == '%1'").arg(plugInName));
+
+ if(offers.count() == 1)
+ {
+ // kdDebug() << "TestPlayer::createPlayerObject: Loading " << offers[0]->library() << endl;
+ KLibFactory *factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if (factory)
+ player =
+ KParts::ComponentFactory::createInstanceFromLibrary<Player>(
+ offers[0]->library().latin1(), this, offers[0]->library().latin1());
+ else
+ kdDebug() << "TestPlayer::createPlayerObject: Could not create factory." << endl;
+ }
+ if (player == 0)
+ kdDebug() << "TestPlayer::createPlayerObject: Could not load " + plugInName +
+ ". Is KDEDIRS set correctly?" << endl;
+ else
+ // Must have GStreamer >= 0.8.7.
+ if (playerOption == 1)
+ {
+ if (!player->requireVersion(0, 8, 7))
+ {
+ delete player;
+ player = 0;
+ }
+ }
+ if (player) player->setSinkName(m_sinkName);
+ return player;
+}
+
+/**
+ * Constructs a temporary filename for plugins to use as a suggested filename
+ * for synthesis to write to.
+ * @return Full pathname of suggested file.
+ */
+QString TestPlayer::makeSuggestedFilename()
+{
+ KTempFile tempFile (locateLocal("tmp", "kttsmgr-"), ".wav");
+ QString waveFile = tempFile.file()->name();
+ tempFile.close();
+ QFile::remove(waveFile);
+ // kdDebug() << "TestPlayer::makeSuggestedFilename: Suggesting filename: " << waveFile << endl;
+ return PlugInConf::realFilePath(waveFile);
+}
+
diff --git a/kttsd/libkttsd/testplayer.h b/kttsd/libkttsd/testplayer.h
new file mode 100644
index 0000000..2e7339c
--- /dev/null
+++ b/kttsd/libkttsd/testplayer.h
@@ -0,0 +1,121 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Player Object for playing synthesized audio files. Plays them
+ synchronously.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _TESTPLAYER_H_
+#define _TESTPLAYER_H_
+
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+
+class Player;
+class Stretcher;
+
+// TODO: Make this work asynchronously.
+
+class KDE_EXPORT TestPlayer : public QObject{
+ public:
+ /**
+ * Constructor.
+ * @param playerOption
+ * @param audioStretchFactor
+ */
+ TestPlayer(QObject *parent = 0, const char *name = 0,
+ const int playerOption = 0, const float audioStretchFactor = 1.0,
+ const QString &sinkName = QString::null);
+
+ /**
+ * Destructor.
+ */
+ ~TestPlayer();
+
+ /**
+ * Sets which audio player to use.
+ * 0 = aRts
+ * 1 = gstreamer
+ */
+ void setPlayerOption(const int playerOption);
+
+ /**
+ * Sets the audio stretch factor (Speed adjustment).
+ * 1.0 = normal
+ * 0.5 = twice as fast
+ * 2.0 = twice as slow
+ */
+ void setAudioStretchFactor(const float audioStretchFactor);
+
+ /**
+ * Plays the specifified audio file and waits for completion.
+ * The audio file speed is adjusted according to the stretch factor.
+ * @param waveFile Name of the audio file to play.
+ */
+ void play(const QString &waveFile);
+
+ /**
+ * Sets the GStreamer Sink Name. Examples: "alsasink", "osssink", "nassink".
+ */
+ void setSinkName(const QString &sinkName);
+
+ /**
+ * Creates and returns a player object based on user option.
+ */
+ Player* createPlayerObject(int playerOption);
+
+ private:
+
+ /**
+ * Constructs a temporary filename for plugins to use as a suggested filename
+ * for synthesis to write to.
+ * @return Full pathname of suggested file.
+ */
+ QString makeSuggestedFilename();
+
+ /**
+ * Which audio player to use.
+ * 0 = aRts
+ * 1 = gstreamer
+ */
+ int m_playerOption;
+
+ /**
+ * Audio stretch factor (Speed).
+ */
+ float m_audioStretchFactor;
+
+ /**
+ * GStreamer sink name.
+ */
+ QString m_sinkName;
+
+ /**
+ * Stretcher object.
+ */
+ Stretcher* m_stretcher;
+
+ /**
+ * Player object.
+ */
+ Player* m_player;
+};
+
+#endif // _TESTPLAYER_H_
diff --git a/kttsd/libkttsd/utils.cpp b/kttsd/libkttsd/utils.cpp
new file mode 100644
index 0000000..dd9f98c
--- /dev/null
+++ b/kttsd/libkttsd/utils.cpp
@@ -0,0 +1,132 @@
+/***************************************************************************
+ Class of utility functions.
+ -------------------
+ Copyright : (C) 2004 Paul Giannaros
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+ Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com>
+ ****************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <qstring.h>
+#include <kdebug.h>
+#include <qcombobox.h>
+
+#include "utils.h"
+
+KttsUtils::KttsUtils() {
+}
+
+
+KttsUtils::~KttsUtils() {
+}
+
+/**
+ * Check if an XML document has a certain root element.
+ * @param xmldoc The document to check for the element.
+ * @param elementName The element to check for in the document.
+ * @returns True if the root element exists in the document, false otherwise.
+*/
+bool KttsUtils::hasRootElement(const QString &xmldoc, const QString &elementName) {
+ // Strip all whitespace and go from there.
+ QString doc = xmldoc.simplifyWhiteSpace();
+ // Take off the <?xml...?> if it exists
+ if(doc.startsWith("<?xml")) {
+ // Look for ?> and strip everything off from there to the start - effectively removing
+ // <?xml...?>
+ int xmlStatementEnd = doc.find("?>");
+ if(xmlStatementEnd == -1) {
+ kdDebug() << "KttsUtils::hasRootElement: Bad XML file syntax\n";
+ return false;
+ }
+ xmlStatementEnd += 2; // len '?>' == 2
+ doc = doc.right(doc.length() - xmlStatementEnd);
+ }
+ // Take off leading comments, if they exist.
+ while(doc.startsWith("<!--") || doc.startsWith(" <!--")) {
+ int commentStatementEnd = doc.find("-->");
+ if(commentStatementEnd == -1) {
+ kdDebug() << "KttsUtils::hasRootElement: Bad XML file syntax\n";
+ return false;
+ }
+ commentStatementEnd += 3; // len '>' == 2
+ doc = doc.right(doc.length() - commentStatementEnd);
+ }
+ // Take off the doctype statement if it exists.
+ while(doc.startsWith("<!DOCTYPE") || doc.startsWith(" <!DOCTYPE")) {
+ int doctypeStatementEnd = doc.find(">");
+ if(doctypeStatementEnd == -1) {
+ kdDebug() << "KttsUtils::hasRootElement: Bad XML file syntax\n";
+ return false;
+ }
+ doctypeStatementEnd += 1; // len '>' == 2
+ doc = doc.right(doc.length() - doctypeStatementEnd);
+ }
+ // We should (hopefully) be left with the root element.
+ return (doc.startsWith("<" + elementName) || doc.startsWith(" <" + elementName));
+}
+
+/**
+ * Check if an XML document has a certain DOCTYPE.
+ * @param xmldoc The document to check for the doctype.
+ * @param name The doctype name to check for. Pass QString::null to not check the name.
+ * @param publicId The public ID to check for. Pass QString::null to not check the ID.
+ * @param systemId The system ID to check for. Pass QString::null to not check the ID.
+ * @returns True if the parameters match the doctype, false otherwise.
+*/
+bool KttsUtils::hasDoctype(const QString &xmldoc, const QString &name/*, const QString &publicId, const QString &systemId*/) {
+ // Strip all whitespace and go from there.
+ QString doc = xmldoc.stripWhiteSpace();
+ // Take off the <?xml...?> if it exists
+ if(doc.startsWith("<?xml")) {
+ // Look for ?> and strip everything off from there to the start - effectively removing
+ // <?xml...?>
+ int xmlStatementEnd = doc.find("?>");
+ if(xmlStatementEnd == -1) {
+ kdDebug() << "KttsUtils::hasDoctype: Bad XML file syntax\n";
+ return false;
+ }
+ xmlStatementEnd += 2; // len '?>' == 2
+ doc = doc.right(doc.length() - xmlStatementEnd);
+ doc = doc.stripWhiteSpace();
+ }
+ // Take off leading comments, if they exist.
+ while(doc.startsWith("<!--")) {
+ int commentStatementEnd = doc.find("-->");
+ if(commentStatementEnd == -1) {
+ kdDebug() << "KttsUtils::hasDoctype: Bad XML file syntax\n";
+ return false;
+ }
+ commentStatementEnd += 3; // len '>' == 2
+ doc = doc.right(doc.length() - commentStatementEnd);
+ doc = doc.stripWhiteSpace();
+ }
+ // Match the doctype statement if it exists.
+ // kdDebug() << "KttsUtils::hasDoctype: searching " << doc.left(20) << "... for " << "<!DOCTYPE " << name << endl;
+ return (doc.startsWith("<!DOCTYPE " + name));
+}
+
+/**
+ * Sets the current item in the given combobox to the item with the given text.
+ * If item with the text not found, does nothing.
+ */
+/*static*/ void KttsUtils::setCbItemFromText(QComboBox* cb, const QString& text)
+{
+ const int itemCount = cb->count();
+ for (int ndx = 0; ndx < itemCount; ++ndx)
+ {
+ if (cb->text(ndx) == text)
+ {
+ cb->setCurrentItem(ndx);
+ return;
+ }
+ }
+}
+
diff --git a/kttsd/libkttsd/utils.h b/kttsd/libkttsd/utils.h
new file mode 100644
index 0000000..63e95bc
--- /dev/null
+++ b/kttsd/libkttsd/utils.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ Class of utility functions.
+ -------------------
+ Copyright : (C) 2004 Paul Giannaros
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+ Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com>
+ ****************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+
+class QString;
+class QComboBox;
+
+class KDE_EXPORT KttsUtils {
+
+public:
+ /// Constructor
+ KttsUtils();
+ /// Destructor
+ ~KttsUtils();
+
+ /**
+ * Check if an XML document has a certain root element.
+ * @param xmldoc The document to check for the element.
+ * @param elementName The element to check for in the document.
+ * @returns true if the root element exists in the document, false otherwise.
+ */
+ static bool hasRootElement(const QString &xmldoc, const QString &elementName);
+
+ /**
+ * Check if an XML document has a certain DOCTYPE.
+ * @param xmldoc The document to check for the doctype.
+ * @param name The doctype name to check for. Pass QString::null to not check the name.
+ * @param publicId The public ID to check for. Pass QString::null to not check the ID.
+ * @param systemId The system ID to check for. Pass QString::null to not check the ID.
+ * @returns true if the parameters match the doctype, false otherwise.
+ */
+ static bool hasDoctype(const QString &xmldoc, const QString &name/*, const QString &publicId, const QString &systemId*/);
+
+ /**
+ * Sets the current item in the given combobox to the item with the given text.
+ * If item with the text not found, does nothing.
+ */
+ static void setCbItemFromText(QComboBox* cb, const QString& text);
+
+};
+
+#endif
diff --git a/kttsd/players/Makefile.am b/kttsd/players/Makefile.am
new file mode 100644
index 0000000..f400d82
--- /dev/null
+++ b/kttsd/players/Makefile.am
@@ -0,0 +1,27 @@
+#kdevelop: artsplayer_DIR = artsplayer
+if include_kttsd_artsplayer
+ artsplayer_DIR = artsplayer
+endif
+
+#kdevelop: gstplayer_DIR = gstplayer
+if include_kttsd_gstplayer
+ gstplayer_DIR = gstplayer
+endif
+
+#kdevelop: alsaplayer_DIR = alsaplayer
+if include_kttsd_alsaplayer
+ alsaplayer_DIR = alsaplayer
+endif
+
+#kdevelop: akodeplayer_DIR = akodeplayer
+if include_kttsd_akodeplayer
+ akodeplayer_DIR = akodeplayer
+endif
+
+SUBDIRS = \
+ $(artsplayer_DIR) \
+ $(alsaplayer_DIR) \
+ $(gstplayer_DIR) \
+ $(akodeplayer_DIR)
+
+kde_servicetypes_DATA = kttsd_audioplugin.desktop
diff --git a/kttsd/players/akodeplayer/Makefile.am b/kttsd/players/akodeplayer/Makefile.am
new file mode 100644
index 0000000..f5039f6
--- /dev/null
+++ b/kttsd/players/akodeplayer/Makefile.am
@@ -0,0 +1,28 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(akode_includes) \
+ $(all_includes)
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# LIBRARY SECTION
+#########################################################################
+# This is the library that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+kde_module_LTLIBRARIES = libkttsd_akodeplugin.la
+
+libkttsd_akodeplugin_la_SOURCES = \
+ akodeplugin.cpp \
+ akodeplayer.cpp
+libkttsd_akodeplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) -no-undefined
+libkttsd_akodeplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la $(akode_libs)
+
+# Header files that should not be installed.
+noinst_HEADERS = \
+ akodeplayer.h
+
+# This library is installed as a plugin.
+services_DATA = kttsd_akodeplugin.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/kttsd/players/akodeplayer/README b/kttsd/players/akodeplayer/README
new file mode 100644
index 0000000..a45864f
--- /dev/null
+++ b/kttsd/players/akodeplayer/README
@@ -0,0 +1,19 @@
+This is an aKode audio plugin for KTTS.
+
+There are two problems right now (19 Jun 2005) that prevent this from being usable
+for KTTS:
+
+1. There was a bug in aKode that prevents it from playing .wav files. Carewolf
+ applied a patch on 13 Jun 2005 to decoderpluginhandler.cpp for this,
+ so you may need to update your kdemultimedia modules.
+
+2. aKode doesn't instantly stop when calling pause() or stop().
+ See bug:107135.
+
+If you want to try this plugin, add --enable-kttsd-akode to ./configure command.
+
+If the problems above aren't addressed, this plugin should probably be removed
+from KTTS.
+
+-- Gary Cramblitt (PhantomsDad)
+
diff --git a/kttsd/players/akodeplayer/akodeplayer.cpp b/kttsd/players/akodeplayer/akodeplayer.cpp
new file mode 100644
index 0000000..de88773
--- /dev/null
+++ b/kttsd/players/akodeplayer/akodeplayer.cpp
@@ -0,0 +1,179 @@
+/***************************************************************************
+ copyright : (C) 2004 by Allan Sandfeld Jensen
+ email : kde@carewolf.com
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <config.h>
+
+#include <kdebug.h>
+
+#include <qfile.h>
+
+#include "akode/player.h"
+#include "akode/decoder.h"
+
+#include "akodeplayer.h"
+
+using namespace aKode;
+
+////////////////////////////////////////////////////////////////////////////////
+// public methods
+////////////////////////////////////////////////////////////////////////////////
+
+aKodePlayer::aKodePlayer(QObject* parent, const char* name, const QStringList& args) :
+ Player(parent, name, args),
+ m_player(0)
+{}
+
+aKodePlayer::~aKodePlayer()
+{
+ delete m_player;
+}
+
+//void aKodePlayer::play(const FileHandle &file)
+void aKodePlayer::startPlay(const QString &file)
+{
+ kdDebug() << k_funcinfo << endl;
+
+ if (file.isNull()) { // null FileHandle file means unpause
+ if (paused())
+ // m_player->resume();
+ m_player->play();
+ else
+ stop();
+ return;
+ }
+
+ // QString filename = file.absFilePath();
+
+ kdDebug() << "Opening: " << file << endl;
+
+ if (m_player)
+ m_player->stop();
+ else {
+ m_player = new aKode::Player();
+ if (!m_player->open(m_sinkName.ascii())) {
+ kdDebug() << k_funcinfo << "Unable to open aKode " << m_sinkName << " sink. "
+ << "Falling back to auto." << endl;
+ m_player->open("auto");
+ }
+ }
+
+ if (m_player->load(QFile::encodeName(file)))
+ m_player->play();
+
+}
+
+void aKodePlayer::pause()
+{
+ if (m_player)
+ m_player->pause();
+}
+
+void aKodePlayer::stop()
+{
+ if (m_player) {
+ m_player->stop();
+ m_player->unload();
+ }
+}
+
+void aKodePlayer::setVolume(float volume)
+{
+ if (m_player)
+ m_player->setVolume(volume);
+}
+
+float aKodePlayer::volume() const
+{
+ if (m_player)
+ return m_player->volume();
+ // 1.0 is full volume
+ return 1.0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// m_player status functions
+/////////////////////////////////////////////////////////////////////////////////
+
+bool aKodePlayer::playing() const
+{
+ if (m_player && m_player->decoder())
+ return !m_player->decoder()->eof();
+ else
+ return false;
+}
+
+bool aKodePlayer::paused() const
+{
+ return m_player && (m_player->state() == aKode::Player::Paused);
+}
+
+int aKodePlayer::totalTime() const
+{
+ if (m_player) {
+ Decoder *d = m_player->decoder();
+ if (d)
+ return d->length() / 1000;
+ }
+ return -1;
+}
+
+int aKodePlayer::currentTime() const
+{
+ if (m_player) {
+ Decoder *d = m_player->decoder();
+ if (d)
+ return d->position() / 1000;
+ }
+ return -1;
+}
+
+int aKodePlayer::position() const
+{
+ if (m_player) {
+ Decoder *d = m_player->decoder();
+ if (d && d->length())
+ return (d->position()*1000)/(d->length());
+ else
+ return -1;
+ }
+ else
+ return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// m_player seek functions
+/////////////////////////////////////////////////////////////////////////////////
+
+void aKodePlayer::seek(int seekTime)
+{
+ // seek time in seconds?
+ if (m_player)
+ m_player->decoder()->seek(seekTime*1000);
+}
+
+void aKodePlayer::seekPosition(int position)
+{
+ // position unit is 1/1000th
+ if (m_player)
+ m_player->decoder()->seek((position * m_player->decoder()->length())/1000);
+}
+
+QStringList aKodePlayer::getPluginList( const QCString& /*classname*/ )
+{
+ return QStringList::split("|", "auto|polyp|alsa|jack|oss");
+}
+
+void aKodePlayer::setSinkName(const QString& sinkName) { m_sinkName = sinkName; }
+
+#include "akodeplayer.moc"
diff --git a/kttsd/players/akodeplayer/akodeplayer.h b/kttsd/players/akodeplayer/akodeplayer.h
new file mode 100644
index 0000000..bbfb3ea
--- /dev/null
+++ b/kttsd/players/akodeplayer/akodeplayer.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ copyright : (C) 2004 by Allan Sandfeld Jensen
+ email : kde@carewolf.com
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef AKODEPLAYER_H
+#define AKODEPLAYER_H
+
+#include <config.h>
+#include "kdeexportfix.h"
+
+#include <qstring.h>
+
+#include "player.h"
+#include <kdemacros.h>
+namespace aKode {
+ class File;
+ class Player;
+}
+
+class KDE_EXPORT aKodePlayer : public Player
+{
+ Q_OBJECT
+
+public:
+ aKodePlayer(QObject* parent = 0, const char* name = 0, const QStringList& args=QStringList());
+ virtual ~aKodePlayer();
+
+ // virtual void play(const FileHandle &file = FileHandle::null());
+ virtual void startPlay(const QString &file);
+
+ virtual void setVolume(float volume = 1.0);
+ virtual float volume() const;
+
+ virtual bool playing() const;
+ virtual bool paused() const;
+
+ virtual int totalTime() const;
+ virtual int currentTime() const;
+ virtual int position() const;
+
+ virtual void seek(int seekTime);
+ virtual void seekPosition(int position);
+
+ virtual QStringList getPluginList( const QCString& classname );
+ virtual void setSinkName(const QString &sinkName);
+
+public slots:
+ void pause();
+ void stop();
+
+private:
+ aKode::Player *m_player;
+ QString m_sinkName;
+};
+
+#endif
diff --git a/kttsd/players/akodeplayer/akodeplugin.cpp b/kttsd/players/akodeplayer/akodeplugin.cpp
new file mode 100644
index 0000000..9ef0deb
--- /dev/null
+++ b/kttsd/players/akodeplayer/akodeplugin.cpp
@@ -0,0 +1,29 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so aKode can be used as an audio plug in.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "akodeplayer.h"
+
+K_EXPORT_COMPONENT_FACTORY( libkttsd_akodeplugin, KGenericFactory<aKodePlayer>("kttsd_akode") );
+
diff --git a/kttsd/players/akodeplayer/kttsd_akodeplugin.desktop b/kttsd/players/akodeplayer/kttsd_akodeplugin.desktop
new file mode 100644
index 0000000..cc2c4bf
--- /dev/null
+++ b/kttsd/players/akodeplayer/kttsd_akodeplugin.desktop
@@ -0,0 +1,89 @@
+[Desktop Entry]
+Name=KTTSD aKode Plugin
+Name[br]=Lugent aKode evit KTTSD
+Name[bs]=KTTSD aKode dodatak
+Name[ca]=Connector aKode pel KTTSD
+Name[cs]=KTTSD aKode modul
+Name[da]=KTTSD aKode-plugin
+Name[de]=KTTSD aKode-Modul
+Name[el]=KTTSD πρόσθετο aKode
+Name[es]=Complemento aKode de KTTSD
+Name[et]=KTTSD aKode plugin
+Name[eu]=KTTSD-ren aKode plugina
+Name[fa]=وصلۀ KTTSD aKode
+Name[fi]=KTTSD aKode -liitännäinen
+Name[fr]=Module aKode pour KTTSD
+Name[ga]=Breiseán KTTSD aKode
+Name[gl]=Plugin aKode de KTTSD
+Name[he]=תוסף aKode עבור KTTSD
+Name[hu]=KTTSD aKode hangmodul
+Name[is]=KTTSD aKode íforrit
+Name[it]=Plugin per aKode di KTTSD
+Name[ja]=KTTSD aKode プラグイン
+Name[ka]=KTTSD aKode მოდული
+Name[km]= កម្មវិធី​ជំនួយ​ aKode សម្រាប់ KTTSD
+Name[mk]=aKode-приклучок за KTTSD
+Name[nb]=Programtillegg for KTTSD aKode
+Name[nds]=aKode-Moduul för KTTSD
+Name[ne]=KTTSD aKode प्लगइन
+Name[nl]=KTTSD aKode-plugin
+Name[pa]=KTTSD aKode ਪਲੱਗਿੰਨ
+Name[pl]=Wtyczka aKode KTTSD
+Name[pt]='Plugin' aKode do KTTSD
+Name[pt_BR]=Plug-in aKode para o KTTSD
+Name[ru]=Модуль aKode для KTTSD
+Name[sk]=Modul KTTSD aKode
+Name[sl]=Vstavek KTTSD za aKode
+Name[sr]=aKode прикључак за KTTSD
+Name[sr@Latn]=aKode priključak za KTTSD
+Name[sv]=KTTSD-insticksprogram för aKode
+Name[tg]=Модули KTTSD aKode
+Name[tr]=KTTSD aKode Eklentisi
+Name[uk]=Втулок aKode для KTTSD
+Name[vi]=Trình bổ sung KTTSD aKode
+Name[zh_TW]=KTTSD aKode 外掛程式
+Comment=KTTSD aKode audio plugin
+Comment[bg]=Аудио приставка на KTTSD за aKode
+Comment[br]=Lugent klevet aKode evit KTTSD
+Comment[ca]=Connector d'àudio aKode pel KTTSD
+Comment[cs]=KTTSD aKode zvukový modul
+Comment[da]=KTTSD aKode lyd-plugin
+Comment[de]=KTTSD aKode-Audio-Modul
+Comment[el]=KTTSD πρόσθετο ήχου aKode
+Comment[es]=Complemento de audio aKode de KTTSD
+Comment[et]=KTTSD aKode audioplugin
+Comment[eu]=KTTSD-ren aKode audio-plugina
+Comment[fa]=وصلۀ صوتی KTTSD aKode
+Comment[fi]=KTTSD aKode ääniliitännäinen
+Comment[fr]=Module audio aKode pour KTTSD
+Comment[ga]=Breiseán fuaime KTTSD aKode
+Comment[gl]=Plugin de áudio aKode para KTTSD
+Comment[hu]=KTTSD aKode hangmodul
+Comment[is]=KTTSD aKode hljóð íforrit
+Comment[it]=Plugin audio per aKode di KTTSD
+Comment[ja]=KTTSD aKode オーディオプラグイン
+Comment[ka]=KTTSD aKode აუდიო მოდული
+Comment[km]=កម្មវិធី​ជំនួយ​អូឌីយ៉ូ aKode សម្រាប់ KTTSD
+Comment[mk]=aKode-аудиоприклучок за KTTSD
+Comment[nb]=aKodes lyd-programtillegg for KTTSD
+Comment[nds]=aKode-Audiomoduul för KTTSD
+Comment[ne]=KTTSD aKode अडियो प्लगइन
+Comment[nl]=KTTSD aKode geluidsplugin
+Comment[pa]=KTTSD aKode ਆਡੀਓ ਪਲੱਗਿੰਨ
+Comment[pl]=Wtyczka dźwięku aKode dla KTTSD
+Comment[pt]='Plugin' de áudio aKode do KTTSD
+Comment[pt_BR]=Plug-in de áudio KTTSD aKode
+Comment[ru]=Модуль вывода звука KTTSD через aKode
+Comment[sk]=Modul KTTSD aKode audio
+Comment[sl]=Vstavek KTTSD za zvok v aKode
+Comment[sr]=aKode аудио прикључак за KTTSD
+Comment[sr@Latn]=aKode audio priključak za KTTSD
+Comment[sv]=KTTSD-ljudinsticksprogram för aKode
+Comment[tg]=Модули KTTSD aKode барои аудио
+Comment[tr]=KTTSD aRts ses eklentisi
+Comment[uk]=Втулок аудіо aKode для KTTSD
+Comment[vi]=Trình bổ sung âm thanh KTTSD aKode
+Comment[zh_TW]=KTTSd aKode 語音外掛程式
+Type=Service
+ServiceTypes=KTTSD/AudioPlugin
+X-KDE-Library=libkttsd_akodeplugin
diff --git a/kttsd/players/alsaplayer/Makefile.am b/kttsd/players/alsaplayer/Makefile.am
new file mode 100644
index 0000000..9653629
--- /dev/null
+++ b/kttsd/players/alsaplayer/Makefile.am
@@ -0,0 +1,30 @@
+# Include paths.
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+KDE_CXXFLAGS = -D_LARGEFILE64_SOURCE -D_GNU_SOURCE
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# LIBRARY SECTION
+#########################################################################
+# This is the library that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+kde_module_LTLIBRARIES = libkttsd_alsaplugin.la
+
+libkttsd_alsaplugin_la_SOURCES = \
+ alsaplugin.cpp \
+ alsaplayer.cpp
+libkttsd_alsaplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) $(LIBASOUND) -no-undefined
+libkttsd_alsaplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+# Header files that should not be installed.
+noinst_HEADERS = \
+ alsaplayer.h \
+ formats.h
+
+# This library is installed as a plugin.
+services_DATA = kttsd_alsaplugin.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/kttsd/players/alsaplayer/alsaplayer.cpp b/kttsd/players/alsaplayer/alsaplayer.cpp
new file mode 100644
index 0000000..d3eabe8
--- /dev/null
+++ b/kttsd/players/alsaplayer/alsaplayer.cpp
@@ -0,0 +1,1729 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ ALSA player.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ Portions based on aplay.c in alsa-utils
+ Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ Based on vplay program by Michael Beck
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// #include <sys/wait.h>
+// System includes.
+#include <config.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+// Qt includes.
+#include <qdir.h>
+#include <qapplication.h>
+#include <qcstring.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+// AlsaPlayer includes.
+#include "alsaplayer.h"
+
+#if !defined(__GNUC__) || __GNUC__ >= 3
+#define ERR(...) do {\
+ QString dbgStr;\
+ QString s = dbgStr.sprintf( "%s:%d: ERROR ", __FUNCTION__, __LINE__); \
+ s += dbgStr.sprintf( __VA_ARGS__); \
+ kdDebug() << timestamp() << "AlsaPlayer::" << s << endl; \
+} while (0)
+#else
+#define ERR(args...) do {\
+ QString dbgStr;\
+ QString s = dbgStr.sprintf( "%s:%d: ERROR ", __FUNCTION__, __LINE__); \
+ s += dbgStr.sprintf( ##args ); \
+ kdDebug() << timestamp() << "AlsaPlayer::" << s << endl; \
+} while (0)
+#endif
+
+#if !defined(__GNUC__) || __GNUC__ >= 3
+#define MSG(...) do {\
+ if (m_debugLevel >= 1) {\
+ QString dbgStr; \
+ QString s = dbgStr.sprintf( "%s:%d: ", __FUNCTION__, __LINE__); \
+ s += dbgStr.sprintf( __VA_ARGS__); \
+ kdDebug() << timestamp() << "AlsaPlayer::" << s << endl; \
+ }; \
+} while (0)
+#else
+#define MSG(args...) do {\
+ if (m_debugLevel >= 1) {\
+ QString dbgStr; \
+ QString s = dbgStr.sprintf( "%s:%d: ", __FUNCTION__, __LINE__); \
+ s += dbgStr.sprintf( ##args ); \
+ kdDebug() << timestamp() << "AlsaPlayer::" << s << endl; \
+ }; \
+} while (0)
+#endif
+
+#if !defined(__GNUC__) || __GNUC__ >= 3
+#define DBG(...) do {\
+ if (m_debugLevel >= 2) {\
+ QString dbgStr; \
+ QString s = dbgStr.sprintf( "%s:%d: ", __FUNCTION__, __LINE__); \
+ s += dbgStr.sprintf( __VA_ARGS__); \
+ kdDebug() << timestamp() << "AlsaPlayer::" << s << endl; \
+ }; \
+} while (0)
+#else
+#define DBG(args...) do {\
+ if (m_debugLevel >= 2) {\
+ QString dbgStr; \
+ QString s = dbgStr.sprintf( "%s:%d: ", __FUNCTION__, __LINE__); \
+ s += dbgStr.sprintf( ##args ); \
+ kdDebug() << timestamp() << "AlsaPlayer::" << s << endl; \
+ }; \
+} while (0)
+#endif
+
+QString AlsaPlayer::timestamp() const
+{
+ time_t t;
+ struct timeval tv;
+ char *tstr;
+ t = time(NULL);
+ tstr = strdup(ctime(&t));
+ tstr[strlen(tstr)-1] = 0;
+ gettimeofday(&tv,NULL);
+ QString ts;
+ ts.sprintf(" %s [%d] ",tstr, (int) tv.tv_usec);
+ free(tstr);
+ return ts;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// public methods
+////////////////////////////////////////////////////////////////////////////////
+
+AlsaPlayer::AlsaPlayer(QObject* parent, const char* name, const QStringList& args) :
+ Player(parent, name, args),
+ m_currentVolume(1.0),
+ m_pcmName("default"),
+ m_defPeriodSize(128),
+ m_defPeriods(8),
+ m_debugLevel(1),
+ m_simulatedPause(false)
+{
+ init();
+}
+
+AlsaPlayer::~AlsaPlayer()
+{
+ if (running()) {
+ stop();
+ wait();
+ }
+}
+
+//void AlsaPlayer::play(const FileHandle &file)
+void AlsaPlayer::startPlay(const QString &file)
+{
+ if (running()) {
+ if (paused()) {
+ if (canPause)
+ snd_pcm_pause(handle, false);
+ else
+ m_simulatedPause = false;
+ }
+ return;
+ }
+ audiofile.setName(file);
+ audiofile.open(IO_ReadOnly);
+ fd = audiofile.handle();
+ // Start thread running.
+ start();
+}
+
+/*virtual*/ void AlsaPlayer::run()
+{
+ QString pName = m_pcmName.section(" ", 0, 0);
+ DBG("pName = %s", pName.ascii());
+ pcm_name = qstrdup(pName.ascii());
+ int err;
+ snd_pcm_info_t *info;
+
+ m_simulatedPause = false;
+
+ snd_pcm_info_alloca(&info);
+
+ err = snd_output_stdio_attach(&log, stderr, 0);
+ assert(err >= 0);
+
+ rhwdata.format = DEFAULT_FORMAT;
+ rhwdata.rate = DEFAULT_SPEED;
+ rhwdata.channels = 1;
+
+ err = snd_pcm_open(&handle, pcm_name, stream, open_mode);
+ if (err < 0) {
+ ERR("audio open error on pcm device %s: %s", pcm_name, snd_strerror(err));
+ return;
+ }
+
+ if ((err = snd_pcm_info(handle, info)) < 0) {
+ ERR("info error: %s", snd_strerror(err));
+ return;
+ }
+
+ chunk_size = 1024;
+ hwdata = rhwdata;
+
+ audioBuffer.resize(1024);
+ // audiobuf = (char *)malloc(1024);
+ audiobuf = audioBuffer.data();
+ if (audiobuf == NULL) {
+ ERR("not enough memory");
+ return;
+ }
+
+ if (mmap_flag) {
+ writei_func = snd_pcm_mmap_writei;
+ readi_func = snd_pcm_mmap_readi;
+ writen_func = snd_pcm_mmap_writen;
+ readn_func = snd_pcm_mmap_readn;
+ } else {
+ writei_func = snd_pcm_writei;
+ readi_func = snd_pcm_readi;
+ writen_func = snd_pcm_writen;
+ readn_func = snd_pcm_readn;
+ }
+
+ playback(fd);
+ cleanup();
+ return;
+}
+
+void AlsaPlayer::pause()
+{
+ if (running()) {
+ DBG("Pause requested");
+ m_mutex.lock();
+ if (handle) {
+ // Some hardware can pause; some can't. canPause is set in set_params.
+ if (canPause) {
+ m_simulatedPause = false;
+ snd_pcm_pause(handle, true);
+ m_mutex.unlock();
+ } else {
+ // Set a flag and cause wait_for_poll to sleep. When resumed, will get
+ // an underrun.
+ m_simulatedPause = true;
+ m_mutex.unlock();
+ }
+ }
+ }
+}
+
+void AlsaPlayer::stop()
+{
+ if (running()) {
+ DBG("STOP! Locking mutex");
+ m_mutex.lock();
+ m_simulatedPause = false;
+ if (handle) {
+ /* This constant is arbitrary */
+ char buf = 42;
+ DBG("Request for stop, device state is %s",
+ snd_pcm_state_name(snd_pcm_state(handle)));
+ write(alsa_stop_pipe[1], &buf, 1);
+ }
+ DBG("unlocking mutex");
+ m_mutex.unlock();
+ /* Wait for thread to exit */
+ DBG("waiting for thread to exit");
+ wait();
+ DBG("cleaning up");
+ }
+ cleanup();
+}
+
+/*
+ * Stop playback, cleanup and exit thread.
+ */
+void AlsaPlayer::stopAndExit()
+{
+ // if (handle) snd_pcm_drop(handle);
+ cleanup();
+ exit();
+}
+
+void AlsaPlayer::setVolume(float volume)
+{
+ m_currentVolume = volume;
+}
+
+float AlsaPlayer::volume() const
+{
+ return m_currentVolume;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// player status functions
+/////////////////////////////////////////////////////////////////////////////////
+
+bool AlsaPlayer::playing() const
+{
+ bool result = false;
+ if (running()) {
+ m_mutex.lock();
+ if (handle) {
+ if (canPause) {
+ snd_pcm_status_t *status;
+ snd_pcm_status_alloca(&status);
+ int res;
+ if ((res = snd_pcm_status(handle, status)) < 0)
+ ERR("status error: %s", snd_strerror(res));
+ else {
+ result = (SND_PCM_STATE_RUNNING == snd_pcm_status_get_state(status))
+ || (SND_PCM_STATE_DRAINING == snd_pcm_status_get_state(status));
+ DBG("state = %s", snd_pcm_state_name(snd_pcm_status_get_state(status)));
+ }
+ } else
+ result = !m_simulatedPause;
+ }
+ m_mutex.unlock();
+ }
+ return result;
+}
+
+bool AlsaPlayer::paused() const
+{
+ bool result = false;
+ if (running()) {
+ m_mutex.lock();
+ if (handle) {
+ if (canPause) {
+ snd_pcm_status_t *status;
+ snd_pcm_status_alloca(&status);
+ int res;
+ if ((res = snd_pcm_status(handle, status)) < 0)
+ ERR("status error: %s", snd_strerror(res));
+ else {
+ result = (SND_PCM_STATE_PAUSED == snd_pcm_status_get_state(status));
+ DBG("state = %s", snd_pcm_state_name(snd_pcm_status_get_state(status)));
+ }
+ } else
+ result = m_simulatedPause;
+ }
+ m_mutex.unlock();
+ }
+ return result;
+}
+
+int AlsaPlayer::totalTime() const
+{
+ int total = 0;
+ int rate = hwdata.rate;
+ int channels = hwdata.channels;
+ if (rate > 0 && channels > 0) {
+ total = int((double(pbrec_count) / rate) / channels);
+ // DBG("pbrec_count = %i rate =%i channels = %i", pbrec_count, rate, channels);
+ // DBG("totalTime = %i", total);
+ }
+ return total;
+}
+
+int AlsaPlayer::currentTime() const
+{
+ int current = 0;
+ int rate = hwdata.rate;
+ int channels = hwdata.channels;
+ if (rate > 0 && channels > 0) {
+ current = int((double(fdcount) / rate) / channels);
+ // DBG("fdcount = %i rate = %i channels = %i", fdcount, rate, channels);
+ // DBG("currentTime = %i", current);
+ }
+ return current;
+}
+
+int AlsaPlayer::position() const
+{
+ // TODO: Make this more accurate by adding frames that have been so-far
+ // played within the Alsa ring buffer.
+ return pbrec_count > 0 ? int(double(fdcount) * 1000 / pbrec_count + .5) : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// player seek functions
+/////////////////////////////////////////////////////////////////////////////////
+
+void AlsaPlayer::seek(int /*seekTime*/)
+{
+ // TODO:
+}
+
+void AlsaPlayer::seekPosition(int /*position*/)
+{
+ // TODO:
+}
+
+/*
+ * Returns a list of PCM devices.
+ * This function fills the specified list with ALSA hardware soundcards found on the system.
+ * It uses plughw:xx instead of hw:xx for specifiers, because hw:xx are not practical to
+ * use (e.g. they require a resampler/channel mixer in the application).
+ */
+QStringList AlsaPlayer::getPluginList( const QCString& /*classname*/ )
+{
+ int err = 0;
+ int card = -1, device = -1;
+ snd_ctl_t *handle;
+ snd_ctl_card_info_t *info;
+ snd_pcm_info_t *pcminfo;
+ snd_ctl_card_info_alloca(&info);
+ snd_pcm_info_alloca(&pcminfo);
+ QStringList result;
+
+ result.append("default");
+ for (;;) {
+ err = snd_card_next(&card);
+ if (err < 0 || card < 0) break;
+ if (card >= 0) {
+ char name[32];
+ sprintf(name, "hw:%i", card);
+ if ((err = snd_ctl_open(&handle, name, 0)) < 0) continue;
+ if ((err = snd_ctl_card_info(handle, info)) < 0) {
+ snd_ctl_close(handle);
+ continue;
+ }
+ for (int devCnt=0;;++devCnt) {
+ err = snd_ctl_pcm_next_device(handle, &device);
+ if (err < 0 || device < 0) break;
+
+ snd_pcm_info_set_device(pcminfo, device);
+ snd_pcm_info_set_subdevice(pcminfo, 0);
+ snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
+ if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) continue;
+ QString infoName = " ";
+ infoName += snd_ctl_card_info_get_name(info);
+ infoName += " (";
+ infoName += snd_pcm_info_get_name(pcminfo);
+ infoName += ")";
+ if (0 == devCnt) {
+ QString pcmName = QString("default:%1").arg(card);
+ result.append(pcmName + infoName);
+ }
+ QString pcmName = QString("plughw:%1,%2").arg(card).arg(device);
+ result.append(pcmName + infoName);
+ }
+ snd_ctl_close(handle);
+ }
+ }
+ return result;
+}
+
+// QStringList AlsaPlayer::getPluginList( const QCString& /*classname*/ )
+// {
+// QStringList assumed("default");
+// snd_config_t *conf;
+// int err = snd_config_update();
+// if (err < 0) {
+// ERR("snd_config_update: %s", snd_strerror(err));
+// return assumed;
+// }
+// err = snd_config_search(snd_config, "pcm", &conf);
+// if (err < 0) return QStringList();
+// snd_config_iterator_t it = snd_config_iterator_first(conf);
+// snd_config_iterator_t itEnd = snd_config_iterator_end(conf);
+// const char* id;
+// snd_config_t *entry;
+// QStringList result;
+// snd_ctl_card_info_t *info;
+// snd_ctl_card_info_alloca(&info);
+// snd_pcm_info_t *pcminfo;
+// snd_pcm_info_alloca(&pcminfo);
+// while (it != itEnd) {
+// entry = snd_config_iterator_entry(it);
+// err = snd_config_get_id(entry, &id);
+// if (err >= 0) {
+// if (QString(id) != "default")
+// {
+// int card = -1;
+// while (snd_card_next(&card) >= 0 && card >= 0) {
+// char name[32];
+// sprintf(name, "%s:%d", id, card);
+// DBG("Checking %s", name);
+// snd_ctl_t *handle;
+// if ((err = snd_ctl_open(&handle, name, SND_CTL_NONBLOCK)) >= 0) {
+// if ((err = snd_ctl_card_info(handle, info)) >= 0) {
+// int dev = -1;
+// snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
+// while (snd_ctl_pcm_next_device(handle, &dev) >= 0 && dev >= 0) {
+// snd_pcm_info_set_device(pcminfo, dev);
+// snd_pcm_info_set_subdevice(pcminfo, 0);
+// snd_pcm_info_set_stream(pcminfo, stream);
+// if ((err = snd_ctl_pcm_info(handle, pcminfo)) >= 0) {
+// QString pluginName = name;
+// pluginName += ",";
+// pluginName += QString::number(dev);
+// pluginName += " ";
+// pluginName += snd_ctl_card_info_get_name(info);
+// pluginName += ",";
+// pluginName += snd_pcm_info_get_name(pcminfo);
+// result.append(pluginName);
+// // DBG(pluginName);
+// }
+// }
+// }
+// snd_ctl_close(handle);
+// }
+// }
+// if (card == -1) result.append(id);
+// } else result.append(id);
+// }
+// it = snd_config_iterator_next(it);
+// }
+// snd_config_update_free_global();
+// return result;
+// }
+
+void AlsaPlayer::setSinkName(const QString& sinkName) { m_pcmName = sinkName; }
+
+/////////////////////////////////////////////////////////////////////////////////
+// private
+/////////////////////////////////////////////////////////////////////////////////
+
+void AlsaPlayer::init()
+{
+ pcm_name = 0;
+ handle = 0;
+ canPause = false;
+ timelimit = 0;
+ file_type = FORMAT_DEFAULT;
+ sleep_min = 0;
+ // open_mode = 0;
+ open_mode = SND_PCM_NONBLOCK;
+ stream = SND_PCM_STREAM_PLAYBACK;
+ mmap_flag = 0;
+ interleaved = 1;
+ audiobuf = NULL;
+ chunk_size = 0;
+ period_time = 0;
+ buffer_time = 0;
+ avail_min = -1;
+ start_delay = 0;
+ stop_delay = 0;
+ buffer_pos = 0;
+ log = 0;
+ fd = -1;
+ pbrec_count = LLONG_MAX;
+ alsa_stop_pipe[0] = 0;
+ alsa_stop_pipe[1] = 0;
+ alsa_poll_fds = 0;
+ m_simulatedPause = false;
+}
+
+void AlsaPlayer::cleanup()
+{
+ DBG("cleaning up");
+ m_mutex.lock();
+ if (pcm_name) free(pcm_name);
+ if (fd >= 0) audiofile.close();
+ if (handle) {
+ snd_pcm_drop(handle);
+ snd_pcm_close(handle);
+ }
+ if (alsa_stop_pipe[0]) close(alsa_stop_pipe[0]);
+ if (alsa_stop_pipe[1]) close(alsa_stop_pipe[1]);
+ if (audiobuf) audioBuffer.resize(0);
+ if (alsa_poll_fds) alsa_poll_fds_barray.resize(0);
+ if (log) snd_output_close(log);
+ snd_config_update_free_global();
+ init();
+ m_mutex.unlock();
+}
+
+/*
+ * Safe read (for pipes)
+ */
+
+ssize_t AlsaPlayer::safe_read(int fd, void *buf, size_t count)
+{
+ ssize_t result = 0;
+ ssize_t res;
+
+ while (count > 0) {
+ if ((res = read(fd, buf, count)) == 0)
+ break;
+ if (res < 0)
+ return result > 0 ? result : res;
+ count -= res;
+ result += res;
+ buf = (char *)buf + res;
+ }
+ return result;
+}
+
+/*
+ * Test, if it is a .VOC file and return >=0 if ok (this is the length of rest)
+ * < 0 if not
+ */
+int AlsaPlayer::test_vocfile(void *buffer)
+{
+ VocHeader *vp = (VocHeader*)buffer;
+
+ if (!memcmp(vp->magic, VOC_MAGIC_STRING, 20)) {
+ vocminor = LE_SHORT(vp->version) & 0xFF;
+ vocmajor = LE_SHORT(vp->version) / 256;
+ if (LE_SHORT(vp->version) != (0x1233 - LE_SHORT(vp->coded_ver)))
+ return -2; /* coded version mismatch */
+ return LE_SHORT(vp->headerlen) - sizeof(VocHeader); /* 0 mostly */
+ }
+ return -1; /* magic string fail */
+}
+
+/*
+ * helper for test_wavefile
+ */
+
+size_t AlsaPlayer::test_wavefile_read(int fd, char *buffer, size_t *size, size_t reqsize, int line)
+{
+ if (*size >= reqsize)
+ return *size;
+ if ((size_t)safe_read(fd, buffer + *size, reqsize - *size) != reqsize - *size) {
+ ERR("read error (called from line %i)", line);
+ stopAndExit();
+ }
+ return *size = reqsize;
+}
+
+#define check_wavefile_space(buffer, len, blimit) \
+ if (len > blimit) { \
+ blimit = len; \
+ if ((buffer = (char*)realloc(buffer, blimit)) == NULL) { \
+ ERR("not enough memory"); \
+ stopAndExit(); \
+ } \
+ }
+
+/*
+ * test, if it's a .WAV file, > 0 if ok (and set the speed, stereo etc.)
+ * == 0 if not
+ * Value returned is bytes to be discarded.
+ */
+ssize_t AlsaPlayer::test_wavefile(int fd, char *_buffer, size_t size)
+{
+ WaveHeader *h = (WaveHeader *)_buffer;
+ char *buffer = NULL;
+ size_t blimit = 0;
+ WaveFmtBody *f;
+ WaveChunkHeader *c;
+ u_int type;
+ u_int len;
+
+ if (size < sizeof(WaveHeader))
+ return -1;
+ if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
+ return -1;
+ if (size > sizeof(WaveHeader)) {
+ check_wavefile_space(buffer, size - sizeof(WaveHeader), blimit);
+ memcpy(buffer, _buffer + sizeof(WaveHeader), size - sizeof(WaveHeader));
+ }
+ size -= sizeof(WaveHeader);
+ while (1) {
+ check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
+ test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
+ c = (WaveChunkHeader*)buffer;
+ type = c->type;
+ len = LE_INT(c->length);
+ len += len % 2;
+ if (size > sizeof(WaveChunkHeader))
+ memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
+ size -= sizeof(WaveChunkHeader);
+ if (type == WAV_FMT)
+ break;
+ check_wavefile_space(buffer, len, blimit);
+ test_wavefile_read(fd, buffer, &size, len, __LINE__);
+ if (size > len)
+ memmove(buffer, buffer + len, size - len);
+ size -= len;
+ }
+
+ if (len < sizeof(WaveFmtBody)) {
+ ERR("unknown length of 'fmt ' chunk (read %u, should be %u at least)", len, (u_int)sizeof(WaveFmtBody));
+ stopAndExit();
+ }
+ check_wavefile_space(buffer, len, blimit);
+ test_wavefile_read(fd, buffer, &size, len, __LINE__);
+ f = (WaveFmtBody*) buffer;
+ if (LE_SHORT(f->format) != WAV_PCM_CODE) {
+ ERR("can't play not PCM-coded WAVE-files");
+ stopAndExit();
+ }
+ if (LE_SHORT(f->modus) < 1) {
+ ERR("can't play WAVE-files with %d tracks", LE_SHORT(f->modus));
+ stopAndExit();
+ }
+ hwdata.channels = LE_SHORT(f->modus);
+ switch (LE_SHORT(f->bit_p_spl)) {
+ case 8:
+ if (hwdata.format != DEFAULT_FORMAT &&
+ hwdata.format != SND_PCM_FORMAT_U8)
+ MSG("Warning: format is changed to U8");
+ hwdata.format = SND_PCM_FORMAT_U8;
+ break;
+ case 16:
+ if (hwdata.format != DEFAULT_FORMAT &&
+ hwdata.format != SND_PCM_FORMAT_S16_LE)
+ MSG("Warning: format is changed to S16_LE");
+ hwdata.format = SND_PCM_FORMAT_S16_LE;
+ break;
+ case 24:
+ switch (LE_SHORT(f->byte_p_spl) / hwdata.channels) {
+ case 3:
+ if (hwdata.format != DEFAULT_FORMAT &&
+ hwdata.format != SND_PCM_FORMAT_S24_3LE)
+ MSG("Warning: format is changed to S24_3LE");
+ hwdata.format = SND_PCM_FORMAT_S24_3LE;
+ break;
+ case 4:
+ if (hwdata.format != DEFAULT_FORMAT &&
+ hwdata.format != SND_PCM_FORMAT_S24_LE)
+ MSG("Warning: format is changed to S24_LE");
+ hwdata.format = SND_PCM_FORMAT_S24_LE;
+ break;
+ default:
+ ERR("can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)", LE_SHORT(f->bit_p_spl), LE_SHORT(f->byte_p_spl), hwdata.channels);
+ stopAndExit();
+ }
+ break;
+ case 32:
+ hwdata.format = SND_PCM_FORMAT_S32_LE;
+ break;
+ default:
+ ERR("can't play WAVE-files with sample %d bits wide", LE_SHORT(f->bit_p_spl));
+ stopAndExit();
+ }
+ hwdata.rate = LE_INT(f->sample_fq);
+
+ if (size > len)
+ memmove(buffer, buffer + len, size - len);
+ size -= len;
+
+ while (1) {
+ u_int type, len;
+
+ check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
+ test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
+ c = (WaveChunkHeader*)buffer;
+ type = c->type;
+ len = LE_INT(c->length);
+ if (size > sizeof(WaveChunkHeader))
+ memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
+ size -= sizeof(WaveChunkHeader);
+ if (type == WAV_DATA) {
+ if (len < pbrec_count && len < 0x7ffffffe)
+ pbrec_count = len;
+ if (size > 0)
+ memcpy(_buffer, buffer, size);
+ free(buffer);
+ return size;
+ }
+ len += len % 2;
+ check_wavefile_space(buffer, len, blimit);
+ test_wavefile_read(fd, buffer, &size, len, __LINE__);
+ if (size > len)
+ memmove(buffer, buffer + len, size - len);
+ size -= len;
+ }
+
+ /* shouldn't be reached */
+ return -1;
+}
+
+/*
+ * Test for AU file.
+ */
+
+int AlsaPlayer::test_au(int fd, char *buffer)
+{
+ AuHeader *ap = (AuHeader*)buffer;
+
+ if (ap->magic != AU_MAGIC)
+ return -1;
+ if (BE_INT(ap->hdr_size) > 128 || BE_INT(ap->hdr_size) < 24)
+ return -1;
+ pbrec_count = BE_INT(ap->data_size);
+ switch (BE_INT(ap->encoding)) {
+ case AU_FMT_ULAW:
+ if (hwdata.format != DEFAULT_FORMAT &&
+ hwdata.format != SND_PCM_FORMAT_MU_LAW)
+ MSG("Warning: format is changed to MU_LAW");
+ hwdata.format = SND_PCM_FORMAT_MU_LAW;
+ break;
+ case AU_FMT_LIN8:
+ if (hwdata.format != DEFAULT_FORMAT &&
+ hwdata.format != SND_PCM_FORMAT_U8)
+ MSG("Warning: format is changed to U8");
+ hwdata.format = SND_PCM_FORMAT_U8;
+ break;
+ case AU_FMT_LIN16:
+ if (hwdata.format != DEFAULT_FORMAT &&
+ hwdata.format != SND_PCM_FORMAT_S16_BE)
+ MSG("Warning: format is changed to S16_BE");
+ hwdata.format = SND_PCM_FORMAT_S16_BE;
+ break;
+ default:
+ return -1;
+ }
+ hwdata.rate = BE_INT(ap->sample_rate);
+ if (hwdata.rate < 2000 || hwdata.rate > 256000)
+ return -1;
+ hwdata.channels = BE_INT(ap->channels);
+ if (hwdata.channels < 1 || hwdata.channels > 128)
+ return -1;
+ if ((size_t)safe_read(fd, buffer + sizeof(AuHeader), BE_INT(ap->hdr_size) - sizeof(AuHeader)) != BE_INT(ap->hdr_size) - sizeof(AuHeader)) {
+ ERR("read error");
+ stopAndExit();
+ }
+ return 0;
+}
+
+void AlsaPlayer::set_params(void)
+{
+ snd_pcm_hw_params_t *hwparams;
+ snd_pcm_uframes_t period_size;
+ int err;
+ int dir;
+ unsigned int rate;
+ unsigned int periods;
+
+ snd_pcm_hw_params_alloca(&hwparams);
+ err = snd_pcm_hw_params_any(handle, hwparams);
+ if (err < 0) {
+ ERR("Broken configuration for this PCM: no configurations available");
+ stopAndExit();
+ }
+
+ /* Create the pipe for communication about stop requests. */
+ if (pipe(alsa_stop_pipe)) {
+ ERR("Stop pipe creation failed (%s)", strerror(errno));
+ stopAndExit();
+ }
+
+ /* Find how many descriptors we will get for poll(). */
+ alsa_fd_count = snd_pcm_poll_descriptors_count(handle);
+ if (alsa_fd_count <= 0){
+ ERR("Invalid poll descriptors count returned from ALSA.");
+ stopAndExit();
+ }
+
+ /* Create and fill in struct pollfd *alsa_poll_fds with ALSA descriptors. */
+ // alsa_poll_fds = (pollfd *)malloc ((alsa_fd_count + 1) * sizeof(struct pollfd));
+ alsa_poll_fds_barray.resize((alsa_fd_count + 1) * sizeof(struct pollfd));
+ alsa_poll_fds = (pollfd *)alsa_poll_fds_barray.data();
+ assert(alsa_poll_fds);
+ if ((err = snd_pcm_poll_descriptors(handle, alsa_poll_fds, alsa_fd_count)) < 0) {
+ ERR("Unable to obtain poll descriptors for playback: %s", snd_strerror(err));
+ stopAndExit();
+ }
+
+ /* Create a new pollfd structure for requests by alsa_stop(). */
+ struct pollfd alsa_stop_pipe_pfd;
+ alsa_stop_pipe_pfd.fd = alsa_stop_pipe[0];
+ alsa_stop_pipe_pfd.events = POLLIN;
+ alsa_stop_pipe_pfd.revents = 0;
+
+ /* Join this our own pollfd to the ALSAs ones. */
+ alsa_poll_fds[alsa_fd_count] = alsa_stop_pipe_pfd;
+ ++alsa_fd_count;
+
+ if (mmap_flag) {
+ snd_pcm_access_mask_t *mask = (snd_pcm_access_mask_t *)alloca(snd_pcm_access_mask_sizeof());
+ snd_pcm_access_mask_none(mask);
+ snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
+ snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
+ snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
+ err = snd_pcm_hw_params_set_access_mask(handle, hwparams, mask);
+ } else if (interleaved)
+ err = snd_pcm_hw_params_set_access(handle, hwparams,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+ else
+ err = snd_pcm_hw_params_set_access(handle, hwparams,
+ SND_PCM_ACCESS_RW_NONINTERLEAVED);
+ if (err < 0) {
+ ERR("Error setting access type: %s", snd_strerror(err));
+ stopAndExit();
+ }
+ err = snd_pcm_hw_params_set_format(handle, hwparams, hwdata.format);
+ if (err < 0) {
+ ERR("Error setting sample format to %i: %s", hwdata.format, snd_strerror(err));
+ stopAndExit();
+ }
+ err = snd_pcm_hw_params_set_channels(handle, hwparams, hwdata.channels);
+ if (err < 0) {
+ ERR("Error setting channel count to %i: %s", hwdata.channels, snd_strerror(err));
+ stopAndExit();
+ }
+
+#if 0
+ err = snd_pcm_hw_params_set_periods_min(handle, hwparams, 2);
+ assert(err >= 0);
+#endif
+ rate = hwdata.rate;
+#if SND_LIB_MAJOR >= 1
+ err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &hwdata.rate, 0);
+#else
+ err = snd_pcm_hw_params_set_rate_near(handle, hwparams, hwdata.rate, 0);
+#endif
+ assert(err >= 0);
+ if ((float)rate * 1.05 < hwdata.rate || (float)rate * 0.95 > hwdata.rate) {
+ MSG("Warning: rate is not accurate (requested = %iHz, got = %iHz)", rate, hwdata.rate);
+ MSG(" please, try the plug plugin (-Dplug:%s)", snd_pcm_name(handle));
+ }
+
+ period_size = m_defPeriodSize;
+ dir = 1;
+#if SND_LIB_MAJOR >= 1
+ err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &dir);
+#else
+ err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, period_size, &dir);
+#endif
+ if (err < 0) {
+ MSG("Setting period_size to %lu failed, but continuing: %s", period_size, snd_strerror(err));
+ }
+
+ periods = m_defPeriods;
+ dir = 1;
+#if SND_LIB_MAJOR >= 1
+ err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &periods, &dir);
+#else
+ err = snd_pcm_hw_params_set_periods_near(handle, hwparams, periods, &dir);
+#endif
+ if (err < 0)
+ MSG("Unable to set number of periods to %i, but continuing: %s", periods, snd_strerror(err));
+
+ /* Install hw parameters. */
+ err = snd_pcm_hw_params(handle, hwparams);
+ if (err < 0) {
+ MSG("Unable to install hw params: %s", snd_strerror(err));
+ snd_pcm_hw_params_dump(hwparams, log);
+ stopAndExit();
+ }
+
+ /* Determine if device can pause. */
+ canPause = (1 == snd_pcm_hw_params_can_pause(hwparams));
+
+ /* Get final buffer size and calculate the chunk size we will pass to device. */
+#if SND_LIB_MAJOR >= 1
+ snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
+#else
+ buffer_size = snd_pcm_hw_params_get_buffer_size(hwparams);
+#endif
+ chunk_size = periods * period_size;
+
+ if (0 == chunk_size) {
+ ERR("Invalid periods or period_size. Cannot continue.");
+ stopAndExit();
+ }
+
+ if (chunk_size == buffer_size)
+ MSG("WARNING: Shouldn't use chunk_size equal to buffer_size (%lu). Continuing anyway.", chunk_size);
+
+ DBG("Final buffer_size = %lu, chunk_size = %lu, periods = %i, period_size = %lu, canPause = %i",
+ buffer_size, chunk_size, periods, period_size, canPause);
+
+ if (m_debugLevel >= 2)
+ snd_pcm_dump(handle, log);
+
+ bits_per_sample = snd_pcm_format_physical_width(hwdata.format);
+ bits_per_frame = bits_per_sample * hwdata.channels;
+ chunk_bytes = chunk_size * bits_per_frame / 8;
+ audioBuffer.resize(chunk_bytes);
+ audiobuf = audioBuffer.data();
+ if (audiobuf == NULL) {
+ ERR("not enough memory");
+ stopAndExit();
+ }
+}
+
+#ifndef timersub
+#define timersub(a, b, result) \
+do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+} while (0)
+#endif
+
+/* I/O error handler */
+void AlsaPlayer::xrun()
+{
+ snd_pcm_status_t *status;
+ int res;
+
+ snd_pcm_status_alloca(&status);
+ if ((res = snd_pcm_status(handle, status))<0) {
+ ERR("status error: %s", snd_strerror(res));
+ stopAndExit();
+ }
+ if (SND_PCM_STATE_XRUN == snd_pcm_status_get_state(status)) {
+ struct timeval now, diff, tstamp;
+ gettimeofday(&now, 0);
+ snd_pcm_status_get_trigger_tstamp(status, &tstamp);
+ timersub(&now, &tstamp, &diff);
+ MSG("%s!!! (at least %.3f ms long)",
+ stream == SND_PCM_STREAM_PLAYBACK ? "underrun" : "overrun",
+ diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+ if (m_debugLevel >= 2) {
+ DBG("Status:");
+ snd_pcm_status_dump(status, log);
+ }
+ if ((res = snd_pcm_prepare(handle))<0) {
+ ERR("xrun: prepare error: %s", snd_strerror(res));
+ stopAndExit();
+ }
+ return; /* ok, data should be accepted again */
+ } if (SND_PCM_STATE_DRAINING == snd_pcm_status_get_state(status)) {
+ if (m_debugLevel >= 2) {
+ DBG("Status(DRAINING):");
+ snd_pcm_status_dump(status, log);
+ }
+ if (stream == SND_PCM_STREAM_CAPTURE) {
+ MSG("capture stream format change? attempting recover...");
+ if ((res = snd_pcm_prepare(handle))<0) {
+ ERR("xrun(DRAINING): prepare error: %s", snd_strerror(res));
+ stopAndExit();
+ }
+ return;
+ }
+ }
+ if (m_debugLevel >= 2) {
+ DBG("Status(R/W):");
+ snd_pcm_status_dump(status, log);
+ }
+ ERR("read/write error, state = %s", snd_pcm_state_name(snd_pcm_status_get_state(status)));
+ stopAndExit();
+}
+
+/* I/O suspend handler */
+void AlsaPlayer::suspend(void)
+{
+ int res;
+
+ MSG("Suspended. Trying resume. ");
+ while ((res = snd_pcm_resume(handle)) == -EAGAIN)
+ sleep(1); /* wait until suspend flag is released */
+ if (res < 0) {
+ MSG("Failed. Restarting stream. ");
+ if ((res = snd_pcm_prepare(handle)) < 0) {
+ ERR("suspend: prepare error: %s", snd_strerror(res));
+ stopAndExit();
+ }
+ }
+ MSG("Suspend done.");
+}
+
+/* peak handler */
+void AlsaPlayer::compute_max_peak(char *data, size_t count)
+{
+ signed int val, max, max_peak = 0, perc;
+ size_t ocount = count;
+
+ switch (bits_per_sample) {
+ case 8: {
+ signed char *valp = (signed char *)data;
+ signed char mask = snd_pcm_format_silence(hwdata.format);
+ while (count-- > 0) {
+ val = *valp++ ^ mask;
+ val = abs(val);
+ if (max_peak < val)
+ max_peak = val;
+ }
+ break;
+ }
+ case 16: {
+ signed short *valp = (signed short *)data;
+ signed short mask = snd_pcm_format_silence_16(hwdata.format);
+ count /= 2;
+ while (count-- > 0) {
+ val = *valp++ ^ mask;
+ val = abs(val);
+ if (max_peak < val)
+ max_peak = val;
+ }
+ break;
+ }
+ case 32: {
+ signed int *valp = (signed int *)data;
+ signed int mask = snd_pcm_format_silence_32(hwdata.format);
+ count /= 4;
+ while (count-- > 0) {
+ val = *valp++ ^ mask;
+ val = abs(val);
+ if (max_peak < val)
+ max_peak = val;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ max = 1 << (bits_per_sample-1);
+ if (max <= 0)
+ max = 0x7fffffff;
+ DBG("Max peak (%li samples): %05i (0x%04x) ", (long)ocount, max_peak, max_peak);
+ if (bits_per_sample > 16)
+ perc = max_peak / (max / 100);
+ else
+ perc = max_peak * 100 / max;
+ for (val = 0; val < 20; val++)
+ if (val <= perc / 5)
+ kdDebug() << '#';
+ else
+ kdDebug() << ' ';
+ DBG(" %i%%", perc);
+}
+
+/*
+ * Write to the ALSA pcm.
+ */
+
+ssize_t AlsaPlayer::pcm_write(char *data, size_t count)
+{
+ ssize_t r;
+ ssize_t result = 0;
+
+ if (sleep_min == 0 && count < chunk_size) {
+ DBG("calling snd_pcm_format_set_silence");
+ snd_pcm_format_set_silence(hwdata.format, data + count * bits_per_frame / 8, (chunk_size - count) * hwdata.channels);
+ count = chunk_size;
+ }
+ while (count > 0) {
+ DBG("calling writei_func, count = %i", count);
+ r = writei_func(handle, data, count);
+ DBG("writei_func returned %i", r);
+ if (-EAGAIN == r || (r >= 0 && (size_t)r < count)) {
+ DBG("r = %i calling snd_pcm_wait", r);
+ snd_pcm_wait(handle, 100);
+ } else if (-EPIPE == r) {
+ xrun();
+ } else if (-ESTRPIPE == r) {
+ suspend();
+ } else if (-EBUSY == r){
+ MSG("WARNING: sleeping while PCM BUSY");
+ usleep(1000);
+ continue;
+ } else if (r < 0) {
+ ERR("write error: %s", snd_strerror(r));
+ stopAndExit();
+ }
+ if (r > 0) {
+ if (m_debugLevel >= 1)
+ compute_max_peak(data, r * hwdata.channels);
+ result += r;
+ count -= r;
+ data += r * bits_per_frame / 8;
+ }
+ /* Report current state */
+ DBG("PCM state before polling: %s",
+ snd_pcm_state_name(snd_pcm_state(handle)));
+
+ int err = wait_for_poll(0);
+ if (err < 0) {
+ ERR("Wait for poll() failed");
+ return -1;
+ }
+ else if (err == 1){
+ MSG("Playback stopped");
+ /* Drop the playback on the sound device (probably
+ still in progress up till now) */
+ err = snd_pcm_drop(handle);
+ if (err < 0) {
+ ERR("snd_pcm_drop() failed: %s", snd_strerror(err));
+ return -1;
+ }
+ return -1;
+ }
+ }
+ return result;
+}
+
+/*
+ * ok, let's play a .voc file
+ */
+
+ssize_t AlsaPlayer::voc_pcm_write(u_char *data, size_t count)
+{
+ ssize_t result = count, r;
+ size_t size;
+
+ while (count > 0) {
+ size = count;
+ if (size > chunk_bytes - buffer_pos)
+ size = chunk_bytes - buffer_pos;
+ memcpy(audiobuf + buffer_pos, data, size);
+ data += size;
+ count -= size;
+ buffer_pos += size;
+ if ((size_t)buffer_pos == chunk_bytes) {
+ if ((size_t)(r = pcm_write(audiobuf, chunk_size)) != chunk_size)
+ return r;
+ buffer_pos = 0;
+ }
+ }
+ return result;
+}
+
+void AlsaPlayer::voc_write_silence(unsigned x)
+{
+ unsigned l;
+ char *buf;
+
+ QByteArray buffer(chunk_bytes);
+ // buf = (char *) malloc(chunk_bytes);
+ buf = buffer.data();
+ if (buf == NULL) {
+ ERR("can't allocate buffer for silence");
+ return; /* not fatal error */
+ }
+ snd_pcm_format_set_silence(hwdata.format, buf, chunk_size * hwdata.channels);
+ while (x > 0) {
+ l = x;
+ if (l > chunk_size)
+ l = chunk_size;
+ if (voc_pcm_write((u_char*)buf, l) != (ssize_t)l) {
+ ERR("write error");
+ stopAndExit();
+ }
+ x -= l;
+ }
+ // free(buf);
+}
+
+void AlsaPlayer::voc_pcm_flush(void)
+{
+ if (buffer_pos > 0) {
+ size_t b;
+ if (sleep_min == 0) {
+ if (snd_pcm_format_set_silence(hwdata.format, audiobuf + buffer_pos, chunk_bytes - buffer_pos * 8 / bits_per_sample) < 0)
+ MSG("voc_pcm_flush - silence error");
+ b = chunk_size;
+ } else {
+ b = buffer_pos * 8 / bits_per_frame;
+ }
+ if (pcm_write(audiobuf, b) != (ssize_t)b)
+ ERR("voc_pcm_flush error");
+ }
+ snd_pcm_drain(handle);
+}
+
+void AlsaPlayer::voc_play(int fd, int ofs, const char* name)
+{
+ int l;
+ VocBlockType *bp;
+ VocVoiceData *vd;
+ VocExtBlock *eb;
+ size_t nextblock, in_buffer;
+ u_char *data, *buf;
+ char was_extended = 0, output = 0;
+ u_short *sp, repeat = 0;
+ size_t silence;
+ off64_t filepos = 0;
+
+#define COUNT(x) nextblock -= x; in_buffer -= x; data += x
+#define COUNT1(x) in_buffer -= x; data += x
+
+ QByteArray buffer(64 * 1024);
+ // data = buf = (u_char *)malloc(64 * 1024);
+ data = buf = (u_char*)buffer.data();
+ buffer_pos = 0;
+ if (data == NULL) {
+ ERR("malloc error");
+ stopAndExit();
+ }
+ MSG("Playing Creative Labs Channel file '%s'...", name);
+ /* first we waste the rest of header, ugly but we don't need seek */
+ while (ofs > (ssize_t)chunk_bytes) {
+ if ((size_t)safe_read(fd, buf, chunk_bytes) != chunk_bytes) {
+ ERR("read error");
+ stopAndExit();
+ }
+ ofs -= chunk_bytes;
+ }
+ if (ofs) {
+ if (safe_read(fd, buf, ofs) != ofs) {
+ ERR("read error");
+ stopAndExit();
+ }
+ }
+ hwdata.format = DEFAULT_FORMAT;
+ hwdata.channels = 1;
+ hwdata.rate = DEFAULT_SPEED;
+ set_params();
+
+ in_buffer = nextblock = 0;
+ while (1) {
+ Fill_the_buffer: /* need this for repeat */
+ if (in_buffer < 32) {
+ /* move the rest of buffer to pos 0 and fill the buf up */
+ if (in_buffer)
+ memcpy(buf, data, in_buffer);
+ data = buf;
+ if ((l = safe_read(fd, buf + in_buffer, chunk_bytes - in_buffer)) > 0)
+ in_buffer += l;
+ else if (!in_buffer) {
+ /* the file is truncated, so simulate 'Terminator'
+ and reduce the datablock for safe landing */
+ nextblock = buf[0] = 0;
+ if (l == -1) {
+// perror(name);
+ stopAndExit();
+ }
+ }
+ }
+ while (!nextblock) { /* this is a new block */
+ if (in_buffer < sizeof(VocBlockType))
+ goto __end;
+ bp = (VocBlockType *) data;
+ COUNT1(sizeof(VocBlockType));
+ nextblock = VOC_DATALEN(bp);
+ if (output)
+ MSG(" "); /* write /n after ASCII-out */
+ output = 0;
+ switch (bp->type) {
+ case 0:
+#if 0
+ MSG("Terminator");
+#endif
+ return; /* VOC-file stop */
+ case 1:
+ vd = (VocVoiceData *) data;
+ COUNT1(sizeof(VocVoiceData));
+ /* we need a SYNC, before we can set new SPEED, STEREO ... */
+
+ if (!was_extended) {
+ hwdata.rate = (int) (vd->tc);
+ hwdata.rate = 1000000 / (256 - hwdata.rate);
+#if 0
+ MSG("Channel data %d Hz", dsp_speed);
+#endif
+ if (vd->pack) { /* /dev/dsp can't it */
+ ERR("can't play packed .voc files");
+ return;
+ }
+ if (hwdata.channels == 2) /* if we are in Stereo-Mode, switch back */
+ hwdata.channels = 1;
+ } else { /* there was extended block */
+ hwdata.channels = 2;
+ was_extended = 0;
+ }
+ set_params();
+ break;
+ case 2: /* nothing to do, pure data */
+#if 0
+ MSG("Channel continuation");
+#endif
+ break;
+ case 3: /* a silence block, no data, only a count */
+ sp = (u_short *) data;
+ COUNT1(sizeof(u_short));
+ hwdata.rate = (int) (*data);
+ COUNT1(1);
+ hwdata.rate = 1000000 / (256 - hwdata.rate);
+ set_params();
+ silence = (((size_t) * sp) * 1000) / hwdata.rate;
+#if 0
+ MSG("Silence for %d ms", (int) silence);
+#endif
+ voc_write_silence(*sp);
+ break;
+ case 4: /* a marker for syncronisation, no effect */
+ sp = (u_short *) data;
+ COUNT1(sizeof(u_short));
+#if 0
+ MSG("Marker %d", *sp);
+#endif
+ break;
+ case 5: /* ASCII text, we copy to stderr */
+ output = 1;
+#if 0
+ MSG("ASCII - text :");
+#endif
+ break;
+ case 6: /* repeat marker, says repeatcount */
+ /* my specs don't say it: maybe this can be recursive, but
+ I don't think somebody use it */
+ repeat = *(u_short *) data;
+ COUNT1(sizeof(u_short));
+#if 0
+ MSG("Repeat loop %d times", repeat);
+#endif
+ if (filepos >= 0) { /* if < 0, one seek fails, why test another */
+ if ((filepos = lseek64(fd, 0, 1)) < 0) {
+ ERR("can't play loops; %s isn't seekable", name);
+ repeat = 0;
+ } else {
+ filepos -= in_buffer; /* set filepos after repeat */
+ }
+ } else {
+ repeat = 0;
+ }
+ break;
+ case 7: /* ok, lets repeat that be rewinding tape */
+ if (repeat) {
+ if (repeat != 0xFFFF) {
+#if 0
+ MSG("Repeat loop %d", repeat);
+#endif
+ --repeat;
+ }
+#if 0
+ else
+ MSG("Neverending loop");
+#endif
+ lseek64(fd, filepos, 0);
+ in_buffer = 0; /* clear the buffer */
+ goto Fill_the_buffer;
+ }
+#if 0
+ else
+ MSG("End repeat loop");
+#endif
+ break;
+ case 8: /* the extension to play Stereo, I have SB 1.0 :-( */
+ was_extended = 1;
+ eb = (VocExtBlock *) data;
+ COUNT1(sizeof(VocExtBlock));
+ hwdata.rate = (int) (eb->tc);
+ hwdata.rate = 256000000L / (65536 - hwdata.rate);
+ hwdata.channels = eb->mode == VOC_MODE_STEREO ? 2 : 1;
+ if (hwdata.channels == 2)
+ hwdata.rate = hwdata.rate >> 1;
+ if (eb->pack) { /* /dev/dsp can't it */
+ ERR("can't play packed .voc files");
+ return;
+ }
+#if 0
+ MSG("Extended block %s %d Hz",
+ (eb->mode ? "Stereo" : "Mono"), dsp_speed);
+#endif
+ break;
+ default:
+ ERR("unknown blocktype %d. terminate.", bp->type);
+ return;
+ } /* switch (bp->type) */
+ } /* while (! nextblock) */
+ /* put nextblock data bytes to dsp */
+ l = in_buffer;
+ if (nextblock < (size_t)l)
+ l = nextblock;
+ if (l) {
+ if (output) {
+ if (write(2, data, l) != l) { /* to stderr */
+ ERR("write error");
+ stopAndExit();
+ }
+ } else {
+ if (voc_pcm_write(data, l) != l) {
+ ERR("write error");
+ stopAndExit();
+ }
+ }
+ COUNT(l);
+ }
+ } /* while(1) */
+ __end:
+ voc_pcm_flush();
+ // free(buf);
+}
+/* that was a big one, perhaps somebody split it :-) */
+
+/* setting the globals for playing raw data */
+void AlsaPlayer::init_raw_data(void)
+{
+ hwdata = rhwdata;
+}
+
+/* calculate the data count to read from/to dsp */
+off64_t AlsaPlayer::calc_count(void)
+{
+ off64_t count;
+
+ if (timelimit == 0) {
+ count = pbrec_count;
+ } else {
+ count = snd_pcm_format_size(hwdata.format, hwdata.rate * hwdata.channels);
+ count *= (off64_t)timelimit;
+ }
+ return count < pbrec_count ? count : pbrec_count;
+}
+
+void AlsaPlayer::header(int /*rtype*/, const char* /*name*/)
+{
+// fprintf(stderr, "%s %s '%s' : ",
+// (stream == SND_PCM_STREAM_PLAYBACK) ? "Playing" : "Recording",
+// fmt_rec_table[rtype].what,
+// name);
+ QString channels;
+ if (hwdata.channels == 1)
+ channels = "Mono";
+ else if (hwdata.channels == 2)
+ channels = "Stereo";
+ else
+ channels = QString("Channels %1").arg(hwdata.channels);
+ DBG("Format: %s, Rate %d Hz, %s",
+ snd_pcm_format_description(hwdata.format),
+ hwdata.rate,
+ channels.ascii());
+}
+
+/* playing raw data */
+
+void AlsaPlayer::playback_go(int fd, size_t loaded, off64_t count, int rtype, const char *name)
+{
+ int l, r;
+ off64_t written = 0;
+ off64_t c;
+
+ if (m_debugLevel >= 1) header(rtype, name);
+ set_params();
+
+ while (loaded > chunk_bytes && written < count) {
+ if (pcm_write(audiobuf + written, chunk_size) <= 0)
+ return;
+ written += chunk_bytes;
+ loaded -= chunk_bytes;
+ }
+ if (written > 0 && loaded > 0)
+ memmove(audiobuf, audiobuf + written, loaded);
+
+ l = loaded;
+ while (written < count) {
+ do {
+ c = count - written;
+ if (c > chunk_bytes)
+ c = chunk_bytes;
+ c -= l;
+
+ if (c == 0)
+ break;
+ r = safe_read(fd, audiobuf + l, c);
+ if (r < 0) {
+// perror(name);
+ stopAndExit();
+ }
+ fdcount += r;
+ if (r == 0)
+ break;
+ l += r;
+ } while (sleep_min == 0 && (size_t)l < chunk_bytes);
+ l = l * 8 / bits_per_frame;
+ DBG("calling pcm_write with %i frames.", l);
+ r = pcm_write(audiobuf, l);
+ DBG("pcm_write returned r = %i", r);
+ if (r < 0) return;
+ if (r != l)
+ break;
+ r = r * bits_per_frame / 8;
+ written += r;
+ l = 0;
+ }
+
+ DBG("Draining...");
+
+ /* We want the next "device ready" notification only when the buffer is completely empty. */
+ /* Do this by setting the avail_min to the buffer size. */
+ int err;
+ DBG("Getting swparams");
+ snd_pcm_sw_params_t *swparams;
+ snd_pcm_sw_params_alloca(&swparams);
+ err = snd_pcm_sw_params_current(handle, swparams);
+ if (err < 0) {
+ ERR("Unable to get current swparams: %s", snd_strerror(err));
+ return;
+ }
+ DBG("Setting avail min to %lu", buffer_size);
+ err = snd_pcm_sw_params_set_avail_min(handle, swparams, buffer_size);
+ if (err < 0) {
+ ERR("Unable to set avail min for playback: %s", snd_strerror(err));
+ return;
+ }
+ /* write the parameters to the playback device */
+ DBG("Writing swparams");
+ err = snd_pcm_sw_params(handle, swparams);
+ if (err < 0) {
+ ERR("Unable to set sw params for playback: %s", snd_strerror(err));
+ return;
+ }
+
+ DBG("Waiting for poll");
+ err = wait_for_poll(1);
+ if (err < 0) {
+ ERR("Wait for poll() failed");
+ return;
+ } else if (err == 1){
+ MSG("Playback stopped while draining");
+
+ /* Drop the playback on the sound device (probably
+ still in progress up till now) */
+ err = snd_pcm_drop(handle);
+ if (err < 0) {
+ ERR("snd_pcm_drop() failed: %s", snd_strerror(err));
+ return;
+ }
+ }
+ DBG("Draining completed");
+}
+
+/*
+ * let's play or capture it (capture_type says VOC/WAVE/raw)
+ */
+
+void AlsaPlayer::playback(int fd)
+{
+ int ofs;
+ size_t dta;
+ ssize_t dtawave;
+
+ pbrec_count = LLONG_MAX;
+ fdcount = 0;
+
+ /* read the file header */
+ dta = sizeof(AuHeader);
+ if ((size_t)safe_read(fd, audiobuf, dta) != dta) {
+ ERR("read error");
+ stopAndExit();
+ }
+ if (test_au(fd, audiobuf) >= 0) {
+ rhwdata.format = hwdata.format;
+ pbrec_count = calc_count();
+ playback_go(fd, 0, pbrec_count, FORMAT_AU, name.ascii());
+ goto __end;
+ }
+ dta = sizeof(VocHeader);
+ if ((size_t)safe_read(fd, audiobuf + sizeof(AuHeader),
+ dta - sizeof(AuHeader)) != dta - sizeof(AuHeader)) {
+ ERR("read error");
+ stopAndExit();
+ }
+ if ((ofs = test_vocfile(audiobuf)) >= 0) {
+ pbrec_count = calc_count();
+ voc_play(fd, ofs, name.ascii());
+ goto __end;
+ }
+ /* read bytes for WAVE-header */
+ if ((dtawave = test_wavefile(fd, audiobuf, dta)) >= 0) {
+ pbrec_count = calc_count();
+ playback_go(fd, dtawave, pbrec_count, FORMAT_WAVE, name.ascii());
+ } else {
+ /* should be raw data */
+ init_raw_data();
+ pbrec_count = calc_count();
+ playback_go(fd, dta, pbrec_count, FORMAT_RAW, name.ascii());
+ }
+__end:
+ return;
+}
+
+/* Wait until ALSA is ready for more samples or stop() was called.
+ @return 0 if ALSA is ready for more input, +1 if a request to stop
+ the sound output was received and a negative value on error. */
+int AlsaPlayer::wait_for_poll(int draining)
+{
+ unsigned short revents;
+ snd_pcm_state_t state;
+ int ret;
+
+ DBG("Waiting for poll");
+
+ /* Wait for certain events */
+ while (1) {
+ /* Simulated pause by not writing to alsa device, which will lead to an XRUN
+ when resumed. */
+ if (m_simulatedPause)
+ msleep(500);
+ else {
+
+ ret = poll(alsa_poll_fds, alsa_fd_count, -1);
+ DBG("activity on %d descriptors", ret);
+
+ /* Check for stop request from alsa_stop on the last file descriptors. */
+ if ((revents = alsa_poll_fds[alsa_fd_count-1].revents)) {
+ if (revents & POLLIN){
+ DBG("stop requested");
+ return 1;
+ }
+ }
+
+ /* Check the first count-1 descriptors for ALSA events */
+ snd_pcm_poll_descriptors_revents(handle, alsa_poll_fds, alsa_fd_count-1, &revents);
+
+ /* Ensure we are in the right state */
+ state = snd_pcm_state(handle);
+ DBG("State after poll returned is %s", snd_pcm_state_name(state));
+
+ if (SND_PCM_STATE_XRUN == state){
+ if (!draining){
+ MSG("WARNING: Buffer underrun detected!");
+ xrun();
+ return 0;
+ }else{
+ DBG("Playback terminated");
+ return 0;
+ }
+ }
+
+ if (SND_PCM_STATE_SUSPENDED == state){
+ DBG("WARNING: Suspend detected!");
+ suspend();
+ return 0;
+ }
+
+ /* Check for errors */
+ if (revents & POLLERR) {
+ DBG("poll revents says POLLERR");
+ return -EIO;
+ }
+
+ /* Is ALSA ready for more input? */
+ if ((revents & POLLOUT)){
+ DBG("Ready for more input");
+ return 0;
+ }
+ }
+ }
+}
+
+#include "alsaplayer.moc"
+
+#undef DBG
+#undef MSG
+#undef ERR
+
+// vim: sw=4 ts=8 et
diff --git a/kttsd/players/alsaplayer/alsaplayer.h b/kttsd/players/alsaplayer/alsaplayer.h
new file mode 100644
index 0000000..acd465c
--- /dev/null
+++ b/kttsd/players/alsaplayer/alsaplayer.h
@@ -0,0 +1,187 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ ALSA player.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef ALSAPLAYER_H
+#define ALSAPLAYER_H
+
+// System includes.
+#include <alsa/asoundlib.h>
+#include <sys/poll.h>
+
+// Qt includes.
+#include <qstring.h>
+#include <qobject.h>
+#include <qthread.h>
+#include <qfile.h>
+#include <qmutex.h>
+
+// KDE includes.
+#include <config.h>
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+#include <kurl.h>
+
+// AlsaPlayer includes.
+#include "formats.h"
+#include "player.h"
+
+#ifndef LLONG_MAX
+#define LLONG_MAX 9223372036854775807LL
+#endif
+
+#define DEFAULT_FORMAT SND_PCM_FORMAT_U8
+#define DEFAULT_SPEED 8000
+
+#define FORMAT_DEFAULT -1
+#define FORMAT_RAW 0
+#define FORMAT_VOC 1
+#define FORMAT_WAVE 2
+#define FORMAT_AU 3
+
+static snd_pcm_sframes_t (*readi_func)(snd_pcm_t *handle, void *buffer, snd_pcm_uframes_t size);
+static snd_pcm_sframes_t (*writei_func)(snd_pcm_t *handle, const void *buffer, snd_pcm_uframes_t size);
+static snd_pcm_sframes_t (*readn_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);
+static snd_pcm_sframes_t (*writen_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);
+
+class KDE_EXPORT AlsaPlayer : public Player, QThread
+{
+ Q_OBJECT
+
+public:
+ AlsaPlayer(QObject* parent = 0, const char* name = 0, const QStringList& args=QStringList());
+ ~AlsaPlayer();
+
+ virtual void startPlay(const QString& file);
+ virtual void pause();
+ virtual void stop();
+
+ virtual void setVolume(float volume = 1.0);
+ virtual float volume() const;
+
+ virtual bool playing() const;
+ virtual bool paused() const;
+
+ virtual int totalTime() const;
+ virtual int currentTime() const;
+ virtual int position() const; // in this case not really the percent
+
+ virtual void seek(int seekTime);
+ virtual void seekPosition(int position);
+
+ virtual QStringList getPluginList( const QCString& classname );
+ virtual void setSinkName(const QString &sinkName);
+
+ virtual void setDebugLevel(uint level) { m_debugLevel = level; }
+ virtual void setPeriodSize(uint periodSize) { m_defPeriodSize = periodSize; }
+ virtual void setPeriods(uint periods) { m_defPeriods = periods; }
+
+protected:
+ virtual void run();
+
+private slots:
+
+private:
+ void init();
+ void cleanup();
+ void stopAndExit();
+ int wait_for_poll(int draining);
+
+ QString timestamp() const;
+
+ ssize_t safe_read(int fd, void *buf, size_t count);
+ int test_vocfile(void *buffer);
+ size_t test_wavefile_read(int fd, char *buffer, size_t *size, size_t reqsize, int line);
+ ssize_t test_wavefile(int fd, char *_buffer, size_t size);
+ int test_au(int fd, char *buffer);
+ void set_params(void);
+ void xrun();
+ void suspend(void);
+ void compute_max_peak(char *data, size_t count);
+ ssize_t pcm_write(char *data, size_t count);
+ ssize_t voc_pcm_write(u_char *data, size_t count);
+ void voc_write_silence(unsigned x);
+ void voc_pcm_flush(void);
+ void voc_play(int fd, int ofs, const char *name);
+ void init_raw_data(void);
+ off64_t calc_count(void);
+ void header(int rtype, const char *name);
+ void playback_go(int fd, size_t loaded, off64_t count, int rtype, const char *name);
+ void playback(int fd);
+
+ KURL m_currentURL;
+ float m_currentVolume;
+ QString m_pcmName;
+ char* pcm_name;
+ mutable QMutex m_mutex;
+
+ QFile audiofile;
+ QString name;
+ bool canPause;
+
+ snd_pcm_t *handle;
+ struct {
+ snd_pcm_format_t format;
+ unsigned int channels;
+ unsigned int rate;
+ } hwdata, rhwdata;
+ int timelimit;
+ int file_type;
+ unsigned int sleep_min;
+ int open_mode;
+ snd_pcm_stream_t stream;
+ int mmap_flag;
+ int interleaved;
+ QByteArray audioBuffer;
+ char *audiobuf;
+ snd_pcm_uframes_t chunk_size;
+ snd_pcm_uframes_t period_frames;
+ unsigned period_time;
+ unsigned buffer_time;
+ snd_pcm_uframes_t buffer_size;
+ int avail_min;
+ int start_delay;
+ int stop_delay;
+ int buffer_pos;
+ size_t bits_per_sample;
+ size_t bits_per_frame;
+ size_t chunk_bytes;
+ snd_output_t *log;
+ int fd;
+ off64_t pbrec_count;
+ off64_t fdcount;
+ int vocmajor;
+ int vocminor;
+
+ int alsa_stop_pipe[2]; /* Pipe for communication about stop requests*/
+ int alsa_fd_count; /* Counter of descriptors to poll */
+ QByteArray alsa_poll_fds_barray;
+ struct pollfd *alsa_poll_fds; /* Descriptors to poll */
+ unsigned int m_defPeriodSize;
+ unsigned int m_defPeriods;
+ unsigned int m_debugLevel;
+ bool m_simulatedPause;
+};
+
+#endif // ALSAPLAYER_H
+
+// vim: sw=4 ts=8 et
diff --git a/kttsd/players/alsaplayer/alsaplugin.cpp b/kttsd/players/alsaplayer/alsaplugin.cpp
new file mode 100644
index 0000000..4bd700d
--- /dev/null
+++ b/kttsd/players/alsaplayer/alsaplugin.cpp
@@ -0,0 +1,29 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so ALSA can be used as an audio plug in.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "alsaplayer.h"
+
+K_EXPORT_COMPONENT_FACTORY( libkttsd_alsaplugin, KGenericFactory<AlsaPlayer>("kttsd_alsa") )
+
diff --git a/kttsd/players/alsaplayer/formats.h b/kttsd/players/alsaplayer/formats.h
new file mode 100644
index 0000000..2c4f724
--- /dev/null
+++ b/kttsd/players/alsaplayer/formats.h
@@ -0,0 +1,110 @@
+#ifndef FORMATS_H
+#define FORMATS_H 1
+
+#include <endian.h>
+#include <byteswap.h>
+
+/* Definitions for .VOC files */
+
+#define VOC_MAGIC_STRING "Creative Voice File\x1A"
+#define VOC_ACTUAL_VERSION 0x010A
+#define VOC_SAMPLESIZE 8
+
+#define VOC_MODE_MONO 0
+#define VOC_MODE_STEREO 1
+
+#define VOC_DATALEN(bp) ((u_long)(bp->datalen) | \
+ ((u_long)(bp->datalen_m) << 8) | \
+ ((u_long)(bp->datalen_h) << 16) )
+
+typedef struct voc_header {
+ u_char magic[20]; /* must be MAGIC_STRING */
+ u_short headerlen; /* Headerlength, should be 0x1A */
+ u_short version; /* VOC-file version */
+ u_short coded_ver; /* 0x1233-version */
+} VocHeader;
+
+typedef struct voc_blocktype {
+ u_char type;
+ u_char datalen; /* low-byte */
+ u_char datalen_m; /* medium-byte */
+ u_char datalen_h; /* high-byte */
+} VocBlockType;
+
+typedef struct voc_voice_data {
+ u_char tc;
+ u_char pack;
+} VocVoiceData;
+
+typedef struct voc_ext_block {
+ u_short tc;
+ u_char pack;
+ u_char mode;
+} VocExtBlock;
+
+/* Definitions for Microsoft WAVE format */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define COMPOSE_ID(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
+#define LE_SHORT(v) (v)
+#define LE_INT(v) (v)
+#define BE_SHORT(v) bswap_16(v)
+#define BE_INT(v) bswap_32(v)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define COMPOSE_ID(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
+#define LE_SHORT(v) bswap_16(v)
+#define LE_INT(v) bswap_32(v)
+#define BE_SHORT(v) (v)
+#define BE_INT(v) (v)
+#else
+#error "Wrong endian"
+#endif
+
+#define WAV_RIFF COMPOSE_ID('R','I','F','F')
+#define WAV_WAVE COMPOSE_ID('W','A','V','E')
+#define WAV_FMT COMPOSE_ID('f','m','t',' ')
+#define WAV_DATA COMPOSE_ID('d','a','t','a')
+#define WAV_PCM_CODE 1
+
+/* it's in chunks like .voc and AMIGA iff, but my source say there
+ are in only in this combination, so I combined them in one header;
+ it works on all WAVE-file I have
+ */
+typedef struct {
+ u_int magic; /* 'RIFF' */
+ u_int length; /* filelen */
+ u_int type; /* 'WAVE' */
+} WaveHeader;
+
+typedef struct {
+ u_short format; /* should be 1 for PCM-code */
+ u_short modus; /* 1 Mono, 2 Stereo */
+ u_int sample_fq; /* frequence of sample */
+ u_int byte_p_sec;
+ u_short byte_p_spl; /* samplesize; 1 or 2 bytes */
+ u_short bit_p_spl; /* 8, 12 or 16 bit */
+} WaveFmtBody;
+
+typedef struct {
+ u_int type; /* 'data' */
+ u_int length; /* samplecount */
+} WaveChunkHeader;
+
+/* Definitions for Sparc .au header */
+
+#define AU_MAGIC COMPOSE_ID('.','s','n','d')
+
+#define AU_FMT_ULAW 1
+#define AU_FMT_LIN8 2
+#define AU_FMT_LIN16 3
+
+typedef struct au_header {
+ u_int magic; /* '.snd' */
+ u_int hdr_size; /* size of header (min 24) */
+ u_int data_size; /* size of data */
+ u_int encoding; /* see to AU_FMT_XXXX */
+ u_int sample_rate; /* sample rate */
+ u_int channels; /* number of channels (voices) */
+} AuHeader;
+
+#endif /* FORMATS */
diff --git a/kttsd/players/alsaplayer/kttsd_alsaplugin.desktop b/kttsd/players/alsaplayer/kttsd_alsaplugin.desktop
new file mode 100644
index 0000000..36eec0b
--- /dev/null
+++ b/kttsd/players/alsaplayer/kttsd_alsaplugin.desktop
@@ -0,0 +1,89 @@
+[Desktop Entry]
+Name=KTTSD ALSA Plugin
+Name[br]=Lugent ALSA evit KTTSD
+Name[bs]=KTTSD ALSA dodatak
+Name[ca]=Connector ALSA pel KTTSD
+Name[cs]=KTTSD ALSA modul
+Name[da]=KTTSD ALSA plugin
+Name[de]=KTTSD ALSA-Modul
+Name[el]=KTTSD πρόσθετο ALSA
+Name[es]=Complemento ALSA de KTTSD
+Name[et]=KTTSD ALSA plugin
+Name[eu]=KTTSD-ren ALSA plugina
+Name[fa]=وصلۀ KTTSD ALSA
+Name[fi]=KTTSD ALSA -liitännäinen
+Name[fr]=Module ALSA pour KTTSD
+Name[ga]=Breiseán KTTSD ALSA
+Name[gl]=Plugin ALSA de KTTSD
+Name[hu]=KTTSD ALSA hangmodul
+Name[is]=KTTSD ALSA íforrit
+Name[it]=Plugin per ALSA di KTTSD
+Name[ja]=KTTSD ALSA プラグイン
+Name[ka]=KTTSD ALSA მოდული
+Name[km]= កម្មវិធី​ជំនួយ​ ALSA សម្រាប់ KTTSD
+Name[mk]=ALSA-приклучок за KTTSD
+Name[nb]=Alsas programtillegg for KTTSD
+Name[nds]=ALSA-Moduul för KTTSD
+Name[ne]=KTTSD ALSA प्लगइन
+Name[nl]=KTTSD ALSA-plugin
+Name[pa]=KTTSD ALSA ਪਲੱਗਿੰਨ
+Name[pl]=Wtyczka ALSA dla KTTSD
+Name[pt]='Plugin' ALSA do KTTSD
+Name[pt_BR]=Plug-in ALSA para o KTTSD
+Name[ru]=Модуль alsa для KTTSD
+Name[sk]=Modul KTTSD ALSA
+Name[sl]=Vstavek KTTSD za ALSA
+Name[sr]=ALSA прикључак за KTTSD
+Name[sr@Latn]=ALSA priključak za KTTSD
+Name[sv]=KTTSD-insticksprogram för ALSA
+Name[tg]=Модули KTTSD ALSA
+Name[tr]=KTTSD ALSA Eklentisi
+Name[uk]=Втулок ALSA для KTTSD
+Name[vi]=Trình bổ sung KTTSD ALSA
+Name[zh_TW]=KTTSd ALSA 外掛程式
+Comment=KTTSD ALSA audio plugin
+Comment[bg]=Аудио приставка на KTTSD за ALSA
+Comment[br]=Lugent klevet ALSA evit KTTSD
+Comment[bs]=KTTSD ALSA audio dodatak
+Comment[ca]=Connector d'àudio ALSA pel KTTSD
+Comment[cs]=KTTSD ALSA zvukový modul
+Comment[da]=KTTSD ALSA lyd-plugin
+Comment[de]=KTTSD ALSA-Audio-Modul
+Comment[el]=KTTSD πρόσθετο ήχου ALSA
+Comment[es]=Complemento de audio ALSA de KTTSD
+Comment[et]=KTTSD ALSA audioplugin
+Comment[eu]=KTTSD-ren ALSA audio-plugina
+Comment[fa]=وصلۀ صوتی KTTSD ALSA
+Comment[fi]=KTTSD ALSA ääniliitännäinen
+Comment[fr]=Module audio ALSA pour KTTSD
+Comment[ga]=Breiseán fuaime KTTSD ALSA
+Comment[gl]=Plugin de áudio ALSA para KTTSD
+Comment[hu]=KTTSD ALSA hangmodul
+Comment[is]=KTTSD ALSA hljóð íforrit
+Comment[it]=Plugin audio per ALSA di KTTSD
+Comment[ja]=KTTSD ALSA オーディオプラグイン
+Comment[ka]=KTTSD ALSA აუდიო მოდული
+Comment[km]= កម្មវិធី​ជំនួយអូឌីយ៉ូ​ ALSA សម្រាប់ KTTSD
+Comment[mk]=ALSA-аудиоприклучок за KTTSD
+Comment[nb]=Alsas lyd-programtillegg for KTTSD
+Comment[nds]=ALSA-Audiomoduul för KTTSD
+Comment[ne]=KTTSD ALSA अडियो प्लगइन
+Comment[nl]=KTTSD ALSA geluidsplugin
+Comment[pa]=KTTSD ALSA ਆਡੀਓ ਪਲੱਗਿੰਨ
+Comment[pl]=Wtyczka dźwięku ALSA dla KTTSD
+Comment[pt]='Plugin' de áudio ALSA do KTTSD
+Comment[pt_BR]=Plug-in de áudio ALSA para o KTTSD
+Comment[ru]=Модуль вывода звука KTTSD через alsa
+Comment[sk]=Modul KTTSD ALSA audio
+Comment[sl]=Vstavek KTTSD za zvok v ALSA
+Comment[sr]=ALSA аудио прикључак за KTTSD
+Comment[sr@Latn]=ALSA audio priključak za KTTSD
+Comment[sv]=KTTSD-ljudinsticksprogram för ALSA
+Comment[tg]=Модули KTTSD ALSA барои аудио
+Comment[tr]=KTTSD ALSA ses eklentisi
+Comment[uk]=Втулок аудіо ALSA для KTTSD
+Comment[vi]=Trình bổ sung âm thanh KTTSD ALSA
+Comment[zh_TW]=KTTSd ALSA 語音外掛程式
+Type=Service
+ServiceTypes=KTTSD/AudioPlugin
+X-KDE-Library=libkttsd_alsaplugin
diff --git a/kttsd/players/artsplayer/Makefile.am b/kttsd/players/artsplayer/Makefile.am
new file mode 100644
index 0000000..d5c6012
--- /dev/null
+++ b/kttsd/players/artsplayer/Makefile.am
@@ -0,0 +1,30 @@
+# Include paths. INCLUDES is maintained by KDevelop, AM_CPPFLAGS is the preferred variable,
+# so keep them synchronized.
+INCLUDES = \
+ -I$(kde_includes)/arts \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# LIBRARY SECTION
+#########################################################################
+# This is the library that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+kde_module_LTLIBRARIES = libkttsd_artsplugin.la
+
+libkttsd_artsplugin_la_SOURCES = \
+ artsplugin.cpp \
+ artsplayer.cpp
+libkttsd_artsplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) -no-undefined
+libkttsd_artsplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la -lartskde
+
+# Header files that should not be installed.
+noinst_HEADERS = \
+ artsplayer.h
+
+# This library is installed as a plugin.
+services_DATA = kttsd_artsplugin.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/kttsd/players/artsplayer/artsplayer.cpp b/kttsd/players/artsplayer/artsplayer.cpp
new file mode 100644
index 0000000..512765a
--- /dev/null
+++ b/kttsd/players/artsplayer/artsplayer.cpp
@@ -0,0 +1,296 @@
+/***************************************************************************
+ begin : Sun Feb 17 2002
+ copyright : (C) 2002 - 2004 by Scott Wheeler
+ email : wheeler@kde.org
+
+ copyright : (C) 2003 by Matthias Kretz
+ email : kretz@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "artsplayer.h"
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+
+#include <qdir.h>
+#include <qapplication.h>
+
+#include <kartsserver.h>
+#include <kartsdispatcher.h>
+#include <kplayobject.h>
+#include <kplayobjectfactory.h>
+
+#include <sys/wait.h>
+
+#include <kmessagebox.h>
+#include <kaudiomanagerplay.h>
+#include <klocale.h>
+
+////////////////////////////////////////////////////////////////////////////////
+// public methods
+////////////////////////////////////////////////////////////////////////////////
+
+ArtsPlayer::ArtsPlayer(QObject* parent, const char* name, const QStringList& args) :
+ Player(parent, name, args),
+ m_dispatcher(0),
+ m_server(0),
+ m_factory(0),
+ m_playobject(0),
+ m_amanPlay(0),
+ m_volumeControl(Arts::StereoVolumeControl::null()),
+ m_currentVolume(1.0)
+{
+}
+
+ArtsPlayer::~ArtsPlayer()
+{
+ delete m_playobject;
+ delete m_factory;
+ delete m_amanPlay;
+ delete m_server;
+ delete m_dispatcher;
+}
+
+//void ArtsPlayer::play(const FileHandle &file)
+void ArtsPlayer::startPlay(const QString &file)
+{
+ if (!m_dispatcher)
+ setupPlayer();
+
+ // kdDebug(65432) << k_funcinfo << endl;
+ // Make sure that the server still exists, if it doesn't a new one should
+ // be started automatically and the factory and amanPlay are created again.
+
+ if(!file.isNull())
+// m_currentURL.setPath(file.absFilePath());
+ m_currentURL.setPath(file);
+
+ if(m_server->server().isNull()) {
+ KMessageBox::error(0, i18n("Cannot find the aRts soundserver."));
+ return;
+ }
+
+ if(!m_playobject || !file.isNull()) {
+ stop();
+
+ delete m_playobject;
+ m_playobject = m_factory->createPlayObject(m_currentURL, false);
+
+ if(m_playobject->object().isNull())
+ connect(m_playobject, SIGNAL(playObjectCreated()), SLOT(playObjectCreated()));
+ else
+ playObjectCreated();
+ }
+
+ m_playobject->play();
+}
+
+void ArtsPlayer::pause()
+{
+ // kdDebug(65432) << k_funcinfo << endl;
+ if(m_playobject)
+ m_playobject->pause();
+}
+
+void ArtsPlayer::stop()
+{
+ // kdDebug(65432) << k_funcinfo << endl;
+ if(m_playobject) {
+ m_playobject->halt();
+ delete m_playobject;
+ m_playobject = 0;
+ }
+ if(!m_volumeControl.isNull()) {
+ m_volumeControl.stop();
+ m_volumeControl = Arts::StereoVolumeControl::null();
+ }
+}
+
+void ArtsPlayer::setVolume(float volume)
+{
+ // kdDebug( 65432 ) << k_funcinfo << endl;
+
+ m_currentVolume = volume;
+
+ if(serverRunning() && m_playobject && !m_playobject->isNull()) {
+ if(m_volumeControl.isNull())
+ setupVolumeControl();
+ if(!m_volumeControl.isNull()) {
+ m_volumeControl.scaleFactor(volume);
+ // kdDebug( 65432 ) << "set volume to " << volume << endl;
+ }
+ }
+}
+
+float ArtsPlayer::volume() const
+{
+ return m_currentVolume;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// player status functions
+/////////////////////////////////////////////////////////////////////////////////
+
+bool ArtsPlayer::playing() const
+{
+ if(serverRunning() && m_playobject && m_playobject->state() == Arts::posPlaying)
+ return true;
+ else
+ return false;
+}
+
+bool ArtsPlayer::paused() const
+{
+ if(serverRunning() && m_playobject && m_playobject->state() == Arts::posPaused)
+ return true;
+ else
+ return false;
+}
+
+int ArtsPlayer::totalTime() const
+{
+ if(serverRunning() && m_playobject)
+ return m_playobject->overallTime().seconds;
+ else
+ return -1;
+}
+
+int ArtsPlayer::currentTime() const
+{
+ if(serverRunning() && m_playobject &&
+ (m_playobject->state() == Arts::posPlaying ||
+ m_playobject->state() == Arts::posPaused))
+ {
+ return m_playobject->currentTime().seconds;
+ }
+ else
+ return -1;
+}
+
+int ArtsPlayer::position() const
+{
+ if(serverRunning() && m_playobject && m_playobject->state() == Arts::posPlaying) {
+ long total = m_playobject->overallTime().seconds * 1000 + m_playobject->overallTime().ms;
+ long current = m_playobject->currentTime().seconds * 1000 + m_playobject->currentTime().ms;
+
+ // add .5 to make rounding happen properly
+
+ return int(double(current) * 1000 / total + .5);
+ }
+ else
+ return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// player seek functions
+/////////////////////////////////////////////////////////////////////////////////
+
+void ArtsPlayer::seek(int seekTime)
+{
+ if(serverRunning() && m_playobject) {
+ Arts::poTime poSeekTime;
+ poSeekTime.custom = 0;
+ poSeekTime.ms = 0;
+ poSeekTime.seconds = seekTime;
+ m_playobject->object().seek(poSeekTime);
+ }
+}
+
+void ArtsPlayer::seekPosition(int position)
+{
+ if(serverRunning() && m_playobject) {
+ Arts::poTime poSeekTime;
+ long total = m_playobject->overallTime().seconds;
+ poSeekTime.custom = 0;
+ poSeekTime.ms = 0;
+ poSeekTime.seconds = long(double(total) * position / 1000 + .5);
+ m_playobject->object().seek(poSeekTime);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// private
+/////////////////////////////////////////////////////////////////////////////////
+
+void ArtsPlayer::setupArtsObjects()
+{
+ // kdDebug( 65432 ) << k_funcinfo << endl;
+ delete m_factory;
+ delete m_amanPlay;
+ m_volumeControl = Arts::StereoVolumeControl::null();
+ m_factory = new KDE::PlayObjectFactory(m_server);
+ m_amanPlay = new KAudioManagerPlay(m_server);
+
+ if(m_amanPlay->isNull() || !m_factory) {
+ KMessageBox::error(0, i18n("Connecting/starting aRts soundserver failed. "
+ "Make sure that artsd is configured properly."));
+ qApp->exit(1);
+ }
+
+ m_amanPlay->setTitle(i18n("kttsd"));
+ m_amanPlay->setAutoRestoreID("kttsdAmanPlay");
+
+ m_factory->setAudioManagerPlay(m_amanPlay);
+}
+
+void ArtsPlayer::playObjectCreated()
+{
+ // kdDebug(65432) << k_funcinfo << endl;
+ setVolume(m_currentVolume);
+}
+
+void ArtsPlayer::setupPlayer()
+{
+ m_dispatcher = new KArtsDispatcher;
+ m_server = new KArtsServer;
+ setupArtsObjects();
+ connect(m_server, SIGNAL(restartedServer()), SLOT(setupArtsObjects()));
+}
+
+void ArtsPlayer::setupVolumeControl()
+{
+ // kdDebug( 65432 ) << k_funcinfo << endl;
+ m_volumeControl = Arts::DynamicCast(m_server->server().createObject("Arts::StereoVolumeControl"));
+ if(!m_volumeControl.isNull() && !m_playobject->isNull() && !m_playobject->object().isNull()) {
+ Arts::Synth_AMAN_PLAY ap = m_amanPlay->amanPlay();
+ Arts::PlayObject po = m_playobject->object();
+ ap.stop();
+ Arts::disconnect(po, "left" , ap, "left" );
+ Arts::disconnect(po, "right", ap, "right");
+
+ m_volumeControl.start();
+ ap.start();
+
+ Arts::connect(po, "left" , m_volumeControl, "inleft" );
+ Arts::connect(po, "right", m_volumeControl, "inright");
+ Arts::connect(m_volumeControl, "outleft" , ap, "left" );
+ Arts::connect(m_volumeControl, "outright", ap, "right");
+ // kdDebug( 65432 ) << "connected volume control" << endl;
+ }
+ else {
+ m_volumeControl = Arts::StereoVolumeControl::null();
+ kdDebug(65432) << "Could not initialize volume control!" << endl;
+ }
+}
+
+bool ArtsPlayer::serverRunning() const
+{
+ if(m_server)
+ return !(m_server->server().isNull());
+ else
+ return false;
+}
+
+#include "artsplayer.moc"
+
+// vim: sw=4 ts=8 et
diff --git a/kttsd/players/artsplayer/artsplayer.h b/kttsd/players/artsplayer/artsplayer.h
new file mode 100644
index 0000000..96d62f6
--- /dev/null
+++ b/kttsd/players/artsplayer/artsplayer.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ begin : Sun Feb 17 2002
+ copyright : (C) 2002 - 2004 by Scott Wheeler
+ email : wheeler@kde.org
+
+ copyright : (C) 2003 by Matthias Kretz
+ email : kretz@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef ARTSPLAYER_H
+#define ARTSPLAYER_H
+
+#include <config.h>
+#include <kdemacros.h>
+#include "kdeexportfix.h"
+
+#include "player.h"
+
+#include <kurl.h>
+
+#include <qstring.h>
+#include <qobject.h>
+#include <artsflow.h>
+
+class KArtsDispatcher;
+class KArtsServer;
+class KAudioManagerPlay;
+
+namespace KDE {
+ class PlayObjectFactory;
+ class PlayObject;
+}
+
+class KDE_EXPORT ArtsPlayer : public Player
+{
+ Q_OBJECT
+
+public:
+ ArtsPlayer(QObject* parent = 0, const char* name = 0, const QStringList& args=QStringList());
+ ~ArtsPlayer();
+
+// virtual void play(const FileHandle &file = FileHandle::null());
+ virtual void startPlay(const QString& file);
+ virtual void pause();
+ virtual void stop();
+
+ virtual void setVolume(float volume = 1.0);
+ virtual float volume() const;
+
+ virtual bool playing() const;
+ virtual bool paused() const;
+
+ virtual int totalTime() const;
+ virtual int currentTime() const;
+ virtual int position() const; // in this case not really the percent
+
+ virtual void seek(int seekTime);
+ virtual void seekPosition(int position);
+
+private slots:
+ void setupArtsObjects();
+ void playObjectCreated();
+
+private:
+ void setupPlayer();
+ void setupVolumeControl();
+ bool serverRunning() const;
+
+ KArtsDispatcher *m_dispatcher;
+ KArtsServer *m_server;
+ KDE::PlayObjectFactory *m_factory;
+ KDE::PlayObject *m_playobject;
+ KAudioManagerPlay *m_amanPlay;
+
+ // This is a pretty heavy module for the needs that JuK has, it would probably
+ // be good to use two Synth_MUL instead or the one from Noatun.
+
+ Arts::StereoVolumeControl m_volumeControl;
+
+ KURL m_currentURL;
+ float m_currentVolume;
+};
+
+#endif
+
+// vim: sw=4 ts=8 et
diff --git a/kttsd/players/artsplayer/artsplugin.cpp b/kttsd/players/artsplayer/artsplugin.cpp
new file mode 100644
index 0000000..36f4517
--- /dev/null
+++ b/kttsd/players/artsplayer/artsplugin.cpp
@@ -0,0 +1,29 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so aRts can be used as an audio plug in.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "artsplayer.h"
+
+K_EXPORT_COMPONENT_FACTORY( libkttsd_artsplugin, KGenericFactory<ArtsPlayer>("kttsd_arts") )
+
diff --git a/kttsd/players/artsplayer/kttsd_artsplugin.desktop b/kttsd/players/artsplayer/kttsd_artsplugin.desktop
new file mode 100644
index 0000000..9eef151
--- /dev/null
+++ b/kttsd/players/artsplayer/kttsd_artsplugin.desktop
@@ -0,0 +1,91 @@
+[Desktop Entry]
+Name=KTTSD Arts Plugin
+Name[br]=Lugent Arts evit KTTSD
+Name[bs]=KTTSD Arts dodatak
+Name[ca]=Connector Arts pel KTTSD
+Name[cs]=KTTSD Arts modul
+Name[da]=KTTSD aRts-plugin
+Name[de]=KTTSD Arts-Modul
+Name[el]=KTTSD πρόσθετο Arts
+Name[es]=Complemento KTTSD Arts
+Name[et]=KTTSD Artsi plugin
+Name[eu]=KTTSD-ren Arts-plugina
+Name[fa]=وصلۀ KTTSD Arts
+Name[fi]=KTTSD Arts -liitännäinen
+Name[fr]=Module Arts pour KTTSD
+Name[ga]=Breiseán KTTSD Arts
+Name[gl]=Plugin Arts de KTTSD
+Name[hu]=KTTSD aRts hangmodul
+Name[is]=KTTSD Arts íforrit
+Name[it]=Plugin per Arts di KTTSD
+Name[ja]=KTTSD aRts プラグイン
+Name[ka]=KTTSD Arts მოდული
+Name[km]=កម្មវិធី​ជំនួយ Arts សម្រាប់ KTTSD
+Name[mk]=aRts-приклучок за KTTSD
+Name[nb]=Arts programtillegg for KTTSD
+Name[nds]=aRts-Moduul för KTTSD
+Name[ne]=KTTSD कला प्लगइन
+Name[nl]=KTTSD Arts-plugin
+Name[pa]=KTTSD Arts ਪਲੱਗਿੰਨ
+Name[pl]=Wtyczka aRts KTTSD
+Name[pt]='Plugin' Arts do KTTSD
+Name[pt_BR]=Plug-in do Arts para o KTTSD
+Name[ru]=Модуль Arts для KTTSD
+Name[sk]=Modul KTTSD Arts
+Name[sl]=Vstavek KTTSD za aRts
+Name[sr]=Arts као прикључак за KTTSD
+Name[sr@Latn]=Arts kao priključak za KTTSD
+Name[sv]=KTTSD-insticksprogram för aRts
+Name[ta]=KTTSD ஆர்ட்ஸ் சொருகுப்பொருள்
+Name[tg]=Модули Arts барои KTTSD
+Name[tr]=KTTSD Arts Eklentisi
+Name[uk]=Втулок Arts для KTTSD
+Name[vi]=Trình bổ sung KTTSD Arts
+Name[zh_TW]=KTTSd Arts 外掛程式
+Comment=KTTSD aRts audio plugin
+Comment[bg]=Аудио приставка на KTTSD за aRts
+Comment[br]=Lugent klevet Arts evit KTTSD
+Comment[ca]=Connector d'àudio aRts pel KTTSD
+Comment[cs]=KTTSD aRts zvukový modul
+Comment[da]=KTTSD aRts lyd-plugin
+Comment[de]=KTTSD aRts Audio-Modul
+Comment[el]=KTTSD πρόσθετο ήχου aRts
+Comment[es]=Complemento de audio KTTSD aRts
+Comment[et]=KTTSD aRts'i audioplugin
+Comment[eu]=KTTSD-ren aRts audio-plugina
+Comment[fa]=وصلۀ صوتی KTTSD aRts
+Comment[fi]=KTTSD aRts ääniliitännäinen
+Comment[fr]=Module audio Arts pour KTTSD
+Comment[ga]=Breiseán fuaime KTTSD aRts
+Comment[gl]=Plugin de áudio aRts para KTTSD
+Comment[hu]=KTTSD hangmodul az aRts hangrendszerhez
+Comment[is]=KTTSD aRts hljóð íforrit
+Comment[it]=Plugin audio per aRts di KTTSD
+Comment[ja]=KTTSD aRts オーディオプラグイン
+Comment[ka]=KTTSD aRts აუდიო მოდული
+Comment[km]=កម្មវិធី​ជំនួយ​អូឌីយ៉ូ aRts សម្រាប់ KTTSD
+Comment[mk]=aRts-аудиоприклучок за KTTSD
+Comment[ms]=Plugin audio aRts KTTSD
+Comment[nb]=aRts lyd-programtillegg for KTTSD
+Comment[nds]=aRts-Audiomoduul för KTTSD
+Comment[ne]=KTTSD कला अडियो प्लगइन
+Comment[nl]=KTTSD aRts-audioplugin
+Comment[pa]=KTTSD aRts ਆਡੀਓ ਪਲੱਗਿੰਨ
+Comment[pl]=Wtyczka dźwięku aRts dla KTTSD
+Comment[pt]='Plugin' áudio aRts do KTTSD
+Comment[pt_BR]=Plug-in de áudio do Arts para o KTTSD
+Comment[ru]=Модуль вывода звука KTTSD через aRts
+Comment[sk]=Modul KTTSD aRts audio
+Comment[sl]=Vstavek KTTSD za zvok v aRts
+Comment[sr]=Arts као аудио прикључак за KTTSD
+Comment[sr@Latn]=Arts kao audio priključak za KTTSD
+Comment[sv]=KTTSD-ljudinsticksprogram för aRts
+Comment[ta]=KTTSD aRts கேட்பொலி சொருகுப்பொருள்
+Comment[tg]=Модули барориши овози KTTSD ба воситаи aRts
+Comment[tr]=KTTSD aRts ses eklentisi
+Comment[uk]=Звуковий втулок aRts для KTTSD
+Comment[vi]=Trình bổ sung âm thanh KTTSD aRts
+Comment[zh_TW]=KTTSd aRts 語音外掛程式
+Type=Service
+ServiceTypes=KTTSD/AudioPlugin
+X-KDE-Library=libkttsd_artsplugin
diff --git a/kttsd/players/gstplayer/Makefile.am b/kttsd/players/gstplayer/Makefile.am
new file mode 100644
index 0000000..df00c55
--- /dev/null
+++ b/kttsd/players/gstplayer/Makefile.am
@@ -0,0 +1,30 @@
+# Include paths. INCLUDES is maintained by KDevelop, AM_CPPFLAGS is the preferred variable,
+# so keep them synchronized.
+INCLUDES = \
+ $(GST_CFLAGS) \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# LIBRARY SECTION
+#########################################################################
+# This is the library that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+kde_module_LTLIBRARIES = libkttsd_gstplugin.la
+
+libkttsd_gstplugin_la_SOURCES = \
+ gstplugin.cpp \
+ gstreamerplayer.cpp
+libkttsd_gstplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) $(LDFLAGS_GST) -no-undefined
+libkttsd_gstplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la $(LDADD_GST)
+
+# Header files that should not be installed.
+noinst_HEADERS = \
+ gstreamerplayer.h
+
+# This library is installed as a plugin.
+services_DATA = kttsd_gstplugin.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/kttsd/players/gstplayer/gstplugin.cpp b/kttsd/players/gstplayer/gstplugin.cpp
new file mode 100644
index 0000000..633bff9
--- /dev/null
+++ b/kttsd/players/gstplayer/gstplugin.cpp
@@ -0,0 +1,29 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so that GStreamer can be used as and audio plug in.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "gstreamerplayer.h"
+
+K_EXPORT_COMPONENT_FACTORY( libkttsd_gstplugin, KGenericFactory<GStreamerPlayer>("kttsd_gst") );
+
diff --git a/kttsd/players/gstplayer/gstreamerplayer.cpp b/kttsd/players/gstplayer/gstreamerplayer.cpp
new file mode 100644
index 0000000..64aa1c4
--- /dev/null
+++ b/kttsd/players/gstplayer/gstreamerplayer.cpp
@@ -0,0 +1,258 @@
+/***************************************************************************
+ copyright : (C) 2004 Scott Wheeler
+ email : wheeler@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qfile.h>
+
+// KDE includes.
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+// GStreamerPlayer includes.
+#include "gstreamerplayer.h"
+#include "gstreamerplayer.moc"
+
+////////////////////////////////////////////////////////////////////////////////
+// public methods
+////////////////////////////////////////////////////////////////////////////////
+
+GStreamerPlayer::GStreamerPlayer(QObject* parent, const char* name, const QStringList& args) :
+ Player(parent, name, args),
+ m_initialized(false),
+ m_pipeline(0),
+ m_source(0),
+ m_decoder(0),
+ m_volume(0),
+ m_sink(0)
+{
+ // readConfig();
+ setupPipeline();
+}
+
+GStreamerPlayer::~GStreamerPlayer()
+{
+ stop();
+ gst_object_unref(GST_OBJECT(m_pipeline));
+}
+
+//void GStreamerPlayer::play(const FileHandle &file)
+void GStreamerPlayer::startPlay(const QString &file)
+{
+ if(!file.isNull()) {
+ stop();
+ // g_object_set(G_OBJECT(m_source), "location", file.absFilePath().local8Bit().data(), 0);
+ g_object_set(G_OBJECT(m_source),"location",file.local8Bit().data(),NULL);
+ }
+
+ gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
+}
+
+void GStreamerPlayer::pause()
+{
+ gst_element_set_state(m_pipeline, GST_STATE_PAUSED);
+}
+
+void GStreamerPlayer::stop()
+{
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+}
+
+void GStreamerPlayer::setVolume(float volume)
+{
+ g_object_set(G_OBJECT(m_volume), "volume", volume, NULL);
+}
+
+float GStreamerPlayer::volume() const
+{
+ gfloat value;
+ g_object_get(G_OBJECT(m_volume), "volume", &value, NULL);
+ return value;
+}
+
+bool GStreamerPlayer::playing() const
+{
+ return gst_element_get_state(m_pipeline) == GST_STATE_PLAYING;
+}
+
+bool GStreamerPlayer::paused() const
+{
+ return gst_element_get_state(m_pipeline) == GST_STATE_PAUSED;
+}
+
+int GStreamerPlayer::totalTime() const
+{
+ return time(GST_QUERY_TOTAL) / GST_SECOND;
+}
+
+int GStreamerPlayer::currentTime() const
+{
+ return time(GST_QUERY_POSITION) / GST_SECOND;
+}
+
+int GStreamerPlayer::position() const
+{
+ long long total = time(GST_QUERY_TOTAL);
+ long long current = time(GST_QUERY_POSITION);
+ return total > 0 ? int((double(current) / double(total)) * double(1000) + 0.5) : 0;
+}
+
+void GStreamerPlayer::seek(int seekTime)
+{
+ int type = (GST_FORMAT_TIME | GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH);
+ gst_element_seek(m_sink, GstSeekType(type), seekTime * GST_SECOND);
+}
+
+void GStreamerPlayer::seekPosition(int position)
+{
+ long long total = time(GST_QUERY_TOTAL);
+ if(total > 0)
+ seek(int(double(position) / double(1000) * double(totalTime()) + 0.5));
+}
+
+/**
+ * Returns a list of GStreamer plugins of the specified class.
+ * @param classname Desired class. Use "Sink/Audio" for sinks.
+ * @return List of plugin names.
+ */
+QStringList GStreamerPlayer::getPluginList( const QCString& classname )
+{
+ GList * pool_registries = NULL;
+ GList* registries = NULL;
+ GList* plugins = NULL;
+ GList* features = NULL;
+ QString name;
+ QStringList results;
+
+ if(!m_initialized) {
+ int argc = kapp->argc();
+ char **argv = kapp->argv();
+ gst_init(&argc, &argv);
+ m_initialized = true;
+ }
+
+ pool_registries = gst_registry_pool_list ();
+ registries = pool_registries;
+
+ while ( registries ) {
+ GstRegistry * registry = GST_REGISTRY ( registries->data );
+ plugins = registry->plugins;
+
+ while ( plugins ) {
+ GstPlugin * plugin = GST_PLUGIN ( plugins->data );
+ features = gst_plugin_get_feature_list ( plugin );
+
+ while ( features ) {
+ GstPluginFeature * feature = GST_PLUGIN_FEATURE ( features->data );
+
+ if ( GST_IS_ELEMENT_FACTORY ( feature ) ) {
+ GstElementFactory * factory = GST_ELEMENT_FACTORY ( feature );
+
+ if ( g_strrstr ( factory->details.klass, classname ) ) {
+ name = g_strdup ( GST_OBJECT_NAME ( factory ) );
+ if ( name != "artsdsink" ) results << name;
+ }
+ }
+ features = g_list_next ( features );
+ }
+ plugins = g_list_next ( plugins );
+ }
+ registries = g_list_next ( registries );
+ }
+ g_list_free ( pool_registries );
+ pool_registries = NULL;
+
+ return results;
+}
+
+bool GStreamerPlayer::requireVersion(uint major, uint minor, uint micro)
+{
+ guint gmajor, gminor, gmicro;
+
+ if(!m_initialized) {
+ int argc = kapp->argc();
+ char **argv = kapp->argv();
+ gst_init(&argc, &argv);
+ m_initialized = true;
+ }
+
+ gst_version(&gmajor, &gminor, &gmicro);
+ // kdDebug() << QString("GStreamerPlayer::requireVersion: You have gstreamer %1.%2.%3 installed.").arg(gmajor).arg(gminor).arg(gmicro) << endl;
+ if (gmajor > major) return true;
+ if (gminor > minor) return true;
+ if (gmicro >= micro) return true;
+ kdDebug() << QString("GStreamerPlayer::requireVersion: You have gstreamer %1.%2.%3 installed.").arg(gmajor).arg(gminor).arg(gmicro) << endl;
+ kdDebug() << QString("GStreamerPlayer::requireVersion: This application requires %1.%2.%3 or greater.").arg(major).arg(minor).arg(micro) << endl;
+ return false;
+}
+
+void GStreamerPlayer::setSinkName(const QString &sinkName) { m_sinkName = sinkName; }
+
+////////////////////////////////////////////////////////////////////////////////
+// private methods
+////////////////////////////////////////////////////////////////////////////////
+
+void GStreamerPlayer::readConfig()
+{
+ KConfigGroup config(KGlobal::config(), "GStreamerPlayer");
+ m_sinkName = config.readEntry("SinkName", QString::null);
+}
+
+void GStreamerPlayer::setupPipeline()
+{
+ if(!m_initialized) {
+ int argc = kapp->argc();
+ char **argv = kapp->argv();
+ gst_init(&argc, &argv);
+ m_initialized = true;
+ }
+
+ m_pipeline = gst_thread_new("pipeline");
+ m_source = gst_element_factory_make("filesrc", "source");
+ m_decoder = gst_element_factory_make("spider", "decoder");
+ m_volume = gst_element_factory_make("volume", "volume");
+
+ if(!m_sinkName.isNull())
+ m_sink = gst_element_factory_make(m_sinkName.utf8().data(), "sink");
+ if (!m_sink)
+ {
+ // m_sink = gst_element_factory_make("alsasink", "sink");
+ // if(!m_sink)
+ // m_sink = gst_element_factory_make("osssink", "sink");
+
+ // Reversing order. OSS seems to work. Alsa sink produces ugly echo of last
+ // couple of words in each wav file. argh!
+ // kdDebug() << "GStreamerPlayer::setupPipeline: trying oss sink." << endl;
+ m_sink = gst_element_factory_make("osssink", "sink");
+ if(!m_sink)
+ {
+ // kdDebug() << "GStreamerPlayer::setupPipeline: reverting to alsa sink." << endl;
+ m_sink = gst_element_factory_make("alsasink", "sink");
+ }
+ }
+
+ gst_bin_add_many(GST_BIN(m_pipeline), m_source, m_decoder, m_volume, m_sink, 0);
+ gst_element_link_many(m_source, m_decoder, m_volume, m_sink, 0);
+}
+
+long long GStreamerPlayer::time(GstQueryType type) const
+{
+ gint64 ns = 0;
+ GstFormat format = GST_FORMAT_TIME;
+ gst_element_query(m_sink, type, &format, &ns);
+ return ns;
+}
+
+// vim: set et sw=4:
diff --git a/kttsd/players/gstplayer/gstreamerplayer.h b/kttsd/players/gstplayer/gstreamerplayer.h
new file mode 100644
index 0000000..6a7f1d6
--- /dev/null
+++ b/kttsd/players/gstplayer/gstreamerplayer.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ copyright : (C) 2004 Scott Wheeler
+ email : wheeler@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef GSTREAMERPLAYER_H
+#define GSTREAMERPLAYER_H
+
+#include "config.h"
+
+#include <glib.h>
+extern "C" {
+#include <gst/gstversion.h>
+}
+#include <gst/gst.h>
+#include <qstring.h>
+#include "player.h"
+
+class GStreamerPlayer : public Player
+{
+ Q_OBJECT
+
+public:
+ GStreamerPlayer(QObject* parent = 0, const char* name = 0, const QStringList& args=QStringList());
+ virtual ~GStreamerPlayer();
+
+ // virtual void play(const FileHandle &file = FileHandle::null());
+ virtual void startPlay(const QString& file);
+
+ virtual void setVolume(float volume = 1.0);
+ virtual float volume() const;
+
+ virtual bool playing() const;
+ virtual bool paused() const;
+
+ virtual int totalTime() const;
+ virtual int currentTime() const;
+ virtual int position() const; // in this case not really the percent
+
+ virtual void seek(int seekTime);
+ virtual void seekPosition(int position);
+
+ virtual QStringList getPluginList( const QCString& classname );
+ virtual void setSinkName(const QString &sinkName);
+
+ virtual bool requireVersion(uint major, uint minor, uint micro);
+
+ void pause();
+ void stop();
+
+private:
+ void readConfig();
+ void setupPipeline();
+ long long time(GstQueryType type) const;
+
+ QString m_sinkName;
+ // True once gst_init() has been called.
+ bool m_initialized;
+
+ GstElement *m_pipeline;
+ GstElement *m_source;
+ GstElement *m_decoder;
+ GstElement *m_volume;
+ GstElement *m_sink;
+};
+
+#endif
diff --git a/kttsd/players/gstplayer/kttsd_gstplugin.desktop b/kttsd/players/gstplayer/kttsd_gstplugin.desktop
new file mode 100644
index 0000000..7646cee
--- /dev/null
+++ b/kttsd/players/gstplayer/kttsd_gstplugin.desktop
@@ -0,0 +1,92 @@
+[Desktop Entry]
+Name=KTTSD GStreamer Plugin
+Name[br]=Lugent KTTSD GStreamer
+Name[bs]=KTTSD GStreamer dodatak
+Name[ca]=Connector GStreamer pel KTTSD
+Name[cs]=KTTSD GStreamer modul
+Name[da]=KTTSD GStreamer-plugin
+Name[de]=KTTSD GStreamer-Modul
+Name[el]=KTTSD πρόσθετο GStreamer
+Name[es]=Complemento KTTSD GStreamer
+Name[et]=KTTSD GStreameri plugin
+Name[eu]=KTTSD-ren GStreamer plugina
+Name[fa]=وصلۀ KTTSD GStreamer
+Name[fi]=KTTSD GStreamer-liitännäinen
+Name[fr]=Module GStreamer pour KTTSD
+Name[ga]=Breiseán KTTSD GStreamer
+Name[gl]=Plugin GStreamer de KTTSD
+Name[hu]=KTTSD GStreamer-modul
+Name[is]=KTTSD GStreamer íforrit
+Name[it]=Plugin per GStreamer di KTTSD
+Name[ja]=KTTSD GStreamer プラグイン
+Name[ka]=KTTSD GStreamer მოდული
+Name[km]= កម្មវិធី​ជំនួយ GStreamer សម្រាប់ KTTSD
+Name[mk]=GStreamer-приклучок за KTTSD
+Name[ms]=Plugin KTTSD GStreamer
+Name[nb]=GStreamer programtillegg for KTTSD
+Name[nds]=GStreamer-Moduul för KTTSD
+Name[ne]=KTTSD जि स्ट्रिमर प्लगइन
+Name[nl]=KTTSD GStreamer-plugin
+Name[pa]=KTTSD ਜੀਸਟਰੀਮਰ ਪਲੱਗਿੰਨ
+Name[pl]=Wtyczka GStreamer KTTSD
+Name[pt]='Plugin' GStreamer do KTTSD
+Name[pt_BR]=Plug-in do GStreamer para o KTTSD
+Name[ru]=Модуль GStreamer для KTTSD
+Name[sk]=Modul KTTSD GStreamer
+Name[sl]=Vstavek KTTSD za GStreamer
+Name[sr]=GStreamer као прикључак за KTTSD
+Name[sr@Latn]=GStreamer kao priključak za KTTSD
+Name[sv]=KTTSD-insticksprogram för Gstreamer
+Name[ta]=KTTSD GStreamer சொருகுப்பொருள்
+Name[tg]=Модули GStreamer барои KTTSD
+Name[tr]=KTTSD GStreamer Eklentisi
+Name[uk]=Втулок GStreamer для KTTSD
+Name[vi]=Trình bổ sung KTTSD GStreamer
+Name[zh_TW]=KTTSd GStreamer 外掛程式
+Comment=KTTSD GStreamer audio plugin
+Comment[bg]=Аудио приставка на KTTSD за GStreamer
+Comment[br]=Lugent klevet GStreamer evit KTTSD
+Comment[ca]=Connector d'àudio GStreamer pel KTTSD
+Comment[cs]=KTTSD GStreamer zvukový modul
+Comment[da]=KTTSD GStreamer lyd-plugin
+Comment[de]=KTTSD GStreamer Audio-Modul
+Comment[el]=KTTSD πρόσθετο ήχου GStreamer
+Comment[es]=Complemento de audio KTTSD GStreamer
+Comment[et]=KTTSD GStreameri audioplugin
+Comment[eu]=KTTSD-ren GStreamer audio-plugina
+Comment[fa]=وصلۀ صوتی KTTSD GStreamer
+Comment[fi]=KTTSD GStreamer ääniliitännäinen
+Comment[fr]=Module audio GStreamer pour KTTSD
+Comment[ga]=Breiseán fuaime GStreamer KTTSD
+Comment[gl]=Plugin de áudio GStreamer para KTTSD
+Comment[hu]=KTTSD hangmodul a GStreamerhez
+Comment[is]=KTTSD GStreamer hljóð íforrit
+Comment[it]=Plugin audio per GStreamer di KTTSD
+Comment[ja]=KTTSD GStreamer オーディオプラグイン
+Comment[ka]=KTTSD GStreamer აუდიო მოდული
+Comment[km]=កម្មវិធី​ជំនួយអូឌីយ៉ូ​ GStreamer សម្រាប់ KTTSD
+Comment[mk]=GStreamer-аудиоприклучок за KTTSD
+Comment[ms]=Plugin audio KTTSD GStreamer
+Comment[nb]=GStreamer lyd-programtillegg for KTTSD
+Comment[nds]=GStreamer-Audiomoduul för KTTSD
+Comment[ne]=KTTSD जि स्ट्रिमर अडियो प्लगइन
+Comment[nl]=KTTSD GStreamer-audioplugin
+Comment[pa]=KTTSD ਜੀਸਟਰੀਮਰ ਆਡੀਓ ਪਲੱਗਿੰਨ
+Comment[pl]=Wtyczka dźwięku GStreamer dla KTTSD
+Comment[pt]='Plugin' áudio GStreamer do KTTSD
+Comment[pt_BR]=Plug-in de áudio do GStreamer para o KTTSD
+Comment[ru]=Модуль вывода звука KTTSD через GStreamer
+Comment[sk]=Modul KTTSD GStreamer audio
+Comment[sl]=Vstavek KTTSD za zvok v GStreamer
+Comment[sr]=GStreamer као аудио прикључак за KTTSD
+Comment[sr@Latn]=GStreamer kao audio priključak za KTTSD
+Comment[sv]=KTTSD-ljudinsticksprogram för Gstreamer
+Comment[ta]=KTTSD GStreamer கேட்பொலி சொருகுப்பொருள்
+Comment[tg]=Модули барориши овози KTTSD ба воситаи GStreamer
+Comment[tr]= KTTSD GStreamer ses eklentisi
+Comment[uk]=Звуковий втулок GStreamer для KTTSD
+Comment[vi]=Trình bổ sung âm thanh KTTSD GStreamer
+Comment[zh_TW]=KTTSd GStreamer 語音外掛程式
+Type=Service
+ServiceTypes=KTTSD/AudioPlugin
+X-KDE-Library=libkttsd_gstplugin
diff --git a/kttsd/players/kttsd_audioplugin.desktop b/kttsd/players/kttsd_audioplugin.desktop
new file mode 100644
index 0000000..ae39e7c
--- /dev/null
+++ b/kttsd/players/kttsd_audioplugin.desktop
@@ -0,0 +1,47 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KTTSD/AudioPlugin
+Comment=Audio Plugin for KTTSD
+Comment[bg]=Аудио приставка на KTTSD
+Comment[br]=Lugent klevet evit KTTSD
+Comment[ca]=Connector d'àudio pel KTTSD
+Comment[cs]=Zvukový modul KTTSD
+Comment[da]=Lyd-plugin for KTTSD
+Comment[de]=Audio-Modul für KTTSD
+Comment[el]=Πρόσθετο ήχου για το KTTSD
+Comment[es]=Complemento de audio para KTTSD
+Comment[et]=KTTSD audioplugin
+Comment[eu]=KTTSD-ren audio plugnka
+Comment[fa]=وصلۀ صوتی برای KTTSD
+Comment[fi]=Ääniliitännäinen KTTSD-ohjelmalle
+Comment[fr]=Module audio pour KTTSD
+Comment[ga]=Breiseán fuaime KTTSD
+Comment[gl]=Plugin de Áudio para KTTSD
+Comment[hu]=Hangmodul a KTTSD szolgáltatáshoz
+Comment[is]=Hljóð íforrit fyrir KTTSD
+Comment[it]=Plugin audio per KTTSD
+Comment[ja]=KTTSD 用オーディオプラグイン
+Comment[ka]=აუდიო მოდული KTTSD-თვის
+Comment[km]=​កម្មវិធី​ជំនួយ​អូឌីយ៉ូ​សម្រាប់​ KTTSD
+Comment[mk]=Аудиоприклучок за KTTSD
+Comment[ms]=Plugin Audio bagi KTTSD
+Comment[nb]=Lyd-programtillegg for KTTSD
+Comment[nds]=Audiomoduul för KTTSD
+Comment[ne]=KTTSD का लागि अडियो प्लगइन
+Comment[nl]=Audio-plugin voor KTTSD
+Comment[pa]=KTTSD ਲਈ ਆਡੀਓ ਪਲੱਗਿੰਨ
+Comment[pl]=Wtyczka dźwięku dla KTTSD
+Comment[pt]='Plugin' Áudio para o KTTSD
+Comment[pt_BR]=Plug-in de áudio para o KTTSD
+Comment[ru]=Модуль вывода звука KTTSD
+Comment[sk]=Audio modul pre KTTSD
+Comment[sl]=Vstavek KTTSD za zvok
+Comment[sr]=Аудио прикључак за KTTSD
+Comment[sr@Latn]=Audio priključak za KTTSD
+Comment[sv]=Ljudinsticksprogram för KTTSD
+Comment[ta]= KTTSDக்கான கேட்பொலி சொருகுப்பொருள்
+Comment[tg]=Модули барориши овози KTTSD
+Comment[tr]=KTTS için Ses Eklentisi
+Comment[uk]=Звуковий втулок для KTTSD
+Comment[vi]=Trình bổ sung Âm thanh cho KTTSD
+Comment[zh_TW]=KTTSd 語音外掛程式
diff --git a/kttsd/plugins/Makefile.am b/kttsd/plugins/Makefile.am
new file mode 100644
index 0000000..7bf657e
--- /dev/null
+++ b/kttsd/plugins/Makefile.am
@@ -0,0 +1,37 @@
+#kdevelop: festivalint_DIR = festivalint
+if include_kttsd_festivalint
+ festivalint_DIR = festivalint
+endif
+
+#kdevelop: freetts_DIR = freetts
+if include_kttsd_freetts
+ freetts_DIR = freetts
+endif
+
+#kdevelop: command_DIR = command
+if include_kttsd_command
+ command_DIR = command
+endif
+
+#kdevelop: hadifix_DIR = hadifix
+if include_kttsd_hadifix
+ hadifix_DIR = hadifix
+endif
+
+#kdevelop: flite_DIR = flite
+if include_kttsd_flite
+ flite_DIR = flite
+endif
+
+#kdevelop: epos_DIR = epos
+if include_kttsd_epos
+ epos_DIR = epos
+endif
+
+SUBDIRS = \
+ $(festivalint_DIR) \
+ $(freetts_DIR) \
+ $(command_DIR) \
+ $(hadifix_DIR) \
+ $(flite_DIR) \
+ $(epos_DIR)
diff --git a/kttsd/plugins/command/Makefile.am b/kttsd/plugins/command/Makefile.am
new file mode 100644
index 0000000..b180955
--- /dev/null
+++ b/kttsd/plugins/command/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_commandplugin.la
+
+libkttsd_commandplugin_la_SOURCES = \
+ commandconfwidget.ui \
+ commandconf.cpp \
+ commandproc.cpp \
+ commandplugin.cpp
+libkttsd_commandplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_commandplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_commandplugin.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/kttsd/plugins/command/README b/kttsd/plugins/command/README
new file mode 100644
index 0000000..55839ae
--- /dev/null
+++ b/kttsd/plugins/command/README
@@ -0,0 +1,8 @@
+This is the directory containing the Command plug in.
+This plug in is developed and maintained by Gunnar Schmi Dt.
+-- This is no longer necesary for this plug in --
+If you intend to edit the GUI (commandconfwidget.ui) you will have to first
+copy kttsd/libkttsd/pluginconf.h to a standard include directory
+like $KDEDIR/include/ since the interface has been tweaked to derive
+from PlugInConf instead of QWidget and Qt Designer refuses to open it
+if the header is not properly placed.
diff --git a/kttsd/plugins/command/commandconf.cpp b/kttsd/plugins/command/commandconf.cpp
new file mode 100644
index 0000000..9d70ff2
--- /dev/null
+++ b/kttsd/plugins/command/commandconf.cpp
@@ -0,0 +1,217 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Configuration for the Command Plug in
+ -------------------
+ Copyright : (C) 2002,2004 by Gunnar Schmi Dt and Gary Cramblitt
+ -------------------
+ Original author: Gunnar Schmi Dt <kmouth@schmi-dt.de>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qfile.h>
+#include <qapplication.h>
+#include <qtextcodec.h>
+
+// KDE includes.
+#include <kdialog.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kcombobox.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+
+// KTTS includes.
+#include <pluginconf.h>
+#include <testplayer.h>
+
+// Command Plugin includes.
+#include "commandproc.h"
+#include "commandconf.h"
+
+/** Constructor */
+CommandConf::CommandConf( QWidget* parent, const char* name, const QStringList& /*args*/) :
+ PlugInConf(parent, name)
+{
+ // kdDebug() << "CommandConf::CommandConf: Running" << endl;
+ m_commandProc = 0;
+ m_progressDlg = 0;
+
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "CommandConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new CommandConfWidget(this, "CommandConfigWidget");
+ layout->addWidget(m_widget);
+
+ // Build codec list and fill combobox.
+ m_codecList = PlugInProc::buildCodecList();
+ m_widget->characterCodingBox->clear();
+ m_widget->characterCodingBox->insertStringList(m_codecList);
+
+ defaults();
+ connect(m_widget->characterCodingBox, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->characterCodingBox, SIGNAL(activated(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->stdInButton, SIGNAL(toggled(bool)),
+ this, SLOT(configChanged()));
+ connect(m_widget->urlReq, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->commandTestButton, SIGNAL(clicked()),
+ this, SLOT(slotCommandTest_clicked()));
+}
+
+/** Destructor */
+CommandConf::~CommandConf()
+{
+ // kdDebug() << "CommandConf::~CommandConf: Running" << endl;
+ if (!m_waveFile.isNull()) QFile::remove(m_waveFile);
+ delete m_commandProc;
+ delete m_progressDlg;
+}
+
+void CommandConf::load(KConfig *config, const QString &configGroup) {
+ // kdDebug() << "CommandConf::load: Running" << endl;
+ config->setGroup(configGroup);
+ m_widget->urlReq->setURL (config->readEntry("Command", "cat -"));
+ m_widget->stdInButton->setChecked(config->readBoolEntry("StdIn", false));
+ QString codecString = config->readEntry("Codec", "Local");
+ m_languageCode = config->readEntry("LanguageCode", m_languageCode);
+ int codec = PlugInProc::codecNameToListIndex(codecString, m_codecList);
+ m_widget->characterCodingBox->setCurrentItem(codec);
+}
+
+void CommandConf::save(KConfig *config, const QString &configGroup) {
+ // kdDebug() << "CommandConf::save: Running" << endl;
+ config->setGroup(configGroup);
+ config->writeEntry("Command", m_widget->urlReq->url());
+ config->writeEntry("StdIn", m_widget->stdInButton->isChecked());
+ int codec = m_widget->characterCodingBox->currentItem();
+ config->writeEntry("Codec", PlugInProc::codecIndexToCodecName(codec, m_codecList));
+}
+
+void CommandConf::defaults(){
+ // kdDebug() << "CommandConf::defaults: Running" << endl;
+ m_widget->urlReq->setURL("cat -");
+ m_widget->stdInButton->setChecked(false);
+ m_widget->urlReq->setShowLocalProtocol (false);
+ m_widget->characterCodingBox->setCurrentItem(0);
+}
+
+void CommandConf::setDesiredLanguage(const QString &lang)
+{
+ m_languageCode = lang;
+}
+
+QString CommandConf::getTalkerCode()
+{
+ QString url = m_widget->urlReq->url();
+ if (!url.isEmpty())
+ {
+ // Must contain either text or file parameter, or StdIn checkbox must be checked,
+ // otherwise, does nothing!
+ if ((url.contains("%t") > 0) || (url.contains("%f") > 0) || m_widget->stdInButton->isChecked())
+ {
+ return QString(
+ "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />"
+ "<prosody volume=\"%4\" rate=\"%5\" />"
+ "<kttsd synthesizer=\"%6\" />")
+ .arg(m_languageCode)
+ .arg("fixed")
+ .arg("neutral")
+ .arg("medium")
+ .arg("medium")
+ .arg("Command");
+ }
+ }
+ return QString::null;
+}
+
+void CommandConf::slotCommandTest_clicked()
+{
+ // kdDebug() << "CommandConf::slotCommandTest_clicked(): " << endl;
+ // If currently synthesizing, stop it.
+ if (m_commandProc)
+ m_commandProc->stopText();
+ else
+ {
+ m_commandProc = new CommandProc();
+ connect (m_commandProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
+ }
+
+ // Create a temp file name for the wave file.
+ KTempFile tempFile (locateLocal("tmp", "commandplugin-"), ".wav");
+ QString tmpWaveFile = tempFile.file()->name();
+ tempFile.close();
+
+ // Get test message in the language of the voice.
+ QString testMsg = testMessage(m_languageCode);
+
+ // Tell user to wait.
+ m_progressDlg = new KProgressDialog(m_widget, "kttsmgr_command_testdlg",
+ i18n("Testing"),
+ i18n("Testing."),
+ true);
+ m_progressDlg->progressBar()->hide();
+ m_progressDlg->setAllowCancel(true);
+
+ // TODO: Do codec names contain non-ASCII characters?
+ connect (m_commandProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ m_commandProc->synth(
+ testMsg,
+ tmpWaveFile,
+ m_widget->urlReq->url(),
+ m_widget->stdInButton->isChecked(),
+ PlugInProc::codecIndexToCodec(m_widget->characterCodingBox->currentItem(), m_codecList),
+ m_languageCode);
+
+ // Display progress dialog modally. Processing continues when plugin signals synthFinished,
+ // or if user clicks Cancel button.
+ m_progressDlg->exec();
+ disconnect (m_commandProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ if (m_progressDlg->wasCancelled()) m_commandProc->stopText();
+ delete m_progressDlg;
+ m_progressDlg = 0;
+}
+
+void CommandConf::slotSynthFinished()
+{
+ // If user canceled, progress dialog is gone, so exit.
+ if (!m_progressDlg)
+ {
+ m_commandProc->ackFinished();
+ return;
+ }
+ // Hide the Cancel button so user can't cancel in the middle of playback.
+ m_progressDlg->showCancelButton(false);
+ // Get new wavefile name.
+ m_waveFile = m_commandProc->getFilename();
+ // Tell synth we're done.
+ m_commandProc->ackFinished();
+ // Play the wave file (possibly adjusting its Speed).
+ // Player object deletes the wave file when done.
+ if (m_player) m_player->play(m_waveFile);
+ QFile::remove(m_waveFile);
+ m_waveFile = QString::null;
+ if (m_progressDlg) m_progressDlg->close();
+}
+
+void CommandConf::slotSynthStopped()
+{
+ // Clean up after canceling test.
+ QString filename = m_commandProc->getFilename();
+ if (!filename.isNull()) QFile::remove(filename);
+}
+
+#include "commandconf.moc"
diff --git a/kttsd/plugins/command/commandconf.h b/kttsd/plugins/command/commandconf.h
new file mode 100644
index 0000000..7e9a573
--- /dev/null
+++ b/kttsd/plugins/command/commandconf.h
@@ -0,0 +1,121 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Configuration for the Command Plug in
+ -------------------
+ Copyright : (C) 2002,2004 by Gunnar Schmi Dt and Gary Cramblitt
+ -------------------
+ Original author: Gunnar Schmi Dt <kmouth@schmi-dt.de>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _COMMANDCONF_H_
+#define _COMMANDCONF_H_
+
+// Qt includes.
+#include <qstring.h>
+#include <qstringlist.h>
+
+// KDE includes.
+#include <kconfig.h>
+
+// KTTS includes.
+#include <pluginconf.h>
+
+// Command Plugin includes.
+#include "commandconfwidget.h"
+
+class CommandProc;
+class KProgressDialog;
+
+class CommandConf : public PlugInConf {
+ Q_OBJECT
+
+ public:
+ /** Constructor */
+ CommandConf( QWidget* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /** Destructor */
+ ~CommandConf();
+
+ /** This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. NOTE that this is not called after the modules is loaded,
+ * so you probably want to call this method in the constructor.
+ */
+ void load(KConfig *config, const QString &configGroup);
+
+ /** This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok".
+ */
+ void save(KConfig *config, const QString &configGroup);
+
+ /** This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file.
+ */
+ void defaults();
+
+ /**
+ * This function informs the plugin of the desired language to be spoken
+ * by the plugin. The plugin should attempt to adapt itself to the
+ * specified language code, choosing sensible defaults if necessary.
+ * If the passed-in code is QString::null, no specific language has
+ * been chosen.
+ * @param lang The desired language code or Null if none.
+ *
+ * If the plugin is unable to support the desired language, that is OK.
+ * Language codes are given by ISO 639-1 and are in lowercase.
+ * The code may also include an ISO 3166 country code in uppercase
+ * separated from the language code by underscore (_). For
+ * example, en_GB. If your plugin supports the given language, but
+ * not the given country, treat it as though the country
+ * code were not specified, i.e., adapt to the given language.
+ */
+ void setDesiredLanguage(const QString &lang);
+
+ /**
+ * Return fully-specified talker code for the configured plugin. This code
+ * uniquely identifies the configured instance of the plugin and distinquishes
+ * one instance from another. If the plugin has not been fully configured,
+ * i.e., cannot yet synthesize, return QString::null.
+ * @return Fully-specified talker code.
+ */
+ QString getTalkerCode();
+
+ private slots:
+ void configChanged(){
+ // kdDebug() << "CommandConf::configChanged: Running" << endl;
+ emit changed(true);
+ };
+ void slotCommandTest_clicked();
+ void slotSynthFinished();
+ void slotSynthStopped();
+
+ private:
+ QString m_languageCode;
+
+ // Configuration Widget.
+ CommandConfWidget* m_widget;
+
+ // Command synthesizer.
+ CommandProc* m_commandProc;
+ // Synthesized wave file name.
+ QString m_waveFile;
+ // Progress dialog.
+ KProgressDialog* m_progressDlg;
+ // Codec list.
+ QStringList m_codecList;
+};
+#endif // _COMMANDCONF_H_
diff --git a/kttsd/plugins/command/commandconfwidget.ui b/kttsd/plugins/command/commandconfwidget.ui
new file mode 100644
index 0000000..b0b749c
--- /dev/null
+++ b/kttsd/plugins/command/commandconfwidget.ui
@@ -0,0 +1,227 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>CommandConfWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>CommandConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>582</width>
+ <height>322</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>confiurationBox</cstring>
+ </property>
+ <property name="title">
+ <string>Co&amp;mmand Configuration</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="Line" row="1" column="0">
+ <property name="name">
+ <cstring>line</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>urlLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Command &amp;for speaking texts:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>urlReq</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="3" column="0">
+ <property name="name">
+ <cstring>urlReq</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This field specifies both the command used for speaking texts and its parameters. If you want to pass the text as a parameter, write %t at the place where the text should be inserted. To pass a file of the text, write %f. To synthesize only and let KTTSD play the synthesized text, write %w for the generated audio file.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="5" column="0">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>stdInButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Send the data as standard input</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This check box specifies whether the text is sent as standard input (stdin) to the speech synthesizer.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>201</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>commandTestButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Test</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="4" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>characterCodingLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Character &amp;encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies which character encoding is used for passing the text.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>explanationLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Parameters:
+ %t: Text to be spoken
+ %f: Filename of a temporary file containing the text
+ %l: Language (two letter code)
+ %w: Filename of a temporary file for generated audio</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>urlReq</tabstop>
+ <tabstop>characterCodingBox</tabstop>
+ <tabstop>stdInButton</tabstop>
+ <tabstop>commandTestButton</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">kurlrequester.h</include>
+ <include location="global" impldecl="in declaration">klineedit.h</include>
+ <include location="global" impldecl="in declaration">kpushbutton.h</include>
+ <include location="global" impldecl="in declaration">kcombobox.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+ <include location="global" impldecl="in implementation">kcombobox.h</include>
+</includes>
+<signals>
+ <signal>configurationChanged()</signal>
+</signals>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/plugins/command/commandplugin.cpp b/kttsd/plugins/command/commandplugin.cpp
new file mode 100644
index 0000000..119ca47
--- /dev/null
+++ b/kttsd/plugins/command/commandplugin.cpp
@@ -0,0 +1,24 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ -------------------
+ Copyright : (C) 2002 by Gunnar Schmi Dt and 2004 by Gary Cramblitt
+ -------------------
+ Original author: Gunnar Schmi Dt <kmouth@schmi-dt.de>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "commandconf.h"
+#include "commandproc.h"
+
+typedef K_TYPELIST_2( CommandProc, CommandConf ) Command;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_commandplugin, KGenericFactory<Command>("kttsd_command") )
+
diff --git a/kttsd/plugins/command/commandproc.cpp b/kttsd/plugins/command/commandproc.cpp
new file mode 100644
index 0000000..e8d3e72
--- /dev/null
+++ b/kttsd/plugins/command/commandproc.cpp
@@ -0,0 +1,446 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Main speaking functions for the Command Plug in
+ -------------------
+ Copyright : (C) 2002 by Gunnar Schmi Dt and 2004 by Gary Cramblitt
+ -------------------
+ Original author: Gunnar Schmi Dt <kmouth@schmi-dt.de>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qfile.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qtextcodec.h>
+#include <qvaluestack.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kprocess.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+
+// KTTS includes.
+#include <pluginproc.h>
+
+// Command Plugin includes.
+#include "commandproc.h"
+#include "commandproc.moc"
+
+/** Constructor */
+CommandProc::CommandProc( QObject* parent, const char* name, const QStringList& /*args*/) :
+ PlugInProc( parent, name )
+{
+ kdDebug() << "CommandProc::CommandProc: Running" << endl;
+ m_commandProc = 0;
+ m_state = psIdle;
+ m_stdin = true;
+ m_supportsSynth = false;
+ m_waitingStop = false;
+}
+
+/** Destructor */
+CommandProc::~CommandProc()
+{
+ kdDebug() << "CommandProc::~CommandProc: Running" << endl;
+ if (m_commandProc)
+ {
+ if (m_commandProc->isRunning()) m_commandProc->kill();
+ delete m_commandProc;
+ // Don't delete synth file. That is responsibility of caller.
+ if (!m_textFilename.isNull()) QFile::remove(m_textFilename);
+ }
+}
+
+/** Initialize */
+bool CommandProc::init(KConfig *config, const QString &configGroup){
+ kdDebug() << "CommandProc::init: Initializing plug in: Command " << endl;
+
+ config->setGroup(configGroup);
+ m_ttsCommand = config->readEntry("Command", "cat -");
+ m_stdin = config->readBoolEntry("StdIn", true);
+ m_language = config->readEntry("LanguageCode", "en");
+
+ // Support separate synthesis if the TTS command contains %w macro.
+ m_supportsSynth = (m_ttsCommand.contains("%w"));
+
+ QString codecString = config->readEntry("Codec", "Local");
+ m_codec = codecNameToCodec(codecString);
+ kdDebug() << "CommandProc::init: Initialized with command: " << m_ttsCommand << " codec: " << codecString << endl;
+ return true;
+}
+
+/**
+* Say a text. Synthesize and audibilize it.
+* @param text The text to be spoken.
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void CommandProc::sayText(const QString &text)
+{
+ synth(text, QString::null,
+ m_ttsCommand, m_stdin, m_codec, m_language);
+}
+
+/**
+* Synthesize text into an audio file, but do not send to the audio device.
+* @param text The text to be synthesized.
+* @param suggestedFilename Full pathname of file to create. The plugin
+* may ignore this parameter and choose its own
+* filename. KTTSD will query the generated
+* filename using getFilename().
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void CommandProc::synthText(const QString& text, const QString& suggestedFilename)
+{
+ synth(text, suggestedFilename,
+ m_ttsCommand, m_stdin, m_codec, m_language);
+}
+
+/**
+* Say or Synthesize text.
+* @param inputText The text that shall be spoken
+* @param suggestedFilename If not Null, synthesize only to this filename, otherwise
+* synthesize and audibilize the text.
+* @param userCmd The program that shall be executed for speaking
+* @param stdIn True if the program shall recieve its data via standard input
+* @param codec The QTextCodec if encoding==UseCodec
+* @param language The language code (used for the %l macro)
+*/
+void CommandProc::synth(const QString& inputText, const QString& suggestedFilename,
+ const QString& userCmd, bool stdIn, QTextCodec *codec, QString& language)
+{
+ if (m_commandProc)
+ {
+ if (m_commandProc->isRunning()) m_commandProc->kill();
+ delete m_commandProc;
+ m_commandProc = 0;
+ m_synthFilename = QString::null;
+ if (!m_textFilename.isNull()) QFile::remove(m_textFilename);
+ m_textFilename = QString::null;
+ }
+ QString command = userCmd;
+ QString text = inputText.stripWhiteSpace();
+ if (text.isEmpty()) return;
+ // 1. prepare the text:
+ // 1.a) encode the text
+ text += "\n";
+ QCString encodedText;
+ if (codec)
+ encodedText = codec->fromUnicode(text);
+ else
+ encodedText = text.latin1(); // Should not happen, but just in case.
+
+ // 1.b) quote the text as one parameter
+ QString escText = KShellProcess::quote(text);
+
+ // 1.c) create a temporary file for the text, if %f macro is used.
+ if (command.contains("%f"))
+ {
+ KTempFile tempFile(locateLocal("tmp", "commandplugin-"), ".txt");
+ QTextStream* fs = tempFile.textStream();
+ fs->setCodec(codec);
+ *fs << text;
+ *fs << endl;
+ m_textFilename = tempFile.file()->name();
+ tempFile.close();
+ } else m_textFilename = QString::null;
+
+ // 2. replace variables with values
+ QValueStack<bool> stack;
+ bool issinglequote=false;
+ bool isdoublequote=false;
+ int noreplace=0;
+ QRegExp re_noquote("(\"|'|\\\\|`|\\$\\(|\\$\\{|\\(|\\{|\\)|\\}|%%|%t|%f|%l|%w)");
+ QRegExp re_singlequote("('|%%|%t|%f|%l|%w)");
+ QRegExp re_doublequote("(\"|\\\\|`|\\$\\(|\\$\\{|%%|%t|%f|%l|%w)");
+
+ for ( int i = re_noquote.search(command);
+ i != -1;
+ i = (issinglequote?re_singlequote.search(command,i)
+ :isdoublequote?re_doublequote.search(command,i)
+ :re_noquote.search(command,i))
+ )
+ {
+ if ((command[i]=='(') || (command[i]=='{')) // (...) or {...}
+ {
+ // assert(isdoublequote == false)
+ stack.push(isdoublequote);
+ if (noreplace > 0)
+ // count nested braces when within ${...}
+ noreplace++;
+ i++;
+ }
+ else if (command[i]=='$')
+ {
+ stack.push(isdoublequote);
+ isdoublequote = false;
+ if ((noreplace > 0) || (command[i+1]=='{'))
+ // count nested braces when within ${...}
+ noreplace++;
+ i+=2;
+ }
+ else if ((command[i]==')') || (command[i]=='}'))
+ // $(...) or (...) or ${...} or {...}
+ {
+ if (!stack.isEmpty())
+ isdoublequote = stack.pop();
+ else
+ qWarning("Parse error.");
+ if (noreplace > 0)
+ // count nested braces when within ${...}
+ noreplace--;
+ i++;
+ }
+ else if (command[i]=='\'')
+ {
+ issinglequote=!issinglequote;
+ i++;
+ }
+ else if (command[i]=='"')
+ {
+ isdoublequote=!isdoublequote;
+ i++;
+ }
+ else if (command[i]=='\\')
+ i+=2;
+ else if (command[i]=='`')
+ {
+ // Replace all `...` with safer $(...)
+ command.replace (i, 1, "$(");
+ QRegExp re_backticks("(`|\\\\`|\\\\\\\\|\\\\\\$)");
+ for ( int i2=re_backticks.search(command,i+2);
+ i2!=-1;
+ i2=re_backticks.search(command,i2)
+ )
+ {
+ if (command[i2] == '`')
+ {
+ command.replace (i2, 1, ")");
+ i2=command.length(); // leave loop
+ }
+ else
+ { // remove backslash and ignore following character
+ command.remove (i2, 1);
+ i2++;
+ }
+ }
+ // Leave i unchanged! We need to process "$("
+ }
+ else if (noreplace == 0) // do not replace macros within ${...}
+ {
+ QString match, v;
+
+ // get match
+ if (issinglequote)
+ match=re_singlequote.cap();
+ else if (isdoublequote)
+ match=re_doublequote.cap();
+ else
+ match=re_noquote.cap();
+
+ // substitue %variables
+ if (match=="%%")
+ v="%";
+ else if (match=="%t")
+ v=escText;
+ else if (match=="%f")
+ v=m_textFilename;
+ else if (match=="%l")
+ v=language;
+ else if (match=="%w")
+ v = suggestedFilename;
+
+ // %variable inside of a quote?
+ if (isdoublequote)
+ v='"'+v+'"';
+ else if (issinglequote)
+ v="'"+v+"'";
+
+ command.replace (i, match.length(), v);
+ i+=v.length();
+ }
+ else
+ {
+ if (issinglequote)
+ i+=re_singlequote.matchedLength();
+ else if (isdoublequote)
+ i+=re_doublequote.matchedLength();
+ else
+ i+=re_noquote.matchedLength();
+ }
+ }
+
+ // 3. create a new process
+ kdDebug() << "CommandProc::synth: running command: " << command << endl;
+ m_commandProc = new KProcess;
+ m_commandProc->setUseShell(true);
+ m_commandProc->setEnvironment("LANG", language + "." + codec->mimeName());
+ m_commandProc->setEnvironment("LC_CTYPE", language + "." + codec->mimeName());
+ *m_commandProc << command;
+ connect(m_commandProc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*)));
+ connect(m_commandProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStdout(KProcess*, char*, int)));
+ connect(m_commandProc, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStderr(KProcess*, char*, int)));
+ connect(m_commandProc, SIGNAL(wroteStdin(KProcess*)),
+ this, SLOT(slotWroteStdin(KProcess* )));
+
+ // 4. start the process
+
+ if (suggestedFilename.isNull())
+ m_state = psSaying;
+ else
+ {
+ m_synthFilename = suggestedFilename;
+ m_state = psSynthing;
+ }
+ if (stdIn) {
+ m_commandProc->start(KProcess::NotifyOnExit, KProcess::All);
+ if (encodedText.length() > 0)
+ m_commandProc->writeStdin(encodedText, encodedText.length());
+ else
+ m_commandProc->closeStdin();
+ }
+ else
+ m_commandProc->start(KProcess::NotifyOnExit, KProcess::AllOutput);
+}
+
+/**
+* Get the generated audio filename from synthText.
+* @return Name of the audio file the plugin generated.
+* Null if no such file.
+*
+* The plugin must not re-use the filename.
+*/
+QString CommandProc::getFilename()
+{
+ kdDebug() << "CommandProc::getFilename: returning " << m_synthFilename << endl;
+ return m_synthFilename;
+}
+
+/**
+* Stop current operation (saying or synthesizing text).
+* Important: This function may be called from a thread different from the
+* one that called sayText or synthText.
+* If the plugin cannot stop an in-progress @ref sayText or
+* @ref synthText operation, it must not block waiting for it to complete.
+* Instead, return immediately.
+*
+* If a plugin returns before the operation has actually been stopped,
+* the plugin must emit the @ref stopped signal when the operation has
+* actually stopped.
+*
+* The plugin should change to the psIdle state after stopping the
+* operation.
+*/
+void CommandProc::stopText(){
+ kdDebug() << "CommandProc::stopText: Running" << endl;
+ if (m_commandProc)
+ {
+ if (m_commandProc->isRunning())
+ {
+ kdDebug() << "CommandProc::stopText: killing Command." << endl;
+ m_waitingStop = true;
+ m_commandProc->kill();
+ } else m_state = psIdle;
+ }else m_state = psIdle;
+ kdDebug() << "CommandProc::stopText: Command stopped." << endl;
+}
+
+void CommandProc::slotProcessExited(KProcess*)
+{
+ kdDebug() << "CommandProc:slotProcessExited: Command process has exited." << endl;
+ pluginState prevState = m_state;
+ if (m_waitingStop)
+ {
+ m_waitingStop = false;
+ m_state = psIdle;
+ emit stopped();
+ } else {
+ m_state = psFinished;
+ if (prevState == psSaying)
+ emit sayFinished();
+ else
+ if (prevState == psSynthing)
+ emit synthFinished();
+ }
+}
+
+void CommandProc::slotReceivedStdout(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "CommandProc::slotReceivedStdout: Received output from Command: " << buf << endl;
+}
+
+void CommandProc::slotReceivedStderr(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "CommandProc::slotReceivedStderr: Received error from Command: " << buf << endl;
+}
+
+void CommandProc::slotWroteStdin(KProcess*)
+{
+ kdDebug() << "CommandProc::slotWroteStdin: closing Stdin" << endl;
+ m_commandProc->closeStdin();
+}
+
+/**
+* Return the current state of the plugin.
+* This function only makes sense in asynchronous mode.
+* @return The pluginState of the plugin.
+*
+* @see pluginState
+*/
+pluginState CommandProc::getState() { return m_state; }
+
+/**
+* Acknowledges a finished state and resets the plugin state to psIdle.
+*
+* If the plugin is not in state psFinished, nothing happens.
+* The plugin may use this call to do any post-processing cleanup,
+* for example, blanking the stored filename (but do not delete the file).
+* Calling program should call getFilename prior to ackFinished.
+*/
+void CommandProc::ackFinished()
+{
+ if (m_state == psFinished)
+ {
+ m_state = psIdle;
+ m_synthFilename = QString::null;
+ if (!m_textFilename.isNull()) QFile::remove(m_textFilename);
+ m_textFilename = QString::null;
+ }
+}
+
+/**
+* Returns True if the plugin supports asynchronous processing,
+* i.e., returns immediately from sayText or synthText.
+* @return True if this plugin supports asynchronous processing.
+*
+* If the plugin returns True, it must also implement @ref getState .
+* It must also emit @ref sayFinished or @ref synthFinished signals when
+* saying or synthesis is completed.
+*/
+bool CommandProc::supportsAsync() { return true; }
+
+/**
+* Returns True if the plugin supports synthText method,
+* i.e., is able to synthesize text to a sound file without
+* audibilizing the text.
+* @return True if this plugin supports synthText method.
+*/
+bool CommandProc::supportsSynth() { return m_supportsSynth; }
diff --git a/kttsd/plugins/command/commandproc.h b/kttsd/plugins/command/commandproc.h
new file mode 100644
index 0000000..4b46fe5
--- /dev/null
+++ b/kttsd/plugins/command/commandproc.h
@@ -0,0 +1,201 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Main speaking functions for the Command Plug in
+ -------------------
+ Copyright : (C) 2002 by Gunnar Schmi Dt and 2004 by Gary Cramblitt
+ -------------------
+ Original author: Gunnar Schmi Dt <kmouth@schmi-dt.de>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _COMMANDPROC_H_
+#define _COMMANDPROC_H_
+
+// Qt includes.
+#include <qstringlist.h>
+
+// KTTS includes.
+#include <pluginproc.h>
+
+class KProcess;
+class QTextCodec;
+
+class CommandProc : public PlugInProc{
+ Q_OBJECT
+
+ public:
+ /** Constructor */
+ CommandProc( QObject* parent = 0, const char* name = 0,
+ const QStringList &args = QStringList());
+
+ /** Destructor */
+ ~CommandProc();
+
+ /** Initializate the speech */
+ bool init (KConfig *config, const QString &configGroup);
+
+ /**
+ * Say a text string.
+ * @param text The text to speak.
+ */
+ virtual void sayText(const QString &text);
+
+ /**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately.
+ */
+ virtual void synthText(const QString& text, const QString& suggestedFilename);
+
+ /**
+ * Get the generated audio filename from synthText.
+ * @return Name of the audio file the plugin generated.
+ * Null if no such file.
+ *
+ * The plugin must not re-use the filename.
+ */
+ virtual QString getFilename();
+
+ /**
+ * Stop current operation (saying or synthesizing text).
+ * Important: This function may be called from a thread different from the
+ * one that called sayText or synthText.
+ * If the plugin cannot stop an in-progress @ref sayText or
+ * @ref synthText operation, it must not block waiting for it to complete.
+ * Instead, return immediately.
+ *
+ * If a plugin returns before the operation has actually been stopped,
+ * the plugin must emit the @ref stopped signal when the operation has
+ * actually stopped.
+ *
+ * The plugin should change to the psIdle state after stopping the
+ * operation.
+ */
+ virtual void stopText();
+
+ /**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @see pluginState
+ */
+ virtual pluginState getState();
+
+ /**
+ * Acknowledges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref sayFinished or @ref synthFinished signals when
+ * saying or synthesis is completed.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Returns True if the plugin supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ */
+ virtual bool supportsSynth();
+
+ /**
+ * Say or Synthesize text.
+ * @param inputText The text that shall be spoken
+ * @param suggestedFilename If not Null, synthesize only to this filename, otherwise
+ * synthesize and audibilize the text.
+ * @param userCmd The program that shall be executed for speaking
+ * @param stdIn True if the program shall recieve its data via
+ * standard input.
+ * @param codec Codec for encoding the text.
+ * @param language The language code (used for the %l macro)
+ */
+ void synth(const QString& inputText, const QString& suggestedFilename,
+ const QString& userCmd, bool stdIn,
+ QTextCodec *codec, QString& language);
+
+ private slots:
+ void slotProcessExited(KProcess* proc);
+ void slotReceivedStdout(KProcess* proc, char* buffer, int buflen);
+ void slotReceivedStderr(KProcess* proc, char* buffer, int buflen);
+ void slotWroteStdin(KProcess* proc);
+
+ private:
+
+ /**
+ * True if the plugin supports separate synthesis (option set by user).
+ */
+ bool m_supportsSynth;
+
+ /**
+ * TTS command
+ */
+ QString m_ttsCommand;
+
+ /**
+ * True if process should use Stdin.
+ */
+ bool m_stdin;
+
+ /**
+ * Language Group.
+ */
+ QString m_language;
+
+ /**
+ * Codec.
+ */
+ QTextCodec* m_codec;
+
+ /**
+ * Flite process
+ */
+ KProcess* m_commandProc;
+
+ /**
+ * Name of temporary file containing text.
+ */
+ QString m_textFilename;
+
+ /**
+ * Synthesis filename.
+ */
+ QString m_synthFilename;
+
+ /**
+ * Plugin state.
+ */
+ pluginState m_state;
+
+ /**
+ * True when stopText has been called. Used to force transition to psIdle when
+ * Flite exits.
+ */
+ bool m_waitingStop;
+};
+
+#endif // _COMMANDPROC_H_
diff --git a/kttsd/plugins/command/configure.in.in b/kttsd/plugins/command/configure.in.in
new file mode 100644
index 0000000..125ee26
--- /dev/null
+++ b/kttsd/plugins/command/configure.in.in
@@ -0,0 +1,17 @@
+dnl ==========================
+dnl checks for Command plug in
+dnl ==========================
+
+AC_ARG_ENABLE(kttsd-command,
+ AC_HELP_STRING([--enable-kttsd-command],
+ [build KTTSD Command Plugin [default=yes]]),
+ command_plugin=$enableval,
+ command_plugin=yes)
+
+compile_command_plugin="no"
+
+if test "x$command_plugin" = "xyes"; then
+ compile_command_plugin="yes"
+fi
+
+AM_CONDITIONAL(include_kttsd_command, test "x$compile_command_plugin" = "xyes")
diff --git a/kttsd/plugins/command/kttsd_commandplugin.desktop b/kttsd/plugins/command/kttsd_commandplugin.desktop
new file mode 100644
index 0000000..c141790
--- /dev/null
+++ b/kttsd/plugins/command/kttsd_commandplugin.desktop
@@ -0,0 +1,92 @@
+[Desktop Entry]
+Name=Command
+Name[br]=Urzhiad
+Name[bs]=Naredba
+Name[ca]=Odre
+Name[cs]=Příkaz
+Name[cy]=Gorchymyn
+Name[da]=Kommando
+Name[de]=Befehl
+Name[el]=Εντολή
+Name[es]=Orden
+Name[et]=Käsk
+Name[fa]=فرمان
+Name[fi]=Komento
+Name[fr]=Commande
+Name[ga]=Ordú
+Name[gl]=Comando
+Name[he]=פקודה
+Name[hu]=Parancs
+Name[is]=Skipun
+Name[it]=Comando
+Name[ja]=コマンド
+Name[ka]=ბრძანება
+Name[km]=ពាក្យ​បញ្ជា
+Name[mk]=Командна линија
+Name[ms]=Arahan
+Name[nb]=Kommando
+Name[nds]=Befehl
+Name[ne]=आदेश
+Name[pa]=ਕਮਾਂਡ
+Name[pl]=Polecenie
+Name[pt]=Comando
+Name[ru]=Командная строка
+Name[sk]=Príkaz
+Name[sl]=Ukaz
+Name[sr]=Наредба
+Name[sr@Latn]=Naredba
+Name[sv]=Kommando
+Name[ta]=கட்டளை
+Name[tg]=Сатри фармоишӣ
+Name[tr]=Komut
+Name[uk]=Команда
+Name[vi]=Ra lệnh
+Name[zh_TW]=命令
+Comment=Generic speech synthesizer from command line
+Comment[bg]=Общ синтезатор на глас от командния ред
+Comment[bs]=Generalna sinteza govora sa komandne linije
+Comment[ca]=Sintetitzador de veu genèric de línia d'ordres
+Comment[cs]=Hlasový syntetizátor pro příkazovou řádku
+Comment[da]=Generisk tale-synthesizer fra kommandolinjen
+Comment[de]=Generischer Sprachsynthesizer in der Befehlszeile
+Comment[el]=Γενικός συνθέτης ομιλίας για τη γραμμή εντολών
+Comment[es]=Sintetizador genérico de texto a voz para la línea de órdenes
+Comment[et]=Üldine käsurea-kõnesüntesaator
+Comment[eu]=Komando-lerroko hizketa-sintetizadore generikoa
+Comment[fa]=ترکیب‌دهندۀ گفتار عمومی از خط فرمان
+Comment[fi]=Yleinen komentorivipohjainen puhesyntetisaattori
+Comment[fr]=Synthèse vocale générique en ligne de commande
+Comment[ga]=Sintéiseoir cainte ginearálta ó líne na n-orduithe
+Comment[gl]=Sintetizados de fala xenérico para a liña de comandos
+Comment[hu]=Parancssoros kezelőprogram szövegfelolvasáshoz
+Comment[is]=Almennur talgerfill frá skipanalínu
+Comment[it]=Sintetizzatore vocale generico dalla riga di comando
+Comment[ja]=コマンドラインからの汎用スピーチシンセサイザ
+Comment[ka]=საზოგადო ხმის სინქრონიზატორი ბრძანების ველიდან
+Comment[km]=កម្មវិធី​សង្គ្រោះ​ការនិយាយ​ទូទៅ​ពី​បន្ទាត់​ពាក្យ​បញ្ជា
+Comment[mk]=Синтисајзер на општ говор од командната линија
+Comment[ms]=Pensintesis tutur generik dari baris arahan
+Comment[nb]=Generisk talesyntetisering fra kommandolinje
+Comment[nds]=Blicksnuut för de Befehlsreeg
+Comment[ne]=आदेश रेखाबाट जेनेरिक संवाद सिन्थेसाइजर
+Comment[nl]=Generieke spraaksynthesizer voor de commandoregel
+Comment[pa]=ਕਮਾਂਡ ਲਾਈਨ ਤੋਂ ਸਧਾਰਨ ਬੋਲੀ ਸੰਸਲੇਸ਼ਕ
+Comment[pl]=Program syntezatora mowy uruchamiany z linii poleceń
+Comment[pt]=Sintetizador de fala genérico através de uma linha de comandos
+Comment[pt_BR]=Interface de linha de comando para o sintetizador de fala genérico
+Comment[ru]=Консольный интерфейс к движкам синтеза речи
+Comment[sk]=Všeobecný syntetizátor reči z príkazového riadka
+Comment[sl]=Generični sintetizator govora iz ukazne vrstice
+Comment[sr]=Генерички синтетизатор говора из командне линије
+Comment[sr@Latn]=Generički sintetizator govora iz komandne linije
+Comment[sv]=Generell talsyntes från kommandoraden
+Comment[ta]=கட்டளை வரியில் இருந்து பொது பேச்சு கூட்டிணைப்பாளர்
+Comment[tg]=Консоли интерфейс ба микшерҳо барои таҳлили овоз
+Comment[tr]=Komut satırından genel konuşma bireştirici
+Comment[uk]=Загальний синтезатор мовлення з командного рядка
+Comment[vi]=Tổng hợp giọng nói chung cho việc ra lệnh
+Comment[zh_TW]=從命令列的一般語音合成器
+Type=Service
+ServiceTypes=KTTSD/SynthPlugin
+X-KDE-Library=libkttsd_commandplugin
+X-KDE-Languages=other
diff --git a/kttsd/plugins/epos/Makefile.am b/kttsd/plugins/epos/Makefile.am
new file mode 100644
index 0000000..8f40ca7
--- /dev/null
+++ b/kttsd/plugins/epos/Makefile.am
@@ -0,0 +1,20 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_eposplugin.la
+
+libkttsd_eposplugin_la_SOURCES = \
+ eposconfwidget.ui \
+ eposconf.cpp \
+ eposproc.cpp \
+ eposplugin.cpp
+libkttsd_eposplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_eposplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_eposplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+noinst_HEADERS = eposproc.h eposconf.h eposconfwidget.h
diff --git a/kttsd/plugins/epos/README b/kttsd/plugins/epos/README
new file mode 100644
index 0000000..2f61a9c
--- /dev/null
+++ b/kttsd/plugins/epos/README
@@ -0,0 +1,3 @@
+This is the directory containing the Epos plug in.
+This plugin is developed and maintained by Gary Cramblitt.
+<garycramblitt@comcast.net>
diff --git a/kttsd/plugins/epos/configure.in.bot b/kttsd/plugins/epos/configure.in.bot
new file mode 100644
index 0000000..59f4fdc
--- /dev/null
+++ b/kttsd/plugins/epos/configure.in.bot
@@ -0,0 +1,15 @@
+if test "x$epos_bindir" = "xno"; then
+ if test "$compile_epos_plugin" = "yes"; then
+ echo ""
+ echo "======================================================="
+ echo "The Epos program does not appear to be"
+ echo "installed on this system. The epos plugin will"
+ echo "be built, but you need to install epos before you"
+ echo "can use it. You can get it at"
+ echo " http://epos.ure.cas.cz/"
+ echo "Debian users: apt-get install epos"
+ echo "======================================================"
+ all_tests=bad
+ fi
+fi
+
diff --git a/kttsd/plugins/epos/configure.in.in b/kttsd/plugins/epos/configure.in.in
new file mode 100644
index 0000000..5a0f655
--- /dev/null
+++ b/kttsd/plugins/epos/configure.in.in
@@ -0,0 +1,22 @@
+dnl =========================================
+dnl checks for Festival Lite (epos) Plug In
+dnl =========================================
+
+AC_ARG_ENABLE(kttsd-epos,
+ AC_HELP_STRING([--enable-kttsd-epos],
+ [build KTTSD Epos plugin [default=yes]]),
+ epos_plugin=$enableval,
+ epos_plugin=yes)
+
+compile_epos_plugin="yes"
+
+if test "x$epos_plugin" = "xno"; then
+ compile_epos_plugin="no"
+fi
+
+dnl Check for epos executable.
+dnl Note that epos plugin is always built, unless
+dnl user overrides on configure command line.
+AC_PATH_PROG(epos_bindir, "epos", "no")
+
+AM_CONDITIONAL(include_kttsd_epos, test "x$compile_epos_plugin" != "xno")
diff --git a/kttsd/plugins/epos/eposconf.cpp b/kttsd/plugins/epos/eposconf.cpp
new file mode 100644
index 0000000..063c9f9
--- /dev/null
+++ b/kttsd/plugins/epos/eposconf.cpp
@@ -0,0 +1,319 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Configuration widget and functions for Epos plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// C++ includes.
+#include <math.h>
+
+// Qt includes.
+#include <qfile.h>
+#include <qapplication.h>
+#include <qtextcodec.h>
+#include <qlayout.h>
+#include <qslider.h>
+
+// KDE includes.
+#include <kdialog.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+#include <kcombobox.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+// KTTS includes.
+#include <testplayer.h>
+
+// Epos Plugin includes.
+#include "eposproc.h"
+#include "eposconf.h"
+#include "eposconf.moc"
+
+/** Constructor */
+EposConf::EposConf( QWidget* parent, const char* name, const QStringList& /*args*/) :
+ PlugInConf(parent, name)
+{
+ // kdDebug() << "EposConf::EposConf: Running" << endl;
+ m_eposProc = 0;
+ m_progressDlg = 0;
+
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "EposConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new EposConfWidget(this, "EposConfigWidget");
+ layout->addWidget(m_widget);
+
+ // Build codec list and fill combobox.
+ m_codecList = PlugInProc::buildCodecList();
+ m_widget->characterCodingBox->clear();
+ m_widget->characterCodingBox->insertStringList(m_codecList);
+
+ defaults();
+
+ connect(m_widget->eposServerPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->eposClientPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->timeBox, SIGNAL(valueChanged(int)),
+ this, SLOT(timeBox_valueChanged(int)));
+ connect(m_widget->frequencyBox, SIGNAL(valueChanged(int)),
+ this, SLOT(frequencyBox_valueChanged(int)));
+ connect(m_widget->timeSlider, SIGNAL(valueChanged(int)),
+ this, SLOT(timeSlider_valueChanged(int)));
+ connect(m_widget->frequencySlider, SIGNAL(valueChanged(int)),
+ this, SLOT(frequencySlider_valueChanged(int)));
+ connect(m_widget->timeBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->timeSlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->frequencyBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->frequencySlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->characterCodingBox, SIGNAL(activated(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->eposServerOptions, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->eposClientOptions, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->eposTest, SIGNAL(clicked()),
+ this, SLOT(slotEposTest_clicked()));
+}
+
+/** Destructor */
+EposConf::~EposConf(){
+ // kdDebug() << "Running: EposConf::~EposConf()" << endl;
+ if (!m_waveFile.isNull()) QFile::remove(m_waveFile);
+ delete m_eposProc;
+ delete m_progressDlg;
+}
+
+void EposConf::load(KConfig *config, const QString &configGroup){
+ // kdDebug() << "EposConf::load: Running " << endl;
+
+ config->setGroup(configGroup);
+ m_widget->eposServerPath->setURL(config->readEntry("EposServerExePath", "eposd"));
+ m_widget->eposClientPath->setURL(config->readEntry("EposClientExePath", "say-epos"));
+ m_widget->eposServerOptions->setText(config->readEntry("EposServerOptions", ""));
+ m_widget->eposClientOptions->setText(config->readEntry("EposClientOptions", ""));
+ QString codecString = config->readEntry("Codec", "ISO 8859-2");
+ int codec = PlugInProc::codecNameToListIndex(codecString, m_codecList);
+ m_widget->timeBox->setValue(config->readNumEntry("time", 100));
+ m_widget->frequencyBox->setValue(config->readNumEntry("pitch", 100));
+ m_widget->characterCodingBox->setCurrentItem(codec);
+}
+
+/**
+* Converts a language code into the language setting passed to Epos synth.
+*/
+QString EposConf::languageCodeToEposLanguage(const QString &languageCode)
+{
+ QString eposLanguage;
+ if (languageCode.left(2) == "cs") eposLanguage = "czech";
+ if (languageCode.left(2) == "sk") eposLanguage = "slovak";
+ return eposLanguage;
+}
+
+void EposConf::save(KConfig *config, const QString &configGroup){
+ // kdDebug() << "EposConf::save: Running" << endl;
+
+ config->setGroup("Epos");
+ config->writeEntry("EposServerExePath",
+ realFilePath(m_widget->eposServerPath->url()));
+ config->writeEntry("EposClientExePath",
+ realFilePath(m_widget->eposClientPath->url()));
+ config->writeEntry("Language", languageCodeToEposLanguage(m_languageCode));
+ config->setGroup(configGroup);
+ config->writeEntry("EposServerExePath",
+ realFilePath(m_widget->eposServerPath->url()));
+ config->writeEntry("EposClientExePath",
+ realFilePath(m_widget->eposClientPath->url()));
+ config->writeEntry("EposServerOptions", m_widget->eposServerOptions->text());
+ config->writeEntry("EposClientOptions", m_widget->eposClientOptions->text());
+ config->writeEntry("time", m_widget->timeBox->value());
+ config->writeEntry("pitch", m_widget->frequencyBox->value());
+ int codec = m_widget->characterCodingBox->currentItem();
+ config->writeEntry("Codec", PlugInProc::codecIndexToCodecName(codec, m_codecList));
+}
+
+void EposConf::defaults(){
+ // kdDebug() << "EposConf::defaults: Running" << endl;
+ // Epos server command changed from epos to eposd. Epos client command changed from
+ // say to say-epos. These changes appeared around Epos v2.5.35. Try for these automatically.
+ QString exeName = "eposd";
+ if (realFilePath(exeName).isEmpty())
+ if (!realFilePath("epos").isEmpty())
+ exeName = "epos";
+ m_widget->eposServerPath->setURL(exeName);
+ exeName = "say-epos";
+ if (realFilePath(exeName).isEmpty())
+ if (!realFilePath("say").isEmpty())
+ exeName = "say";
+ m_widget->eposClientPath->setURL(exeName);
+ m_widget->eposServerOptions->setText("");
+ m_widget->eposClientOptions->setText("");
+ m_widget->timeBox->setValue(100);
+ timeBox_valueChanged(100);
+ m_widget->frequencyBox->setValue(100);
+ frequencyBox_valueChanged(100);
+ int codec = PlugInProc::codecNameToListIndex("ISO 8859-2", m_codecList);
+ m_widget->characterCodingBox->setCurrentItem(codec);
+}
+
+void EposConf::setDesiredLanguage(const QString &lang)
+{
+ m_languageCode = lang;
+}
+
+QString EposConf::getTalkerCode()
+{
+ QString eposServerExe = realFilePath(m_widget->eposServerPath->url());
+ QString eposClientExe = realFilePath(m_widget->eposClientPath->url());
+ if (!eposServerExe.isEmpty() && !eposClientExe.isEmpty())
+ {
+ if (!getLocation(eposServerExe).isEmpty() && !getLocation(eposClientExe).isEmpty())
+ {
+ QString rate = "medium";
+ if (m_widget->timeBox->value() < 75) rate = "slow";
+ if (m_widget->timeBox->value() > 125) rate = "fast";
+ return QString(
+ "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />"
+ "<prosody volume=\"%4\" rate=\"%5\" />"
+ "<kttsd synthesizer=\"%6\" />")
+ .arg(m_languageCode)
+ .arg("fixed")
+ .arg("neutral")
+ .arg("medium")
+ .arg(rate)
+ .arg("Epos TTS Synthesis System");
+ }
+ }
+ return QString::null;
+}
+
+void EposConf::slotEposTest_clicked()
+{
+ // kdDebug() << "EposConf::slotEposTest_clicked(): Running" << endl;
+ // If currently synthesizing, stop it.
+ if (m_eposProc)
+ m_eposProc->stopText();
+ else
+ {
+ m_eposProc = new EposProc();
+ connect (m_eposProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
+ }
+ // Create a temp file name for the wave file.
+ KTempFile tempFile (locateLocal("tmp", "eposplugin-"), ".wav");
+ QString tmpWaveFile = tempFile.file()->name();
+ tempFile.close();
+
+ // Get test message in the language of the voice.
+ QString testMsg = testMessage(m_languageCode);
+
+ // Tell user to wait.
+ m_progressDlg = new KProgressDialog(m_widget, "kttsmgr_epos_testdlg",
+ i18n("Testing"),
+ i18n("Testing."),
+ true);
+ m_progressDlg->progressBar()->hide();
+ m_progressDlg->setAllowCancel(true);
+
+ // TODO: Whenever server options change, the server must be restarted.
+ // TODO: Do codec names contain non-ASCII characters?
+ connect (m_eposProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ m_eposProc->synth(
+ testMsg,
+ tmpWaveFile,
+ realFilePath(m_widget->eposServerPath->url()),
+ realFilePath(m_widget->eposClientPath->url()),
+ m_widget->eposServerOptions->text(),
+ m_widget->eposClientOptions->text(),
+ PlugInProc::codecIndexToCodec(m_widget->characterCodingBox->currentItem(), m_codecList),
+ languageCodeToEposLanguage(m_languageCode),
+ m_widget->timeBox->value(),
+ m_widget->frequencyBox->value()
+ );
+
+ // Display progress dialog modally. Processing continues when plugin signals synthFinished,
+ // or if user clicks Cancel button.
+ m_progressDlg->exec();
+ disconnect (m_eposProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ if (m_progressDlg->wasCancelled()) m_eposProc->stopText();
+ delete m_progressDlg;
+ m_progressDlg = 0;
+}
+
+void EposConf::slotSynthFinished()
+{
+ // If user canceled, progress dialog is gone, so exit.
+ if (!m_progressDlg)
+ {
+ m_eposProc->ackFinished();
+ return;
+ }
+ // Hide the Cancel button so user can't cancel in the middle of playback.
+ m_progressDlg->showCancelButton(false);
+ // Get new wavefile name.
+ m_waveFile = m_eposProc->getFilename();
+ // Tell synth we're done.
+ m_eposProc->ackFinished();
+ // Play the wave file (possibly adjusting its Speed).
+ // Player object deletes the wave file when done.
+ if (m_player) m_player->play(m_waveFile);
+ QFile::remove(m_waveFile);
+ m_waveFile = QString::null;
+ if (m_progressDlg) m_progressDlg->close();
+}
+
+void EposConf::slotSynthStopped()
+{
+ // Clean up after canceling test.
+ QString filename = m_eposProc->getFilename();
+ if (!filename.isNull()) QFile::remove(filename);
+}
+
+// Basically the slider values are logarithmic (0,...,1000) whereas percent
+// values are linear (50%,...,200%).
+//
+// slider = alpha * (log(percent)-log(50))
+// with alpha = 1000/(log(200)-log(50))
+
+int EposConf::percentToSlider(int percentValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor (0.5 + alpha * (log(percentValue)-log(50)));
+}
+
+int EposConf::sliderToPercent(int sliderValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor(0.5 + exp (sliderValue/alpha + log(50)));
+}
+
+void EposConf::timeBox_valueChanged(int percentValue) {
+ m_widget->timeSlider->setValue (percentToSlider (percentValue));
+}
+
+void EposConf::frequencyBox_valueChanged(int percentValue) {
+ m_widget->frequencySlider->setValue(percentToSlider(percentValue));
+}
+
+void EposConf::timeSlider_valueChanged(int sliderValue) {
+ m_widget->timeBox->setValue (sliderToPercent (sliderValue));
+}
+
+void EposConf::frequencySlider_valueChanged(int sliderValue) {
+ m_widget->frequencyBox->setValue(sliderToPercent(sliderValue));
+}
diff --git a/kttsd/plugins/epos/eposconf.h b/kttsd/plugins/epos/eposconf.h
new file mode 100644
index 0000000..5c3fbe3
--- /dev/null
+++ b/kttsd/plugins/epos/eposconf.h
@@ -0,0 +1,141 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Configuration widget and functions for Epos plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _EPOSCONF_H_
+#define _EPOSCONF_H_
+
+// Qt includes.
+#include <qstring.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kprogress.h>
+
+// KTTS includes.
+#include <pluginconf.h>
+
+// Epos plugin includes.
+#include "eposconfwidget.h"
+
+class EposProc;
+class KProgressDialog;
+
+class EposConf : public PlugInConf {
+ Q_OBJECT
+
+ public:
+ /** Constructor */
+ EposConf( QWidget* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /** Destructor */
+ ~EposConf();
+
+ /** This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. NOTE that this is not called after the modules is loaded,
+ * so you probably want to call this method in the constructor.
+ */
+ void load(KConfig *config, const QString &configGroup);
+
+ /** This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok".
+ */
+ void save(KConfig *config, const QString &configGroup);
+
+ /** This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file.
+ */
+ void defaults();
+
+ /**
+ * This function informs the plugin of the desired language to be spoken
+ * by the plugin. The plugin should attempt to adapt itself to the
+ * specified language code, choosing sensible defaults if necessary.
+ * If the passed-in code is QString::null, no specific language has
+ * been chosen.
+ * @param lang The desired language code or Null if none.
+ *
+ * If the plugin is unable to support the desired language, that is OK.
+ * Language codes are given by ISO 639-1 and are in lowercase.
+ * The code may also include an ISO 3166 country code in uppercase
+ * separated from the language code by underscore (_). For
+ * example, en_GB. If your plugin supports the given language, but
+ * not the given country, treat it as though the country
+ * code were not specified, i.e., adapt to the given language.
+ */
+ void setDesiredLanguage(const QString &lang);
+
+ /**
+ * Return fully-specified talker code for the configured plugin. This code
+ * uniquely identifies the configured instance of the plugin and distinquishes
+ * one instance from another. If the plugin has not been fully configured,
+ * i.e., cannot yet synthesize, return QString::null.
+ * @return Fully-specified talker code.
+ */
+ QString getTalkerCode();
+
+ private slots:
+ void configChanged(){
+ kdDebug() << "EposConf::configChanged: Running" << endl;
+ emit changed(true);
+ };
+ void slotEposTest_clicked();
+ void slotSynthFinished();
+ void slotSynthStopped();
+ void timeBox_valueChanged(int percentValue);
+ void frequencyBox_valueChanged(int percentValue);
+ void timeSlider_valueChanged(int sliderValue);
+ void frequencySlider_valueChanged(int sliderValue);
+
+ private:
+ /**
+ * Converts a language code into the language setting passed to Epos synth.
+ */
+ QString languageCodeToEposLanguage(const QString &languageCode);
+
+ int percentToSlider(int percentValue);
+ int sliderToPercent(int sliderValue);
+
+ // Language code.
+ QString m_languageCode;
+
+ // Configuration widget.
+ EposConfWidget* m_widget;
+
+ // Epos synthesizer.
+ EposProc* m_eposProc;
+ // Synthesized wave file name.
+ QString m_waveFile;
+ // Progress dialog.
+ KProgressDialog* m_progressDlg;
+ // List of displayed codec names.
+ QStringList m_codecList;
+};
+#endif // _EPOSCONF_H_
diff --git a/kttsd/plugins/epos/eposconfwidget.ui b/kttsd/plugins/epos/eposconfwidget.ui
new file mode 100644
index 0000000..23e47da
--- /dev/null
+++ b/kttsd/plugins/epos/eposconfwidget.ui
@@ -0,0 +1,610 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>EposConfWidget</class>
+<author>Gary Cramblitt</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>EposConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>535</width>
+ <height>381</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Epos Config UI</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the configuration dialog for the Epos Czech and Slovak speech synthesizer.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>eposConfigurationBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>E&amp;pos Configuration</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the configuration dialog for the Epos Czech and Slovak speech synthesizer.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>characterCodingLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Character &amp;encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Specifies which character encoding is used for passing the text.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout17</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>timeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Speed:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast".</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>frequencyLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Pitch:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>frequencyBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the tone (frequency) of speech. Slide the slider to the left to lower the voice tone; to the right to increase tone. Anything less than 75 percent is considered "low", and anything greater than 125 percent is considered "high".</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast".</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>frequencyBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the tone (frequency) of speech. Slide the slider to the left to lower the voice tone; to the right to increase tone. Anything less than 75 percent is considered "low", and anything greater than 125 percent is considered "high".</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout16</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>timeSlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast".</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>frequencySlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the tone (frequency) of speech. Slide the slider to the left to lower the voice tone; to the right to increase tone. Anything less than 75 percent is considered "low", and anything greater than 125 percent is considered "high".</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>eposServerPathLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Epos server executable path:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>festivalVoicesPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If the Epos server program will be found due to your PATH environment variable, simply enter "epos", otherwise enter the full path to the Epos server executable program.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>eposClientPathLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Epos client executable path:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>festivalVoicesPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If the Epos client program will be found due to the PATH environment variable, simply enter "say" here. Otherwise, specify the full path to the Epos client program.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>eposServerPath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="url" stdset="0">
+ <string>epos</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If the Epos server program will be found due to your PATH environment variable, simply enter "epos", otherwise enter the full path to the Epos server executable program.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>eposClientPath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="url" stdset="0">
+ <string>say</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If the Epos client program will be found due to the PATH environment variable, simply enter "say" here. Otherwise, specify the full path to the Epos client program.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox" row="3" column="0">
+ <property name="name">
+ <cstring>advancedGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Additional Options (advanced)</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>eposServerOptions</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Optional. Enter any server command line options here. To see available options, enter "epos -h" in a terminal. Do not use "-o".</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>eposClientOptions</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Specify options to be passed to Epos client. To see available options, enter "say -h" in a terminal. Do not use "-o".</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>eposServerOptionsLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Epos server:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>festivalVoicesPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Optional. Enter any server command line options here. To see available options, enter "epos -h" in a terminal. Do not use "-o".</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>eposClientOptionsLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Epos client:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>festivalVoicesPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Specify options to be passed to Epos client. Do not use -o. To see available options, enter "say -h" in a terminal. Do not use "-o".</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="4" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>410</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>eposTest</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Test</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to test the configuration. If correct, you will hear a sentence spoken.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>eposServerPath</tabstop>
+ <tabstop>eposClientPath</tabstop>
+ <tabstop>characterCodingBox</tabstop>
+ <tabstop>eposTest</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/plugins/epos/eposplugin.cpp b/kttsd/plugins/epos/eposplugin.cpp
new file mode 100644
index 0000000..9bc0bee
--- /dev/null
+++ b/kttsd/plugins/epos/eposplugin.cpp
@@ -0,0 +1,31 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so Epos can be used as plug in.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "eposconf.h"
+#include "eposproc.h"
+
+typedef K_TYPELIST_2( EposProc, EposConf ) Epos;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_eposplugin, KGenericFactory<Epos>("kttsd_epos") )
+
diff --git a/kttsd/plugins/epos/eposproc.cpp b/kttsd/plugins/epos/eposproc.cpp
new file mode 100644
index 0000000..35bc1d3
--- /dev/null
+++ b/kttsd/plugins/epos/eposproc.cpp
@@ -0,0 +1,389 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ eposproc.cpp
+ Main speaking functions for the Epos Plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// C++ includes.
+#include <math.h>
+
+// Qt includes.
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextcodec.h>
+#include <qfile.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kconfig.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+
+// Epos Plugin includes.
+#include "eposproc.h"
+#include "eposproc.moc"
+
+/** Constructor */
+EposProc::EposProc( QObject* parent, const char* name, const QStringList& ) :
+ PlugInProc( parent, name ){
+ kdDebug() << "EposProc::EposProc: Running" << endl;
+ m_state = psIdle;
+ m_waitingStop = false;
+ m_eposServerProc = 0;
+ m_eposProc = 0;
+}
+
+/** Destructor */
+EposProc::~EposProc(){
+ kdDebug() << "EposProc::~EposProc:: Running" << endl;
+ if (m_eposProc)
+ {
+ stopText();
+ delete m_eposProc;
+ }
+ delete m_eposServerProc;
+}
+
+/** Initialize the speech */
+bool EposProc::init(KConfig* config, const QString& configGroup)
+{
+ // kdDebug() << "EposProc::init: Running" << endl;
+ // kdDebug() << "Initializing plug in: Epos" << endl;
+ // Retrieve path to epos executable.
+ config->setGroup(configGroup);
+ m_eposServerExePath = config->readEntry("EposServerExePath", "epos");
+ m_eposClientExePath = config->readEntry("EposClientExePath", "say");
+ m_eposLanguage = config->readEntry("Language", QString::null);
+ m_time = config->readNumEntry("time", 100);
+ m_pitch = config->readNumEntry("pitch", 100);
+ m_eposServerOptions = config->readEntry("EposServerOptions", QString::null);
+ m_eposClientOptions = config->readEntry("EposClientOptions", QString::null);
+ kdDebug() << "EposProc::init: path to epos server: " << m_eposServerExePath << endl;
+ kdDebug() << "EposProc::init: path to epos client: " << m_eposClientExePath << endl;
+
+ QString codecString = config->readEntry("Codec", "Local");
+ m_codec = codecNameToCodec(codecString);
+ // Start the Epos server if not already started.
+ if (!m_eposServerProc)
+ {
+ m_eposServerProc = new KProcess;
+ *m_eposServerProc << m_eposServerExePath;
+ if (!m_eposServerOptions.isEmpty())
+ *m_eposServerProc << m_eposServerOptions;
+ connect(m_eposServerProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStdout(KProcess*, char*, int)));
+ connect(m_eposServerProc, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStderr(KProcess*, char*, int)));
+ m_eposServerProc->start(KProcess::DontCare, KProcess::AllOutput);
+ }
+
+ kdDebug() << "EposProc::init: Initialized with codec: " << codecString << endl;
+
+ return true;
+}
+
+/**
+* Say a text. Synthesize and audibilize it.
+* @param text The text to be spoken.
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void EposProc::sayText(const QString &text)
+{
+ synth(text, QString::null, m_eposServerExePath, m_eposClientExePath,
+ m_eposServerOptions, m_eposClientOptions,
+ m_codec, m_eposLanguage, m_time, m_pitch);
+}
+
+/**
+* Synthesize text into an audio file, but do not send to the audio device.
+* @param text The text to be synthesized.
+* @param suggestedFilename Full pathname of file to create. The plugin
+* may ignore this parameter and choose its own
+* filename. KTTSD will query the generated
+* filename using getFilename().
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void EposProc::synthText(const QString& text, const QString& suggestedFilename)
+{
+ synth(text, suggestedFilename, m_eposServerExePath, m_eposClientExePath,
+ m_eposServerOptions, m_eposClientOptions,
+ m_codec, m_eposLanguage, m_time, m_pitch);
+}
+
+/**
+* Say or Synthesize text.
+* @param text The text to be synthesized.
+* @param suggestedFilename If not Null, synthesize only to this filename, otherwise
+* synthesize and audibilize the text.
+* @param eposServerExePath Path to the Epos server executable.
+* @param eposClientExePath Path to the Epos client executable.
+* @param eposServerOptions Options passed to Epos server executable.
+* @param eposClientOptions Options passed to Epos client executable (don't include -o).
+* @param codec Codec for encoding of text.
+* @param eposLanguage Epos language setting. "czech", "slovak",
+* or null (default language).
+* @param time Speed percentage. 50 to 200. 200% = 2x normal.
+* @param pitch Pitch persentage. 50 to 200.
+*/
+void EposProc::synth(
+ const QString &text,
+ const QString &suggestedFilename,
+ const QString& eposServerExePath,
+ const QString& eposClientExePath,
+ const QString& eposServerOptions,
+ const QString& eposClientOptions,
+ QTextCodec *codec,
+ const QString& eposLanguage,
+ int time,
+ int pitch)
+{
+ // kdDebug() << "Running: EposProc::synth(const QString &text)" << endl;
+
+ if (m_eposProc)
+ {
+ if (m_eposProc->isRunning()) m_eposProc->kill();
+ delete m_eposProc;
+ m_eposProc = 0;
+ }
+ // Start the Epos server if not already started.
+ if (!m_eposServerProc)
+ {
+ m_eposServerProc = new KProcess;
+ *m_eposServerProc << eposServerExePath;
+ if (!eposServerOptions.isEmpty())
+ *m_eposServerProc << eposServerOptions;
+ connect(m_eposServerProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStdout(KProcess*, char*, int)));
+ connect(m_eposServerProc, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStderr(KProcess*, char*, int)));
+ m_eposServerProc->start(KProcess::DontCare, KProcess::AllOutput);
+ kdDebug() << "EposProc:: Epos server process started" << endl;
+ }
+
+// // Encode the text.
+// // 1.a) encode the text
+// m_encText = QCString();
+// QTextStream ts (m_encText, IO_WriteOnly);
+// ts.setCodec(codec);
+// ts << text;
+// ts << endl; // Some synths need this, eg. flite.
+
+ if (codec)
+ m_encText = codec->fromUnicode(text);
+ else
+ m_encText = text.latin1(); // Should not happen, but just in case.
+
+ // kdDebug()<< "EposProc::synth: Creating Epos object" << endl;
+ m_eposProc = new KProcess;
+ m_eposProc->setUseShell(true);
+ QString languageCode;
+ if (eposLanguage == "czech")
+ languageCode == "cz";
+ else if (eposLanguage == "slovak")
+ languageCode == "sk";
+ if (!languageCode.isEmpty())
+ {
+ m_eposProc->setEnvironment("LANG", languageCode + "." + codec->mimeName());
+ m_eposProc->setEnvironment("LC_CTYPE", languageCode + "." + codec->mimeName());
+ }
+ *m_eposProc << eposClientExePath;
+ // Language.
+ if (!eposLanguage.isEmpty())
+ *m_eposProc << QString("--language=%1").arg(eposLanguage);
+ // Rate (speed).
+ // Map 50% to 200% onto 0 to 1000.
+ // slider = alpha * (log(percent)-log(50))
+ // with alpha = 1000/(log(200)-log(50))
+ double alpha = 1000 / (log(200) - log(50));
+ int slider = (int)floor (0.5 + alpha * (log(time)-log(50)));
+ // Center at 0.
+ slider = slider - 500;
+ // Map -500 to 500 onto 45 to -45 then shift to 130 to 40 (85 midpoint).
+ float stretchValue = (-float(slider) * 45.0 / 500.0) + 85.0;
+ QString timeMsg = QString("--init_t=%1").arg(stretchValue, 0, 'f', 3);
+ *m_eposProc << timeMsg;
+ // Pitch. Map 50% to 200% onto 50 to 200. easy.
+ QString pitchMsg = QString("--init_f=%1").arg(pitch);
+ *m_eposProc << pitchMsg;
+ // Output file.
+ if (!suggestedFilename.isEmpty())
+ *m_eposProc << "-o";
+ if (!eposClientOptions.isEmpty())
+ *m_eposProc << eposClientOptions;
+ *m_eposProc << "-"; // Read from StdIn.
+ if (!suggestedFilename.isEmpty())
+ *m_eposProc << " >" + suggestedFilename;
+ connect(m_eposProc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*)));
+ connect(m_eposProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStdout(KProcess*, char*, int)));
+ connect(m_eposProc, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStderr(KProcess*, char*, int)));
+ connect(m_eposProc, SIGNAL(wroteStdin(KProcess*)),
+ this, SLOT(slotWroteStdin(KProcess* )));
+ if (suggestedFilename.isEmpty())
+ m_state = psSaying;
+ else
+ m_state = psSynthing;
+
+ // Ok, let's rock.
+ m_synthFilename = suggestedFilename;
+ // kdDebug() << "EposProc::synth: Synthing text: '" << text << "' using Epos plug in" << endl;
+ if (!m_eposProc->start(KProcess::NotifyOnExit, KProcess::All))
+ {
+ kdDebug() << "EposProc::synth: Error starting Epos process. Is epos in the PATH?" << endl;
+ m_state = psIdle;
+ return;
+ }
+ // kdDebug() << "EposProc:synth: Epos initialized" << endl;
+ // kdDebug() << "EposProc::synth: m_encText.length() = " << m_encText.length() << " text.length() = "
+ // << text.length() << endl;
+ if (!m_eposProc->writeStdin(m_encText, m_encText.length()))
+ kdDebug() << "EposProc::synth: Error writing to Epos client StdIn." << endl;
+}
+
+/**
+* Get the generated audio filename from synthText.
+* @return Name of the audio file the plugin generated.
+* Null if no such file.
+*
+* The plugin must not re-use the filename.
+*/
+QString EposProc::getFilename()
+{
+ kdDebug() << "EposProc::getFilename: returning " << m_synthFilename << endl;
+ return m_synthFilename;
+}
+
+/**
+* Stop current operation (saying or synthesizing text).
+* Important: This function may be called from a thread different from the
+* one that called sayText or synthText.
+* If the plugin cannot stop an in-progress @ref sayText or
+* @ref synthText operation, it must not block waiting for it to complete.
+* Instead, return immediately.
+*
+* If a plugin returns before the operation has actually been stopped,
+* the plugin must emit the @ref stopped signal when the operation has
+* actually stopped.
+*
+* The plugin should change to the psIdle state after stopping the
+* operation.
+*/
+void EposProc::stopText(){
+ kdDebug() << "EposProc::stopText:: Running" << endl;
+ if (m_eposProc)
+ {
+ if (m_eposProc->isRunning())
+ {
+ kdDebug() << "EposProc::stopText: killing Epos." << endl;
+ m_waitingStop = true;
+ m_eposProc->kill();
+ } else m_state = psIdle;
+ } else m_state = psIdle;
+ kdDebug() << "EposProc::stopText: Epos stopped." << endl;
+}
+
+void EposProc::slotProcessExited(KProcess*)
+{
+ // kdDebug() << "EposProc:slotProcessExited: Epos process has exited." << endl;
+ pluginState prevState = m_state;
+ if (m_waitingStop)
+ {
+ m_waitingStop = false;
+ m_state = psIdle;
+ emit stopped();
+ } else {
+ m_state = psFinished;
+ if (prevState == psSaying)
+ emit sayFinished();
+ else
+ if (prevState == psSynthing)
+ emit synthFinished();
+ }
+}
+
+void EposProc::slotReceivedStdout(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "EposProc::slotReceivedStdout: Received output from Epos: " << buf << endl;
+}
+
+void EposProc::slotReceivedStderr(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "EposProc::slotReceivedStderr: Received error from Epos: " << buf << endl;
+}
+
+void EposProc::slotWroteStdin(KProcess*)
+{
+ // kdDebug() << "EposProc::slotWroteStdin: closing Stdin" << endl;
+ m_eposProc->closeStdin();
+ m_encText = QCString();
+}
+
+/**
+* Return the current state of the plugin.
+* This function only makes sense in asynchronous mode.
+* @return The pluginState of the plugin.
+*
+* @see pluginState
+*/
+pluginState EposProc::getState() { return m_state; }
+
+/**
+* Acknowledges a finished state and resets the plugin state to psIdle.
+*
+* If the plugin is not in state psFinished, nothing happens.
+* The plugin may use this call to do any post-processing cleanup,
+* for example, blanking the stored filename (but do not delete the file).
+* Calling program should call getFilename prior to ackFinished.
+*/
+void EposProc::ackFinished()
+{
+ if (m_state == psFinished)
+ {
+ m_state = psIdle;
+ m_synthFilename = QString::null;
+ }
+}
+
+/**
+* Returns True if the plugin supports asynchronous processing,
+* i.e., returns immediately from sayText or synthText.
+* @return True if this plugin supports asynchronous processing.
+*
+* If the plugin returns True, it must also implement @ref getState .
+* It must also emit @ref sayFinished or @ref synthFinished signals when
+* saying or synthesis is completed.
+*/
+bool EposProc::supportsAsync() { return true; }
+
+/**
+* Returns True if the plugin supports synthText method,
+* i.e., is able to synthesize text to a sound file without
+* audibilizing the text.
+* @return True if this plugin supports synthText method.
+*/
+bool EposProc::supportsSynth() { return true; }
diff --git a/kttsd/plugins/epos/eposproc.h b/kttsd/plugins/epos/eposproc.h
new file mode 100644
index 0000000..b2d1d90
--- /dev/null
+++ b/kttsd/plugins/epos/eposproc.h
@@ -0,0 +1,241 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ eposproc.h
+ Main speaking functions for the Epos Plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _EPOSPROC_H_
+#define _EPOSPROC_H_
+
+// Qt includes.
+#include <qstringlist.h>
+#include <qmutex.h>
+
+// KTTS includes.
+#include <pluginproc.h>
+
+class KProcess;
+class QTextCodec;
+
+class EposProc : public PlugInProc{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ EposProc( QObject* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /**
+ * Destructor
+ */
+ virtual ~EposProc();
+
+ /**
+ * Initializate the speech engine.
+ * @param config Settings object.
+ * @param configGroup Settings group.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Say a text string.
+ * @param text The text to speak.
+ */
+ virtual void sayText(const QString &text);
+
+ /**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately.
+ */
+ virtual void synthText(const QString& text, const QString& suggestedFilename);
+
+ /**
+ * Get the generated audio filename from synthText.
+ * @return Name of the audio file the plugin generated.
+ * Null if no such file.
+ *
+ * The plugin must not re-use the filename.
+ */
+ virtual QString getFilename();
+
+ /**
+ * Stop current operation (saying or synthesizing text).
+ * Important: This function may be called from a thread different from the
+ * one that called sayText or synthText.
+ * If the plugin cannot stop an in-progress @ref sayText or
+ * @ref synthText operation, it must not block waiting for it to complete.
+ * Instead, return immediately.
+ *
+ * If a plugin returns before the operation has actually been stopped,
+ * the plugin must emit the @ref stopped signal when the operation has
+ * actually stopped.
+ *
+ * The plugin should change to the psIdle state after stopping the
+ * operation.
+ */
+ virtual void stopText();
+
+ /**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @see pluginState
+ */
+ virtual pluginState getState();
+
+ /**
+ * Acknowledges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref sayFinished or @ref synthFinished signals when
+ * saying or synthesis is completed.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Returns True if the plugin supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ */
+ virtual bool supportsSynth();
+
+ /**
+ * Say or Synthesize text.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename If not Null, synthesize only to this filename, otherwise
+ * synthesize and audibilize the text.
+ * @param eposServerExePath Path to the Epos server executable.
+ * @param eposClientExePath Path to the Epos client executable.
+ * @param eposServerOptions Options passed to Epos server executable.
+ * @param eposClientOptions Options passed to Epos client executable (don't include -o).
+ * @param codec Codec for encoding of text.
+ * @param eposLanguage Epos language setting. "czech", "slovak",
+ * or null (default language).
+ * @param time Speed percentage. 50 to 200. 200% = 2x normal.
+ * @param pitch Pitch persentage. 50 to 200.
+ */
+ void synth(
+ const QString &text,
+ const QString &suggestedFilename,
+ const QString& eposServerExePath,
+ const QString& eposClientExePath,
+ const QString& eposServerOptions,
+ const QString& eposClientOptions,
+ QTextCodec *codec,
+ const QString& eposLanguage,
+ int time,
+ int pitch);
+
+ private slots:
+ void slotProcessExited(KProcess* proc);
+ void slotReceivedStdout(KProcess* proc, char* buffer, int buflen);
+ void slotReceivedStderr(KProcess* proc, char* buffer, int buflen);
+ void slotWroteStdin(KProcess* proc);
+
+ private:
+
+ /**
+ * Path to epos executables (from config).
+ */
+ QString m_eposServerExePath;
+ QString m_eposClientExePath;
+
+ /**
+ * User options passed to executables (from config).
+ */
+ QString m_eposServerOptions;
+ QString m_eposClientOptions;
+
+ /**
+ * Epos Server process.
+ */
+ KProcess* m_eposServerProc;
+
+ /**
+ * Epos Client process
+ */
+ KProcess* m_eposProc;
+
+ /**
+ * Epos language setting. "czech", "slovak", or Null (use default language).
+ */
+ QString m_eposLanguage;
+
+ /**
+ * Rate (speed) from config file.
+ */
+ int m_time;
+
+ /**
+ * Pitch from the config file.
+ */
+ int m_pitch;
+
+ /**
+ * Codec.
+ */
+ QTextCodec* m_codec;
+
+ /**
+ * Encoded buffer to be sent to Epos client.
+ */
+ QCString m_encText;
+
+ /**
+ * Synthesis filename.
+ */
+ QString m_synthFilename;
+
+ /**
+ * Plugin state.
+ */
+ pluginState m_state;
+
+ /**
+ * True when stopText has been called. Used to force transition to psIdle when
+ * Epos exits.
+ */
+ bool m_waitingStop;
+
+};
+
+#endif // _EPOSPROC_H_
diff --git a/kttsd/plugins/epos/kttsd_eposplugin.desktop b/kttsd/plugins/epos/kttsd_eposplugin.desktop
new file mode 100644
index 0000000..7673929
--- /dev/null
+++ b/kttsd/plugins/epos/kttsd_eposplugin.desktop
@@ -0,0 +1,87 @@
+[Desktop Entry]
+Name=Epos TTS Synthesis System
+Name[ca]=Sistema de síntesi Epos TTS
+Name[cs]=Epos TTS
+Name[da]=Epos TTS Synthesis-system
+Name[de]=Epos TTS-Synthese-System
+Name[el]=Σύστημα σύνθεσης Epos TTS
+Name[es]=Sistema de síntesis Epos TTS
+Name[et]=Kõnesünteesisüsteem Epos TTS
+Name[eu]=Epos TTS sintesi-sistema
+Name[fa]=سیستم ترکیب‌دهی Epos TTS
+Name[fi]=Epos TTS -syntetisoijasysteemi
+Name[fr]=Système de synthèse Epos TTS
+Name[ga]=Córas Sintéise TTS Epos
+Name[gl]=Sistema de Síntese de TTS Epos
+Name[hu]=Epos szövegfelolvasó motor
+Name[it]=Sistema di sintesi TTS Epos
+Name[ja]=Epos TTS シンセサイズシステム
+Name[ka]=Epos TTS სინთეზის სისტემა
+Name[km]=ប្រព័ន្ធ​សង្គ្រោះ Epos TTS
+Name[mk]=Epos TTS систем за синтеза
+Name[ms]=Sistem Sintesis Epos TTS
+Name[nb]=Epos TTT syntesesystem
+Name[nds]=Epos Blicksnuut
+Name[ne]=Epos TTS सिन्थेसिस प्रणाली
+Name[nl]=Epos TTS Synthesis-systeem
+Name[pa]=Epos TTS ਸੰਸਲੇਸ਼ਣ ਸਿਸਟਮ
+Name[pl]=System syntezy mowy Epos
+Name[pt]=Sistema de Síntese Epos TTS
+Name[pt_BR]=Sistema de Sintetizador de Fala Epos
+Name[sk]=Systém Epos TTS Synthesis
+Name[sl]=Sistem sinteze besedila v govor Epos
+Name[sr]=Систем за синтезу Epos TTS
+Name[sr@Latn]=Sistem za sintezu Epos TTS
+Name[sv]=Epos TTS syntessystem
+Name[ta]=Epos TTS கூட்டிணைப்பு அமைப்பு
+Name[tg]=Системаи Синтезиси Epos TTS
+Name[tr]=Epos TTS Sentezleme Sistemi
+Name[vi]=Hệ thống Tổng hợp Văn bản sang Tiếng nói Epos
+Name[zh_TW]=Epos TTS 合成系統
+Comment=Epos TTS speech synthesizer
+Comment[bg]=Синтезатор на глас Epos TTS
+Comment[ca]=Sintetitzador de veu Epos TTS
+Comment[cs]=Hlasový syntetizér Epos TTS
+Comment[da]=Epos TTS tale-synthesizer
+Comment[de]=Epos TTS-Sprachsynthesizer
+Comment[el]=Συνθέτης ομιλίας Epos TTS
+Comment[es]=Sintetizador de texto a voz Epos TTS
+Comment[et]=Kõnesüntesaator Epos TTS
+Comment[eu]=Epos TTS hizketa-sintetizadorea
+Comment[fa]=ترکیب‌دهندۀ گفتار Epos TTS
+Comment[fi]=Epos TTS -puhesyntetisaattori
+Comment[fr]=Synthèse vocale Epos TTS
+Comment[ga]=Sintéiseoir cainte TTS Epos
+Comment[gl]=Sintetizador de fala TTS Epos
+Comment[hu]=Epos TTS beszédszintetizátor
+Comment[is]=Epos TTS talgerfill
+Comment[it]=Sintetizzatore vocale TTS Epos
+Comment[ja]=Epos TTS スピーチシンセサイザ
+Comment[ka]=Epos TTS სიტყვის სინთეზატორი
+Comment[km]=កម្មវិធី​សង្គ្រោះ​ការនិយាយ Epos TTS
+Comment[mk]=Epos TTS синтетизатор на говор
+Comment[ms]=Pensintesis tutur Epos TTS
+Comment[nb]=Epos TTT talesyntetisering
+Comment[nds]=Blicksnuut vun Epos
+Comment[ne]=Epos TTS संवाद सिन्थेसाइजर
+Comment[nl]=Epos TTS spraaksynthesizer
+Comment[pa]=Epos TTS ਬੋਲੀ ਸੰਸਲੇਸ਼ਣ
+Comment[pl]=Syntezator mowy Epos
+Comment[pt]=O sintetizador de fala Epos TTS
+Comment[pt_BR]=Sistema de Sintetizador de Fala Epos
+Comment[ru]=Синтезатор речи Epos TTS
+Comment[sk]=Syntetizátor reči Epos TTS
+Comment[sl]=Sintetizator besedila v govor Epos
+Comment[sr]=Синтетизатор говора Epos TTS
+Comment[sr@Latn]=Sintetizator govora Epos TTS
+Comment[sv]=Epos TTS talsyntes
+Comment[ta]=Epos TTS பேச்சு கூட்டிணைப்பான்
+Comment[tg]=Таҳлилгари овози Epos TTS
+Comment[tr]=Epos TTS konuşma sentezleyicisi
+Comment[uk]=Синтезатор мовлення Epos TTS
+Comment[vi]=Trình tổng hợp Văn bản sang Tiếng nói Epos
+Comment[zh_TW]=Epos TTS 語音合成器
+Type=Service
+ServiceTypes=KTTSD/SynthPlugin
+X-KDE-Library=libkttsd_eposplugin
+X-KDE-Languages=cs,sk
diff --git a/kttsd/plugins/festivalint/Makefile.am b/kttsd/plugins/festivalint/Makefile.am
new file mode 100644
index 0000000..7c6ca0e
--- /dev/null
+++ b/kttsd/plugins/festivalint/Makefile.am
@@ -0,0 +1,27 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_festivalintplugin.la
+
+libkttsd_festivalintplugin_la_SOURCES = \
+ festivalintconfwidget.ui \
+ festivalintconf.cpp \
+ festivalintproc.cpp \
+ festivalintplugin.cpp
+libkttsd_festivalintplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_festivalintplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_festivalintplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+# Install data files.
+festivalintdatadir = $(kde_datadir)/kttsd/festivalint/
+festivalintdata_DATA = voices sabletowave.scm
+
+festivalintxsltdatadir = $(kde_datadir)/kttsd/festivalint/xslt/
+festivalintxsltdata_DATA = SSMLtoSable.xsl
+
+noinst_HEADERS = festivalintconfwidget.h
diff --git a/kttsd/plugins/festivalint/README b/kttsd/plugins/festivalint/README
new file mode 100644
index 0000000..3903dd0
--- /dev/null
+++ b/kttsd/plugins/festivalint/README
@@ -0,0 +1,9 @@
+This is the directory containing the Festival (Interactive) plug in.
+This plugin is developed and maintained by Gary Cramblitt.
+<garycramblitt@comcast.net>
+
+Make sure that Festival has write access to the audio device
+
+ chmod a+rw /dev/dsp*
+
+
diff --git a/kttsd/plugins/festivalint/SSMLtoSable.xsl b/kttsd/plugins/festivalint/SSMLtoSable.xsl
new file mode 100644
index 0000000..48c2fd0
--- /dev/null
+++ b/kttsd/plugins/festivalint/SSMLtoSable.xsl
@@ -0,0 +1,272 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ***********************************************************************
+ SSMLtoSable.xsl
+ Stylesheet for transforming SSML into SABLE markup.
+ ============
+ Copyright : (C) 2004 by Paul Giannaros
+ ============
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ *************************************************************************** -->
+<!-- @todo create a doc detailing which parts of SSML this sheet can handle -->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="html" indent="no"/>
+
+<!-- speak: Indicates SSML markup. -->
+<xsl:template match="/speak">
+ <SABLE><xsl:apply-templates/></SABLE>
+</xsl:template>
+
+<!-- sub: The word that the text sounds like as abbreviations
+ can be pronounced differently. For example,
+ <sub alias="doctor">Dr.</sub> smith lives at 32 johnson <sub alias="drive">dr.</sub> -->
+<xsl:template match="//sub">
+ <xsl:choose>
+ <xsl:when test="@alias">
+ <xsl:value-of select="@alias"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- p: Indicate a paragraph of text -->
+<xsl:template match="//p">
+ <DIV TYPE="paragraph"><xsl:apply-templates/></DIV>
+</xsl:template>
+<!-- s: Forceefully indicate a sentence (Does not need to be used
+ if full stops are present) -->
+<xsl:template match="//s">
+ <DIV TYPE="sentence"><xsl:apply-templates/></DIV>
+</xsl:template>
+
+<!-- emphasis: Emphasize a word or group of words. -->
+<xsl:template match="//emphasis">
+ <!-- SSML and SABLE both take the same values for their attributes -
+ strong, moderate, none, reduced -->
+ <EM TYPE="{@level}"><xsl:apply-templates/></EM>
+</xsl:template>
+
+<xsl:template match="//voice">
+ <!-- This is turned off because if Festival lacks an installed voice to match a gender
+ or voice name, it bombs out. argh!
+ <xsl:call-template name="voice"><xsl:with-param name="a" select="@*" /></xsl:call-template> -->
+ <xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template name="voice">
+ <xsl:param name="a" />
+ <!-- Get the name of the tag we're creating and convert to a SABLE tag. -->
+ <xsl:variable name="tag">
+ <xsl:choose>
+ <xsl:when test="name($a[1])='gender'">SPEAKER</xsl:when>
+ <xsl:when test="name($a[1])='age'">SPEAKER</xsl:when>
+ <xsl:when test="name($a[1])='name'">SPEAKER</xsl:when>
+ <xsl:otherwise><xsl:value-of select="$a[1]"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:element name="{$tag}">
+ <!-- Create the right attribute to go with element $tag. -->
+
+ <xsl:choose>
+ <!-- gender:
+ The gender of the voice.
+ Values such as male, female, and neutral are supported. -->
+ <xsl:when test="name($a[1])='gender' and $a[1]='male'">
+ <xsl:attribute name="GENDER">male1</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='gender' and $a[1]='female'">
+ <xsl:attribute name="GENDER">female1</xsl:attribute>
+ </xsl:when>
+ <!-- If none of the above match, take the users selected value. -->
+ <xsl:when test="name($a[1])='gender'">
+ <xsl:attribute name="GENDER"><xsl:value-of select=" $a[1]"/></xsl:attribute>
+ </xsl:when>
+
+ <!-- age:
+ The age of the voice.
+ Positive integer values are supported. -->
+ <xsl:when test="name($a[1])='age' and number($a[1]) &lt; 10">
+ <xsl:attribute name="AGE">child</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='age' and number($a[1]) &lt; 20">
+ <xsl:attribute name="AGE">teen</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='age' and number($a[1]) &lt; 30">
+ <xsl:attribute name="AGE">younger</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='age' and number($a[1]) &lt; 50">
+ <xsl:attribute name="AGE">middle</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='age'">
+ <xsl:attribute name="AGE">older</xsl:attribute>
+ </xsl:when>
+
+ <!-- name:
+ Voice name. Synth dependent. -->
+ <xsl:when test="name($a[1])='name'">
+ <xsl:attribute name="NAME"><xsl:value-of select=" $a[1]"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+
+ <!-- Recursively call ourself. -->
+ <xsl:choose>
+ <xsl:when test="$a[2]">
+ <xsl:call-template name="voice"><xsl:with-param name="a" select="$a[position()>1]" /></xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:element>
+</xsl:template>
+
+<xsl:template match="prosody">
+ <!-- contour and duration not supported. -->
+ <xsl:call-template name="prosody"><xsl:with-param name="a"
+ select="@pitch|@rate|@volume|@range" />
+ </xsl:call-template>
+</xsl:template>
+
+<xsl:template name="prosody">
+ <xsl:param name="a" />
+ <!-- Get the name of the tag we're creating and convert to a SABLE tag. -->
+ <xsl:variable name="tag">
+ <xsl:choose>
+ <xsl:when test="name($a[1])='pitch'">PITCH</xsl:when>
+ <xsl:when test="name($a[1])='rate'">RATE</xsl:when>
+ <xsl:when test="name($a[1])='volume'">VOLUME</xsl:when>
+ <xsl:when test="name($a[1])='range'">PITCH</xsl:when>
+ <xsl:otherwise><xsl:value-of select="$a[1]"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:element name="{$tag}">
+ <!-- Create the right attribute to go with element $tag. -->
+
+ <xsl:choose>
+ <!-- pitch:
+ The pitch with which the text is spoken.
+ Values such as x-high, high, low, etc. and percentages (+ or -)
+ are supported. -->
+ <xsl:when test="name($a[1])='pitch' and $a[1]='x-high'">
+ <xsl:attribute name="BASE">70%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='pitch' and $a[1]='high'">
+ <xsl:attribute name="BASE">40%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='pitch' and $a[1]='medium'">
+ <xsl:attribute name="BASE">0%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='pitch' and $a[1]='low'">
+ <xsl:attribute name="BASE">-40%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='pitch' and $a[1]='x-low'">
+ <xsl:attribute name="BASE">-70%</xsl:attribute>
+ </xsl:when>
+ <!-- If none of the above match, take the users selected value. -->
+ <xsl:when test="name($a[1])='pitch'">
+ <xsl:attribute name="BASE"><xsl:value-of select=" $a[1]"/></xsl:attribute>
+ </xsl:when>
+
+ <!-- rate:
+ The speed at which the text is spoken.
+ Values such as x-fast, fast, slow, etc. and percentages (+ or -)
+ are supported. -->
+ <xsl:when test="name($a[1])='rate' and $a[1]='x-fast'">
+ <xsl:attribute name="SPEED">70%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='rate' and $a[1]='fast'">
+ <xsl:attribute name="SPEED">40%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='rate' and $a[1]='medium'">
+ <xsl:attribute name="SPEED">0%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='rate' and $a[1]='slow'">
+ <xsl:attribute name="SPEED">-40%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='rate' and $a[1]='x-slow'">
+ <xsl:attribute name="SPEED">-70%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='rate'">
+ <xsl:attribute name="SPEED"><xsl:value-of select=" $a[1]"/></xsl:attribute>
+ </xsl:when>
+
+ <!-- volume:
+ The volume at which the text is spoken.
+ Values such as x-loud, loud, quiet, etc. and percentages (+ or -)
+ are supported. -->
+ <xsl:when test="name($a[1])='volume' and $a[1]='x-loud'">
+ <xsl:attribute name="LEVEL">70%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='volume' and $a[1]='loud'">
+ <xsl:attribute name="LEVEL">50%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='volume' and $a[1]='medium'">
+ <xsl:attribute name="LEVEL">0%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='volume' and $a[1]='soft'">
+ <xsl:attribute name="LEVEL">-50%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='volume' and $a[1]='x-soft'">
+ <xsl:attribute name="LEVEL">-70%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='volume' and $a[1]='silent'">
+ <xsl:attribute name="LEVEL">-100%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='volume'">
+ <xsl:attribute name="LEVEL"><xsl:value-of select=" $a[1]"/></xsl:attribute>
+ </xsl:when>
+
+ <!-- range:
+ The volume at which the text is spoken.
+ Values such as x-high, high, medium, low, x-low, etc. and percentages (+ or -)
+ are supported. -->
+ <xsl:when test="name($a[1])='range' and $a[1]='x-high'">
+ <xsl:attribute name="RANGE">70%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='range' and $a[1]='high'">
+ <xsl:attribute name="RANGE">40%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='range' and $a[1]='medium'">
+ <xsl:attribute name="RANGE">0%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='range' and $a[1]='low'">
+ <xsl:attribute name="RANGE">-40%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name($a[1])='range' and $a[1]='x-low'">
+ <xsl:attribute name="RANGE">-70%</xsl:attribute>
+ </xsl:when>
+ <!-- If none of the above match, take the users selected value. -->
+ <xsl:when test="name($a[1])='range'">
+ <xsl:attribute name="RANGE"><xsl:value-of select=" $a[1]"/></xsl:attribute>
+ </xsl:when>
+
+ </xsl:choose>
+
+ <!-- Recursively call ourself. -->
+ <xsl:choose>
+ <xsl:when test="$a[2]">
+ <xsl:call-template name="prosody"><xsl:with-param name="a" select="$a[position()>1]" /></xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/kttsd/plugins/festivalint/configure.in.bot b/kttsd/plugins/festivalint/configure.in.bot
new file mode 100644
index 0000000..fee52df
--- /dev/null
+++ b/kttsd/plugins/festivalint/configure.in.bot
@@ -0,0 +1,16 @@
+if test "x$festival_bindir" = "xno"; then
+ if test "$compile_festivalint_plugin" = "yes"; then
+ echo ""
+ echo "======================================================"
+ echo "The festival program does not appear to be installed"
+ echo "on this system. The Festival Interactive plugin will"
+ echo "be built, but you need to install festival before you"
+ echo "can use it. Festival comes on most Linux distribution"
+ echo "CDs, or you can get it at"
+ echo " http://www.cstr.ed.ac.uk/projects/festival/"
+ echo "Debian users: apt-get install festival"
+ echo "====================================================="
+ all_tests=bad
+ fi
+fi
+
diff --git a/kttsd/plugins/festivalint/configure.in.in b/kttsd/plugins/festivalint/configure.in.in
new file mode 100644
index 0000000..c22f422
--- /dev/null
+++ b/kttsd/plugins/festivalint/configure.in.in
@@ -0,0 +1,22 @@
+dnl ==============================
+dnl checks for FestivalInt Plug In
+dnl ==============================
+
+AC_ARG_ENABLE(kttsd-festivalint,
+ AC_HELP_STRING([--enable-kttsd-festivalint],
+ [build KTTSD Festival Interactive plugin [default=yes]]),
+ festivalint_plugin=$enableval,
+ festivalint_plugin=yes)
+
+compile_festivalint_plugin="yes"
+
+if test "x$festivalint_plugin" = "xno"; then
+ compile_festivalint_plugin="no"
+fi
+
+dnl Check for festival executable.
+dnl Note that Festival Interactive plugin is always built
+dnl whether binary is found or not, unless user overrides with -disable-festivalint.
+AC_PATH_PROG(festival_bindir, "festival", "no")
+
+AM_CONDITIONAL(include_kttsd_festivalint, test "x$compile_festivalint_plugin" = "xyes")
diff --git a/kttsd/plugins/festivalint/festivalintconf.cpp b/kttsd/plugins/festivalint/festivalintconf.cpp
new file mode 100644
index 0000000..91cd24f
--- /dev/null
+++ b/kttsd/plugins/festivalint/festivalintconf.cpp
@@ -0,0 +1,730 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Configuration widget and functions for Festival (Interactive) plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// C++ includes.
+#include <math.h>
+
+// Qt includes.
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qcheckbox.h>
+#include <qdir.h>
+#include <qslider.h>
+#include <qdom.h>
+#include <qtextcodec.h>
+
+// KDE includes.
+#include <kdialog.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <kglobal.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+#include <kprocio.h>
+#include <kprogress.h>
+#include <kiconloader.h>
+
+// KTTS includes.
+#include "testplayer.h"
+
+// FestivalInt includes.
+#include "festivalintproc.h"
+#include "festivalintconf.h"
+#include "festivalintconf.moc"
+
+/** Constructor */
+FestivalIntConf::FestivalIntConf( QWidget* parent, const char* name, const QStringList& /*args*/) :
+ PlugInConf(parent, name)
+{
+ // kdDebug() << "FestivalIntConf::FestivalIntConf: Running" << endl;
+ m_festProc = 0;
+ m_progressDlg = 0;
+ m_supportsSSML = FestivalIntProc::ssUnknown;
+
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "FestivalIntConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new FestivalIntConfWidget(this, "FestivalIntConfigWidget");
+ layout->addWidget(m_widget);
+
+ m_widget->festivalPath->setMode(KFile::File | KFile::ExistingOnly);
+ m_widget->festivalPath->setFilter("*");
+
+ // Build codec list and fill combobox.
+ m_codecList = PlugInProc::buildCodecList();
+ m_widget->characterCodingBox->clear();
+ m_widget->characterCodingBox->insertStringList(m_codecList);
+
+ // defaults();
+
+ connect(m_widget->festivalPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotFestivalPath_textChanged()));
+ connect(m_widget->selectVoiceCombo, SIGNAL(activated(const QString&)),
+ this, SLOT(slotSelectVoiceCombo_activated()));
+ connect(m_widget->selectVoiceCombo, SIGNAL(activated(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->testButton, SIGNAL(clicked()), this, SLOT(slotTest_clicked()));
+ connect(m_widget->rescan, SIGNAL(clicked()), this, SLOT(scanVoices()));
+ connect(m_widget->volumeBox, SIGNAL(valueChanged(int)),
+ this, SLOT(volumeBox_valueChanged(int)));
+ connect(m_widget->timeBox, SIGNAL(valueChanged(int)),
+ this, SLOT(timeBox_valueChanged(int)));
+ connect(m_widget->frequencyBox, SIGNAL(valueChanged(int)),
+ this, SLOT(frequencyBox_valueChanged(int)));
+ connect(m_widget->volumeSlider, SIGNAL(valueChanged(int)),
+ this, SLOT(volumeSlider_valueChanged(int)));
+ connect(m_widget->timeSlider, SIGNAL(valueChanged(int)),
+ this, SLOT(timeSlider_valueChanged(int)));
+ connect(m_widget->frequencySlider, SIGNAL(valueChanged(int)),
+ this, SLOT(frequencySlider_valueChanged(int)));
+ connect(m_widget->volumeBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->timeBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->timeSlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->frequencyBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->frequencySlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_widget->preloadCheckBox, SIGNAL(clicked()), this, SLOT(configChanged()));
+ connect(m_widget->characterCodingBox, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->characterCodingBox, SIGNAL(activated(const QString&)),
+ this, SLOT(configChanged()));
+}
+
+/** Destructor */
+FestivalIntConf::~FestivalIntConf(){
+ // kdDebug() << "FestivalIntConf::~FestivalIntConf: Running" << endl;
+ if (!m_waveFile.isNull()) QFile::remove(m_waveFile);
+ delete m_festProc;
+ delete m_progressDlg;
+}
+
+/**
+* Given a voice code, returns index into m_voiceList array (and voiceCombo box).
+* -1 if not found.
+*/
+int FestivalIntConf::voiceCodeToListIndex(const QString& voiceCode) const
+{
+ const int voiceListCount = m_voiceList.count();
+ for(int index = 0; index < voiceListCount; ++index){
+ // kdDebug() << "Testing: " << voiceCode << " == " << m_voiceList[index].code << endl;
+ if(voiceCode == m_voiceList[index].code)
+ return index;
+ }
+ return -1;
+}
+
+void FestivalIntConf::load(KConfig *config, const QString &configGroup){
+ //kdDebug() << "FestivalIntConf::load: Running" << endl;
+ config->setGroup("FestivalInt");
+ QString exePath = config->readEntry("FestivalExecutablePath", "festival");
+ QString exeLocation = getLocation(exePath);
+ if (!exeLocation.isEmpty()) exePath = exeLocation;
+ exePath = realFilePath(exePath);
+ config->setGroup(configGroup);
+ m_widget->festivalPath->setURL(config->readEntry("FestivalExecutablePath", exePath));
+ m_widget->preloadCheckBox->setChecked(false);
+ scanVoices();
+ QString voiceSelected(config->readEntry("Voice"));
+ int index = voiceCodeToListIndex(voiceSelected);
+ if (index >= 0)
+ {
+ m_widget->selectVoiceCombo->setCurrentItem(index);
+ m_widget->preloadCheckBox->setChecked(m_voiceList[index].preload);
+ }
+ m_widget->volumeBox->setValue(config->readNumEntry("volume", 100));
+ m_widget->timeBox->setValue(config->readNumEntry("time", 100));
+ m_widget->frequencyBox->setValue(config->readNumEntry("pitch", 100));
+ m_widget->preloadCheckBox->setChecked(config->readBoolEntry(
+ "Preload", m_widget->preloadCheckBox->isChecked()));
+ m_languageCode = config->readEntry("LanguageCode", m_languageCode);
+ m_supportsSSML = static_cast<FestivalIntProc::SupportsSSML>(
+ config->readNumEntry("SupportsSSML", FestivalIntProc::ssUnknown));
+ QString codecName = PlugInProc::codecIndexToCodecName(
+ m_widget->characterCodingBox->currentItem(), m_codecList);
+ codecName = config->readEntry("Codec", codecName);
+ int codecNdx = PlugInProc::codecNameToListIndex(codecName, m_codecList);
+ m_widget->characterCodingBox->setCurrentItem(codecNdx);
+}
+
+void FestivalIntConf::save(KConfig *config, const QString &configGroup){
+ // kdDebug() << "FestivalIntConf::save: Running" << endl;
+ config->setGroup("FestivalInt");
+ config->writeEntry("FestivalExecutablePath", realFilePath(m_widget->festivalPath->url()));
+ config->setGroup(configGroup);
+ config->writeEntry("FestivalExecutablePath", realFilePath(m_widget->festivalPath->url()));
+ config->writeEntry("Voice", m_voiceList[m_widget->selectVoiceCombo->currentItem()].code);
+ config->writeEntry("volume", m_widget->volumeBox->value());
+ config->writeEntry("time", m_widget->timeBox->value());
+ config->writeEntry("pitch", m_widget->frequencyBox->value());
+ config->writeEntry("Preload", m_widget->preloadCheckBox->isChecked());
+ config->writeEntry("LanguageCode", m_voiceList[m_widget->selectVoiceCombo->currentItem()].languageCode);
+ config->writeEntry("SupportsSSML", m_supportsSSML);
+ int codec = m_widget->characterCodingBox->currentItem();
+ config->writeEntry("Codec", PlugInProc::codecIndexToCodecName(codec, m_codecList));
+}
+
+void FestivalIntConf::defaults(){
+ // kdDebug() << "FestivalIntConf::defaults: Running" << endl;
+ m_widget->festivalPath->setURL("festival");
+ m_widget->timeBox->setValue(100);
+ timeBox_valueChanged(100);
+ m_widget->volumeBox->setValue(100);
+ volumeBox_valueChanged(100);
+ m_widget->frequencyBox->setValue(100);
+ frequencyBox_valueChanged(100);
+ m_widget->preloadCheckBox->setChecked(false);
+ m_widget->characterCodingBox->setCurrentItem(
+ PlugInProc::codecNameToListIndex("ISO 8859-1", m_codecList));
+ scanVoices();
+}
+
+void FestivalIntConf::setDesiredLanguage(const QString &lang)
+{
+ // kdDebug() << "FestivalIntConf::setDesiredLanguage: Running" << endl;
+ m_languageCode = splitLanguageCode(lang, m_countryCode);
+}
+
+QString FestivalIntConf::getTalkerCode()
+{
+ if (!m_widget->selectVoiceCombo->isEnabled()) return QString::null;
+ QString exePath = realFilePath(m_widget->festivalPath->url());
+ if (exePath.isEmpty()) return QString::null;
+ if (getLocation(exePath).isEmpty()) return QString::null;
+ if (m_voiceList.count() == 0) return QString::null;
+ QString normalTalkerCode;
+ voiceStruct voiceTemp = m_voiceList[m_widget->selectVoiceCombo->currentItem()];
+ // Determine volume attribute. soft < 75% <= medium <= 125% < loud.
+ QString volume = "medium";
+ if (m_widget->volumeBox->value() < 75) volume = "soft";
+ if (m_widget->volumeBox->value() > 125) volume = "loud";
+ // Determine rate attribute. slow < 75% <= medium <= 125% < fast.
+ QString rate = "medium";
+ if (m_widget->timeBox->value() < 75) rate = "slow";
+ if (m_widget->timeBox->value() > 125) rate = "fast";
+ normalTalkerCode = QString(
+ "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />"
+ "<prosody volume=\"%4\" rate=\"%5\" />"
+ "<kttsd synthesizer=\"%6\" />")
+ .arg(voiceTemp.languageCode)
+ .arg(voiceTemp.code)
+ .arg(voiceTemp.gender)
+ .arg(volume)
+ .arg(rate)
+ .arg("Festival Interactive");
+ return normalTalkerCode;
+}
+
+/**
+ * Chooses a default voice given scanned list of voices in m_voiceList and current
+ * language and country code, and updates controls.
+ * @param currentVoiceIndex This voice is preferred if it matches.
+ */
+void FestivalIntConf::setDefaultVoice(int currentVoiceIndex)
+{
+ // kdDebug() << "FestivalIntCont::setDefaultVoice: Running" << endl;
+ // If language code is known, auto pick first voice that matches the language code.
+ if (!m_languageCode.isEmpty())
+ {
+ bool found = false;
+ // First search for a match on both language code and country code.
+ QString languageCode = m_languageCode;
+ if (!m_countryCode.isNull()) languageCode += "_" + m_countryCode;
+ // kdDebug() << "FestivalIntConf::setDefaultVoice:: looking for default voice to match language code " << languageCode << endl;
+ uint index = 0;
+ // Prefer existing voice if it matches.
+ if (currentVoiceIndex >= 0)
+ {
+ QString vlCode = m_voiceList[currentVoiceIndex].languageCode.left(languageCode.length());
+ if (languageCode == vlCode)
+ {
+ found = true;
+ index = currentVoiceIndex;
+ }
+ }
+ if (!found)
+ {
+ for(index = 0 ; index < m_voiceList.count(); ++index)
+ {
+ QString vlCode = m_voiceList[index].languageCode.left(languageCode.length());
+ // kdDebug() << "FestivalIntConf::setDefaultVoice: testing " << vlCode << endl;
+ if(languageCode == vlCode)
+ {
+ found = true;
+ break;
+ }
+ }
+ }
+ // If not found, search for a match on just the language code.
+ if (!found)
+ {
+ languageCode = m_languageCode;
+ // Prefer existing voice if it matches.
+ if (currentVoiceIndex >= 0)
+ {
+ QString vlCode = m_voiceList[currentVoiceIndex].languageCode.left(languageCode.length());
+ if (languageCode == vlCode)
+ {
+ found = true;
+ index = currentVoiceIndex;
+ }
+ }
+ if (!found)
+ {
+ for(index = 0 ; index < m_voiceList.count(); ++index)
+ {
+ QString vlCode = m_voiceList[index].languageCode.left(languageCode.length());
+ // kdDebug() << "FestivalIntConf::setDefaultVoice: testing " << vlCode << endl;
+ if(languageCode == vlCode)
+ {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ // If not found, pick first voice that is not "Unknown".
+ if (!found)
+ {
+ for(index = 0 ; index < m_voiceList.count(); ++index)
+ {
+ if (m_voiceList[index].name != i18n("Unknown"))
+ {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ {
+ // kdDebug() << "FestivalIntConf::setDefaultVoice: auto picking voice code " << m_voiceList[index].code << endl;
+ m_widget->selectVoiceCombo->setCurrentItem(index);
+ m_widget->preloadCheckBox->setChecked(m_voiceList[index].preload);
+ QString codecName = m_voiceList[index].codecName;
+ int codecNdx = PlugInProc::codecNameToListIndex(codecName, m_codecList);
+ m_widget->characterCodingBox->setCurrentItem(codecNdx);
+ if (m_voiceList[index].volumeAdjustable)
+ {
+ m_widget->volumeBox->setEnabled(true);
+ m_widget->volumeSlider->setEnabled(true);
+ }
+ else
+ {
+ m_widget->volumeBox->setValue(100);
+ volumeBox_valueChanged(100);
+ m_widget->volumeBox->setEnabled(false);
+ m_widget->volumeSlider->setEnabled(false);
+ }
+ if (m_voiceList[index].rateAdjustable)
+ {
+ m_widget->timeBox->setEnabled(true);
+ m_widget->timeSlider->setEnabled(true);
+ }
+ else
+ {
+ m_widget->timeBox->setValue(100);
+ timeBox_valueChanged(100);
+ m_widget->timeBox->setEnabled(false);
+ m_widget->timeSlider->setEnabled(false);
+ }
+ if (m_voiceList[index].pitchAdjustable)
+ {
+ m_widget->frequencyBox->setEnabled(true);
+ m_widget->frequencySlider->setEnabled(true);
+ }
+ else
+ {
+ m_widget->frequencyBox->setValue(100);
+ frequencyBox_valueChanged(100);
+ m_widget->frequencyBox->setEnabled(false);
+ m_widget->frequencySlider->setEnabled(false);
+ }
+ if ((int)index != currentVoiceIndex) configChanged();
+ }
+ }
+}
+
+/**
+ * Given an XML node and child element name, returns the string value from the child element.
+ * If no such child element, returns def.
+ */
+QString FestivalIntConf::readXmlString(QDomNode &node, const QString &elementName, const QString &def)
+{
+ QDomNode childNode = node.namedItem(elementName);
+ if (!childNode.isNull())
+ return childNode.toElement().text();
+ else
+ return def;
+}
+
+/**
+ * Given an XML node and child element name, returns the boolean value from the child element.
+ * If no such child element, returns def.
+ */
+bool FestivalIntConf::readXmlBool(QDomNode &node, const QString &elementName, bool def)
+{
+ QDomNode childNode = node.namedItem(elementName);
+ if (!childNode.isNull())
+ return (childNode.toElement().text() == "true");
+ else
+ return def;
+}
+
+void FestivalIntConf::scanVoices()
+{
+ // kdDebug() << "FestivalIntConf::scanVoices: Running" << endl;
+ // Get existing voice code (if any).
+ QString currentVoiceCode;
+ int index = m_widget->selectVoiceCombo->currentItem();
+ if (index < (int)m_voiceList.count()) currentVoiceCode = m_voiceList[index].code;
+
+ m_voiceList.clear();
+ m_widget->selectVoiceCombo->clear();
+ m_widget->selectVoiceCombo->insertItem(i18n("Scanning... Please wait."));
+
+ // Save current state of selectVoiceCombo box and disable.
+ bool selectVoiceComboEnabled = m_widget->selectVoiceCombo->isEnabled();
+ m_widget->selectVoiceCombo->setEnabled(false);
+
+ // Clear existing list of supported voice codes.
+ // m_supportedVoiceCodes.clear();
+ m_widget->selectVoiceCombo->clear();
+
+ QString exePath = realFilePath(m_widget->festivalPath->url());
+ if (!getLocation(exePath).isEmpty())
+ {
+ // Set up a progress dialog.
+ m_progressDlg = new KProgressDialog(m_widget, "kttsmgr_queryvoices",
+ i18n("Query Voices"),
+ i18n("Querying Festival for available voices. This could take up to 15 seconds."),
+ true);
+ m_progressDlg->progressBar()->hide();
+ m_progressDlg->setAllowCancel(true);
+
+ // Create Festival process and request a list of voice codes.
+ if (m_festProc)
+ m_festProc->stopText();
+ else
+ {
+ m_festProc = new FestivalIntProc();
+ connect (m_festProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
+ }
+ connect (m_festProc, SIGNAL(queryVoicesFinished(const QStringList&)),
+ this, SLOT(slotQueryVoicesFinished(const QStringList&)));
+ m_festProc->queryVoices(exePath);
+
+ // Display progress dialog modally.
+ m_progressDlg->exec();
+ // kdDebug() << "FestivalIntConf::scanVoices: back from progressDlg->exec()" << endl;
+
+ // Processing continues until either user clicks Cancel button, or until
+ // Festival responds with the list. When Festival responds with list,
+ // the progress dialog is closed.
+
+ disconnect (m_festProc, SIGNAL(queryVoicesFinished(const QStringList&)),
+ this, SLOT(slotQueryVoicesFinished(const QStringList&)));
+ if (!m_progressDlg->wasCancelled()) m_festProc->stopText();
+ delete m_progressDlg;
+ m_progressDlg = 0;
+ m_supportsSSML = m_festProc->supportsSSML();
+ }
+
+ if (!m_supportedVoiceCodes.isEmpty())
+ {
+ // User's desktop language setting.
+ QString desktopLanguageCode = KGlobal::locale()->language();
+ QString twoAlpha;
+ QString countryCode;
+ QString charSet;
+ KGlobal::locale()->splitLocale(desktopLanguageCode, twoAlpha, countryCode, charSet);
+ desktopLanguageCode = twoAlpha.lower();
+
+ // Festival known voices list.
+ QString voicesFilename = KGlobal::dirs()->resourceDirs("data").last() + "/kttsd/festivalint/voices";
+ QDomDocument voicesDoc("Festival Voices");
+ QFile voicesFile(voicesFilename);
+ if (voicesFile.open(IO_ReadOnly)) voicesDoc.setContent(&voicesFile);
+ voicesFile.close();
+ QDomNodeList voices = voicesDoc.elementsByTagName("voice");
+ uint voicesCount = voices.count();
+ if (voicesCount == 0)
+ kdDebug() << "FestivalIntConf::scanVoices: Unable to open " << voicesFilename << ". Is KDEDIR defined?" << endl;
+
+ // Iterate thru list of voice codes returned by Festival,
+ // find matching entry in voices.xml file, and add to list of supported voices.
+ QPixmap maleIcon = KGlobal::iconLoader()->loadIcon("male", KIcon::Small);
+ QPixmap femaleIcon = KGlobal::iconLoader()->loadIcon("female", KIcon::Small);
+ QStringList::ConstIterator itEnd = m_supportedVoiceCodes.constEnd();
+ for(QStringList::ConstIterator it = m_supportedVoiceCodes.begin(); it != itEnd; ++it )
+ {
+ QString code = *it;
+ bool found = false;
+ for (uint index=0; index < voicesCount; ++index)
+ {
+ QDomNode voiceNode = voices.item(index);
+ QString voiceCode = readXmlString(voiceNode, "code", QString::null);
+ // kdDebug() << "FestivalIntConf::scanVoices: Comparing code " << code << " to " << voiceCode << endl;
+ if (voiceCode == code)
+ {
+ found = true;
+ voiceStruct voiceTemp;
+ voiceTemp.code = code;
+ voiceTemp.name = i18n("FestivalVoiceName",
+ readXmlString(voiceNode, "name", "Unknown").utf8());
+ voiceTemp.languageCode = readXmlString(voiceNode, "language", m_languageCode);
+ voiceTemp.codecName = readXmlString(voiceNode, "codec", "ISO 8859-1");
+ voiceTemp.gender = readXmlString(voiceNode, "gender", "neutral");
+ voiceTemp.preload = readXmlBool(voiceNode, "preload", false);
+ voiceTemp.volumeAdjustable = readXmlBool(voiceNode, "volume-adjustable", true);
+ voiceTemp.rateAdjustable = readXmlBool(voiceNode, "rate-adjustable", true);
+ voiceTemp.pitchAdjustable = readXmlBool(voiceNode, "pitch-adjustable", true);
+ m_voiceList.append(voiceTemp);
+ QString voiceDisplayName = voiceTemp.name + " (" + voiceTemp.code + ")";
+ if (voiceTemp.gender == "male")
+ m_widget->selectVoiceCombo->insertItem(maleIcon, voiceDisplayName);
+ else if (voiceTemp.gender == "female")
+ m_widget->selectVoiceCombo->insertItem(femaleIcon, voiceDisplayName);
+ else
+ m_widget->selectVoiceCombo->insertItem(voiceDisplayName);
+ break;
+ }
+ }
+ if (!found)
+ {
+ voiceStruct voiceTemp;
+ voiceTemp.code = code;
+ voiceTemp.name = i18n("Unknown");
+ voiceTemp.languageCode = m_languageCode;
+ voiceTemp.codecName = "ISO 8858-1";
+ voiceTemp.gender = "neutral";
+ voiceTemp.preload = false;
+ voiceTemp.volumeAdjustable = true;
+ voiceTemp.rateAdjustable = true;
+ voiceTemp.pitchAdjustable = true;
+ m_voiceList.append(voiceTemp);
+ m_widget->selectVoiceCombo->insertItem(voiceTemp.name + " (" + voiceTemp.code + ")");
+ }
+ }
+ m_widget->selectVoiceCombo->setEnabled(true);
+ } else kdDebug() << "FestivalIntConf::scanVoices: No voices found" << endl;
+ setDefaultVoice(voiceCodeToListIndex(currentVoiceCode));
+ // Emit configChanged if the enabled state of the selectVoiceCombo has changed.
+ // This occurs when user changes Festival EXE path, then clicks Rescan.
+ if (selectVoiceComboEnabled != m_widget->selectVoiceCombo->isEnabled()) configChanged();
+}
+
+void FestivalIntConf::slotQueryVoicesFinished(const QStringList &voiceCodes)
+{
+ // kdDebug() << "FestivalIntConf::slotQueryVoicesFinished: voiceCodes.count() = " << voiceCodes.count() << endl;
+ m_supportedVoiceCodes = voiceCodes;
+ if (m_progressDlg) m_progressDlg->close();
+}
+
+void FestivalIntConf::slotTest_clicked()
+{
+ // kdDebug() << "FestivalIntConf::slotTest_clicked: Running " << endl;
+ // If currently synthesizing, stop it.
+ if (m_festProc)
+ m_festProc->stopText();
+ else
+ {
+ m_festProc = new FestivalIntProc();
+ connect (m_festProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
+ }
+ // Create a temp file name for the wave file.
+ KTempFile tempFile (locateLocal("tmp", "festivalintplugin-"), ".wav");
+ QString tmpWaveFile = tempFile.file()->name();
+ tempFile.close();
+
+ // Get the code for the selected voice.
+ QString voiceCode = m_voiceList[m_widget->selectVoiceCombo->currentItem()].code;
+
+ // Get language code for the selected voice.
+ QString languageCode = m_voiceList[m_widget->selectVoiceCombo->currentItem()].languageCode;
+
+ // Get test message in the language of the voice.
+ QString testMsg = testMessage(languageCode);
+
+ // Get codec.
+ QTextCodec* codec = PlugInProc::codecIndexToCodec(
+ m_widget->characterCodingBox->currentItem(), m_codecList);
+
+ // Tell user to wait.
+ m_progressDlg = new KProgressDialog(m_widget, "ktts_festivalint_testdlg",
+ i18n("Testing"),
+ i18n("Testing. MultiSyn voices require several seconds to load. Please be patient."),
+ true);
+ m_progressDlg->progressBar()->hide();
+ m_progressDlg->setAllowCancel(true);
+
+ // kdDebug() << "FestivalIntConf::slotTest_clicked: calling synth with voiceCode: " << voiceCode << " time percent: " << m_widget->timeBox->value() << endl;
+ connect (m_festProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ m_festProc->synth(
+ realFilePath(m_widget->festivalPath->url()),
+ testMsg,
+ tmpWaveFile,
+ voiceCode,
+ m_widget->timeBox->value(),
+ m_widget->frequencyBox->value(),
+ m_widget->volumeBox->value(),
+ languageCode,
+ codec);
+
+ // Display progress dialog modally. Processing continues when plugin signals synthFinished,
+ // or if user clicks Cancel button.
+ m_progressDlg->exec();
+ disconnect (m_festProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ if (m_progressDlg->wasCancelled()) m_festProc->stopText();
+ delete m_progressDlg;
+ m_progressDlg = 0;
+}
+
+void FestivalIntConf::slotSynthFinished()
+{
+ // kdDebug() << "FestivalIntConf::slotSynthFinished: Running" << endl;
+ // If user canceled, progress dialog is gone, so exit.
+ if (!m_progressDlg)
+ {
+ m_festProc->ackFinished();
+ return;
+ }
+ // Hide the Cancel button so user can't cancel in the middle of playback.
+ m_progressDlg->showCancelButton(false);
+ // Get new wavefile name.
+ m_waveFile = m_festProc->getFilename();
+ // Tell synth we're done.
+ m_festProc->ackFinished();
+ // Play the wave file (possibly adjusting its Speed).
+ // Player object deletes the wave file when done.
+ if (m_player) m_player->play(m_waveFile);
+ QFile::remove(m_waveFile);
+ m_waveFile = QString::null;
+ if (m_progressDlg) m_progressDlg->close();
+}
+
+void FestivalIntConf::slotSynthStopped()
+{
+ // Clean up after canceling test.
+ QString filename = m_festProc->getFilename();
+ // kdDebug() << "FestivalIntConf::slotSynthStopped: filename = " << filename << endl;
+ if (!filename.isNull()) QFile::remove(filename);
+}
+
+void FestivalIntConf::slotFestivalPath_textChanged()
+{
+ QString exePath = realFilePath(m_widget->festivalPath->url());
+ m_widget->selectVoiceCombo->setEnabled(false);
+ if (!exePath.isEmpty() && !getLocation(exePath).isEmpty())
+ {
+ m_widget->rescan->setEnabled(true);
+ } else m_widget->rescan->setEnabled(false);
+}
+
+void FestivalIntConf::slotSelectVoiceCombo_activated()
+{
+ int index = m_widget->selectVoiceCombo->currentItem();
+ QString codecName = m_voiceList[index].codecName;
+ int codecNdx = PlugInProc::codecNameToListIndex(codecName, m_codecList);
+ m_widget->characterCodingBox->setCurrentItem(codecNdx);
+ m_widget->preloadCheckBox->setChecked(
+ m_voiceList[index].preload);
+ if (m_voiceList[index].volumeAdjustable)
+ {
+ m_widget->volumeBox->setEnabled(true);
+ m_widget->volumeSlider->setEnabled(true);
+ }
+ else
+ {
+ m_widget->volumeBox->setValue(100);
+ volumeBox_valueChanged(100);
+ m_widget->volumeBox->setEnabled(false);
+ m_widget->volumeSlider->setEnabled(false);
+ }
+ if (m_voiceList[index].rateAdjustable)
+ {
+ m_widget->timeBox->setEnabled(true);
+ m_widget->timeSlider->setEnabled(true);
+ }
+ else
+ {
+ m_widget->timeBox->setValue(100);
+ timeBox_valueChanged(100);
+ m_widget->timeBox->setEnabled(false);
+ m_widget->timeSlider->setEnabled(false);
+ }
+ if (m_voiceList[index].pitchAdjustable)
+ {
+ m_widget->frequencyBox->setEnabled(true);
+ m_widget->frequencySlider->setEnabled(true);
+ }
+ else
+ {
+ m_widget->frequencyBox->setValue(100);
+ frequencyBox_valueChanged(100);
+ m_widget->frequencyBox->setEnabled(false);
+ m_widget->frequencySlider->setEnabled(false);
+ }
+}
+
+// Basically the slider values are logarithmic (0,...,1000) whereas percent
+// values are linear (50%,...,200%).
+//
+// slider = alpha * (log(percent)-log(50))
+// with alpha = 1000/(log(200)-log(50))
+
+int FestivalIntConf::percentToSlider(int percentValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor (0.5 + alpha * (log(percentValue)-log(50)));
+}
+
+int FestivalIntConf::sliderToPercent(int sliderValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor(0.5 + exp (sliderValue/alpha + log(50)));
+}
+
+void FestivalIntConf::volumeBox_valueChanged(int percentValue) {
+ m_widget->volumeSlider->setValue(percentToSlider(percentValue));
+}
+
+void FestivalIntConf::timeBox_valueChanged(int percentValue) {
+ m_widget->timeSlider->setValue (percentToSlider (percentValue));
+}
+
+void FestivalIntConf::frequencyBox_valueChanged(int percentValue) {
+ m_widget->frequencySlider->setValue(percentToSlider(percentValue));
+}
+
+void FestivalIntConf::volumeSlider_valueChanged(int sliderValue) {
+ m_widget->volumeBox->setValue(sliderToPercent(sliderValue));
+}
+
+void FestivalIntConf::timeSlider_valueChanged(int sliderValue) {
+ m_widget->timeBox->setValue (sliderToPercent (sliderValue));
+}
+
+void FestivalIntConf::frequencySlider_valueChanged(int sliderValue) {
+ m_widget->frequencyBox->setValue(sliderToPercent(sliderValue));
+}
diff --git a/kttsd/plugins/festivalint/festivalintconf.h b/kttsd/plugins/festivalint/festivalintconf.h
new file mode 100644
index 0000000..a367682
--- /dev/null
+++ b/kttsd/plugins/festivalint/festivalintconf.h
@@ -0,0 +1,187 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Configuration widget and functions for Festival (Interactive) plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _FESTIVALINTCONF_H_
+#define _FESTIVALINTCONF_H_
+
+// Qt includes.
+#include <qstringlist.h>
+#include <qvaluelist.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "pluginconf.h"
+
+// FestivalInt includes.
+#include "festivalintconfwidget.h"
+#include "festivalintproc.h"
+
+class KProgressDialog;
+class QDomNode;
+
+typedef struct voiceStruct{
+ QString code; // Code as sent to Festival
+ QString name; // Name as displayed and returned in Talker Code.
+ QString languageCode; // Language code (en, es, etc)
+ QString codecName; // Character encoding codec name (eg. ISO 8859-1)
+ QString gender; // male, female, or neutral
+ bool preload; // Start Festival and load this language when KTTSD is started.
+ bool volumeAdjustable; // True if the voice supports volume adjustments.
+ bool rateAdjustable; // True if the voice supports rate adjustments.
+ bool pitchAdjustable; // True if the voice supports pitch adjustments.
+} voice;
+
+class FestivalIntConf : public PlugInConf {
+ Q_OBJECT
+
+ public:
+ /** Constructor */
+ FestivalIntConf( QWidget* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /** Destructor */
+ ~FestivalIntConf();
+
+ /** This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. NOTE that this is not called after the modules is loaded,
+ * so you probably want to call this method in the constructor.
+ */
+ void load(KConfig *config, const QString &configGroup);
+
+ /** This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok".
+ */
+ void save(KConfig *config, const QString &configGroup);
+
+ /** This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file. */
+ void defaults();
+
+ /**
+ * This function informs the plugin of the desired language to be spoken
+ * by the plugin. The plugin should attempt to adapt itself to the
+ * specified language code, choosing sensible defaults if necessary.
+ * If the passed-in code is QString::null, no specific language has
+ * been chosen.
+ * @param lang The desired language code or Null if none.
+ *
+ * If the plugin is unable to support the desired language, that is OK.
+ * Language codes are given by ISO 639-1 and are in lowercase.
+ * The code may also include an ISO 3166 country code in uppercase
+ * separated from the language code by underscore (_). For
+ * example, en_GB. If your plugin supports the given language, but
+ * not the given country, treat it as though the country
+ * code were not specified, i.e., adapt to the given language.
+ */
+ void setDesiredLanguage(const QString &lang);
+
+ /**
+ * Return fully-specified talker code for the configured plugin. This code
+ * uniquely identifies the configured instance of the plugin and distinquishes
+ * one instance from another. If the plugin has not been fully configured,
+ * i.e., cannot yet synthesize, return QString::null.
+ * @return Fully-specified talker code.
+ */
+ QString getTalkerCode();
+
+ private slots:
+ /** Scan for the different voices in festivalPath/lib */
+ void scanVoices();
+ void configChanged(){
+ // kdDebug() << "FestivalIntConf::configChanged: Running" << endl;
+ emit changed(true);
+ };
+ void slotTest_clicked();
+ void slotSynthFinished();
+ void slotSynthStopped();
+ void volumeBox_valueChanged(int percentValue);
+ void timeBox_valueChanged(int percentValue);
+ void frequencyBox_valueChanged(int percentValue);
+ void volumeSlider_valueChanged(int sliderValue);
+ void timeSlider_valueChanged(int sliderValue);
+ void frequencySlider_valueChanged(int sliderValue);
+ void slotFestivalPath_textChanged();
+ void slotSelectVoiceCombo_activated();
+ void slotQueryVoicesFinished(const QStringList &voiceCodes);
+
+ private:
+ int percentToSlider(int percentValue);
+ int sliderToPercent(int sliderValue);
+
+ /**
+ * Given an XML node and child element name, returns the string value from the child element.
+ * If no such child element, returns def.
+ */
+ QString readXmlString(QDomNode &node, const QString &elementName, const QString &def);
+
+ /**
+ * Given an XML node and child element name, returns the boolean value from the child element.
+ * If no such child element, returns def.
+ */
+ bool readXmlBool(QDomNode &node, const QString &elementName, bool def);
+
+ /**
+ * Given a voice code, returns index into m_voiceList array (and voiceCombo box).
+ * -1 if not found.
+ */
+ int voiceCodeToListIndex(const QString& voiceCode) const;
+
+ /**
+ * Chooses a default voice given scanned list of voices in m_voiceList and current
+ * language and country code, and updates controls.
+ * @param currentVoiceIndex This voice is preferred if it matches.
+ */
+ void setDefaultVoice(int currentVoiceIndex);
+
+ // Configuration Widget.
+ FestivalIntConfWidget* m_widget;
+
+ // Language code.
+ QString m_languageCode;
+ // Language country code (if any).
+ QString m_countryCode;
+ // List of voices */
+ QValueList<voice> m_voiceList;
+ // Festival synthesizer.
+ FestivalIntProc* m_festProc;
+ // Synthesized wave file name.
+ QString m_waveFile;
+ // Progress dialog.
+ KProgressDialog* m_progressDlg;
+ // List of voice codes supported by Festival.
+ QStringList m_supportedVoiceCodes;
+ // List of displayed codec names.
+ QStringList m_codecList;
+ // Whether Festival supports SSML or not.
+ FestivalIntProc::SupportsSSML m_supportsSSML;
+};
+#endif // _FESTIVALINTCONF_H_
diff --git a/kttsd/plugins/festivalint/festivalintconfwidget.ui b/kttsd/plugins/festivalint/festivalintconfwidget.ui
new file mode 100644
index 0000000..f8b33fb
--- /dev/null
+++ b/kttsd/plugins/festivalint/festivalintconfwidget.ui
@@ -0,0 +1,598 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>FestivalIntConfWidget</class>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>FestivalIntConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>559</width>
+ <height>318</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Festival Config UI</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the dialog for configuring the Festival speech synthesizer in interactive mode.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>festivalConfigurationBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Festival &amp;Interactive Configuration</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the dialog for configuring the Festival speech synthesizer in interactive mode.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>voicesPathBox</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>festivalPathLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Festival executable:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>festivalPath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If Festival is in your PATH environment variable, just enter "festival", otherwise specify the full path to the Festival executable program.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>festivalPath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If Festival is in your PATH environment variable, just enter "festival", otherwise specify the full path to the Festival executable program.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>selectVoiceBox</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>selectVoiceLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Select voice:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>selectVoiceCombo</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select a voice to speak text with. MultiSyn voices are high quality but are slow to load. If no voices are shown, check the Festival executable path. You must install at least one Festival voice. If you have installed a voice and still none are shown, check your Festival configuration. (See the README that comes with Festival.)</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>selectVoiceCombo</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select a voice to speak text with. MultiSyn voices are high quality but are slow to load. If no voices are shown, check the Festival executable path. You must install at least one Festival voice. If you have installed a voice and still none are shown, check your Festival configuration. (See the README that comes with Festival.)</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>rescan</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Rescan</string>
+ <comment>Rescan for voices</comment>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>volumeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Volume:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>volumeBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the volume (loudness) of speech. Slide the slider to the left to lower the volume; to the right to increase volume. Anything less than 75 percent is considered "soft", and anything greater than 125 percent is considered "loud".</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>timeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Sp&amp;eed:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>frequencyLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Pitch:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>frequencyBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the tone (frequency) of speech. Slide the slider to the left to lower the voice tone; to the right to increase tone. Anything less than 75 percent is considered "low", and anything greater than 125 percent is considered "high". You cannot change the pitch of MultiSyn voices.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>volumeBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the volume (loudness) of speech. Slide the slider to the left to lower the volume; to the right to increase volume. Anything less than 75 percent is considered "soft", and anything greater than 125 percent is considered "loud".</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>frequencyBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the tone (frequency) of speech. Slide the slider to the left to lower the voice tone; to the right to increase tone. Anything less than 75 percent is considered "low", and anything greater than 125 percent is considered "high". You cannot change the pitch of MultiSyn voices.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>volumeSlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the volume (loudness) of speech. Slide the slider to the left to lower the volume; to the right to increase volume. Anything less than 75 percent is considered "soft", and anything greater than 125 percent is considered "loud".</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>timeSlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>frequencySlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the tone (frequency) of speech. Slide the slider to the left to lower the voice tone; to the right to increase tone. Anything less than 75 percent is considered "low", and anything greater than 125 percent is considered "high". You cannot change the pitch of MultiSyn voices.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="4" column="0">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>preloadCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Load this voice when starting KTTSD</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If checked, Festival will be started and this voice will be loaded when the Text-to-Speech Deamon (KTTSD) is started. Check when a voice requires a long time to load in Festival (for example, multisyn voices), otherwise, leave unchecked.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>101</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>testButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Test</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to test the configuration. Festival will be started and a test sentence will be spoken.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>characterCodingLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Character e&amp;ncoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies which character encoding is used for passing the text.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>festivalPath</tabstop>
+ <tabstop>selectVoiceCombo</tabstop>
+ <tabstop>rescan</tabstop>
+ <tabstop>volumeBox</tabstop>
+ <tabstop>timeBox</tabstop>
+ <tabstop>frequencyBox</tabstop>
+ <tabstop>preloadCheckBox</tabstop>
+ <tabstop>testButton</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/plugins/festivalint/festivalintplugin.cpp b/kttsd/plugins/festivalint/festivalintplugin.cpp
new file mode 100644
index 0000000..d793b40
--- /dev/null
+++ b/kttsd/plugins/festivalint/festivalintplugin.cpp
@@ -0,0 +1,31 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so festival (interactive) can be used as plug in.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "festivalintconf.h"
+#include "festivalintproc.h"
+
+typedef K_TYPELIST_2( FestivalIntProc, FestivalIntConf ) Festival;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_festivalintplugin, KGenericFactory<Festival>("kttsd_festivalint") )
+
diff --git a/kttsd/plugins/festivalint/festivalintproc.cpp b/kttsd/plugins/festivalint/festivalintproc.cpp
new file mode 100644
index 0000000..77822ea
--- /dev/null
+++ b/kttsd/plugins/festivalint/festivalintproc.cpp
@@ -0,0 +1,662 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Main speaking functions for the Festival (Interactive) Plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// C++ includes.
+#include <math.h>
+
+// Qt includes.
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qthread.h>
+#include <qtextcodec.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+
+// KTTS includes.
+#include "utils.h"
+
+// FestivalInt includes.
+#include "festivalintproc.h"
+#include "festivalintproc.moc"
+
+/** Constructor */
+FestivalIntProc::FestivalIntProc( QObject* parent, const char* name, const QStringList& ) :
+ PlugInProc( parent, name ){
+ // kdDebug() << "FestivalIntProc::FestivalIntProc: Running" << endl;
+ m_ready = true;
+ m_writingStdin = false;
+ m_waitingQueryVoices = false;
+ m_waitingStop = false;
+ m_festProc = 0;
+ m_state = psIdle;
+ m_supportsSSML = ssUnknown;
+ m_languageCode = "en";
+ m_codec = QTextCodec::codecForName("ISO8859-1");
+}
+
+/** Destructor */
+FestivalIntProc::~FestivalIntProc(){
+ // kdDebug() << "FestivalIntProc::~FestivalIntProc: Running" << endl;
+ if (m_festProc)
+ {
+ if (m_festProc->isRunning())
+ {
+ if (m_ready)
+ {
+ m_state = psIdle;
+ // kdDebug() << "FestivalIntProc::~FestivalIntProc: telling Festival to quit." << endl;
+ m_ready = false;
+ m_waitingStop = true;
+ m_festProc->writeStdin("(quit)", true);
+ }
+ else
+ {
+ // kdDebug() << "FestivalIntProc::~FestivalIntProc: killing Festival." << endl;
+ m_waitingStop = true;
+ m_festProc->kill();
+ }
+ }
+ delete m_festProc;
+ }
+}
+
+/** Initialize the speech */
+bool FestivalIntProc::init(KConfig *config, const QString &configGroup)
+{
+ // kdDebug() << "FestivalIntProc::init: Initializing plug in: Festival" << endl;
+
+ config->setGroup(configGroup);
+ m_voiceCode = config->readEntry("Voice");
+ m_festivalExePath = config->readEntry("FestivalExecutablePath", "festival");
+ // kdDebug() << "---- The code for the selected voice " << config->readEntry("Voice") << " is " << voiceCode << endl;
+ m_time = config->readNumEntry("time", 100);
+ m_pitch = config->readNumEntry("pitch", 100);
+ m_volume = config->readNumEntry("volume", 100);
+ // If voice should be pre-loaded, start Festival and load the voice.
+ m_preload = config->readBoolEntry("Preload", false);
+ m_languageCode = config->readEntry("LanguageCode", "en");
+ m_supportsSSML = static_cast<SupportsSSML>(config->readNumEntry("SupportsSSML", ssUnknown));
+ QString codecName = config->readEntry("Codec", "Latin1");
+ m_codec = codecNameToCodec(codecName);
+ if (m_preload) startEngine(m_festivalExePath, m_voiceCode, m_languageCode, m_codec);
+ return true;
+}
+
+/**
+* Say a text. Synthesize and audibilize it.
+* @param text The text to be spoken.
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void FestivalIntProc::sayText(const QString &text)
+{
+ synth(m_festivalExePath, text, QString::null, m_voiceCode, m_time, m_pitch, m_volume,
+ m_languageCode, m_codec);
+}
+
+/**
+* Synthesize text into an audio file, but do not send to the audio device.
+* @param text The text to be synthesized.
+* @param suggestedFilename Full pathname of file to create. The plugin
+* may ignore this parameter and choose its own
+* filename. KTTSD will query the generated
+* filename using getFilename().
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void FestivalIntProc::synthText(const QString& text, const QString& suggestedFilename)
+{
+ synth(m_festivalExePath, text, suggestedFilename, m_voiceCode, m_time, m_pitch, m_volume,
+ m_languageCode, m_codec);
+}
+
+/**
+* Sends command to Festival to query for a list of supported voice codes.
+* Fires queryVoicesFinished when completed.
+* @return False if busy doing something else and therefore cannot
+* do the query.
+*/
+bool FestivalIntProc::queryVoices(const QString &festivalExePath)
+{
+ // kdDebug() << "FestivalIntProc::queryVoices: Running" << endl;
+ if (m_state != psIdle && m_waitingQueryVoices && m_waitingStop) return false;
+ // Start Festival if not already running.
+ startEngine(festivalExePath, QString::null, m_languageCode, m_codec);
+ // Set state, waiting for voice codes list from Festival.
+ m_waitingQueryVoices = true;
+ // Voice rab_diphone is needed in order to support SSML.
+ m_supportsSSML = ssUnknown;
+ // Send command to query the voice codes.
+ sendToFestival("(print (mapcar (lambda (pair) (car pair)) voice-locations))");
+ return true;
+}
+
+/**
+* Start Festival engine.
+* @param festivalExePath Path to the Festival executable, or just "festival".
+* @param voiceCode Voice code in which to speak text.
+* @param languageCode Language code, for example, "en".
+*/
+void FestivalIntProc::startEngine(const QString &festivalExePath, const QString &voiceCode,
+ const QString &languageCode, QTextCodec* codec)
+{
+ // Initialize Festival only if it's not initialized.
+ if (m_festProc)
+ {
+ // Stop Festival if a different EXE is requested or different language code.
+ // If festProc exists but is not running, it is because it was stopped.
+ if ((festivalExePath != m_festivalExePath) || !m_festProc->isRunning() ||
+ (m_languageCode != languageCode) || (codec->name() != m_codec->name()))
+ {
+ delete m_festProc;
+ m_festProc = 0;
+ }
+ }
+ if(!m_festProc)
+ {
+ // kdDebug()<< "FestivalIntProc::startEngine: Creating Festival object" << endl;
+ m_festProc = new KProcess;
+ *m_festProc << festivalExePath;
+ *m_festProc << "--interactive";
+ m_festProc->setEnvironment("LANG", languageCode + "." + codec->mimeName());
+ m_festProc->setEnvironment("LC_CTYPE", languageCode + "." + codec->mimeName());
+ // kdDebug() << "FestivalIntProc::startEngine: setting LANG = LC_CTYPE = " << languageCode << "." << codec->mimeName() << endl;
+ connect(m_festProc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*)));
+ connect(m_festProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStdout(KProcess*, char*, int)));
+ connect(m_festProc, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStderr(KProcess*, char*, int)));
+ connect(m_festProc, SIGNAL(wroteStdin(KProcess*)),
+ this, SLOT(slotWroteStdin(KProcess*)));
+ }
+ if (!m_festProc->isRunning())
+ {
+ // kdDebug() << "FestivalIntProc::startEngine: Starting Festival process" << endl;
+ m_runningVoiceCode = QString::null;
+ m_runningTime = 100;
+ m_runningPitch = 100;
+ m_ready = false;
+ m_outputQueue.clear();
+ if (m_festProc->start(KProcess::NotifyOnExit, KProcess::All))
+ {
+ // kdDebug()<< "FestivalIntProc:startEngine: Festival initialized" << endl;
+ m_festivalExePath = festivalExePath;
+ m_languageCode = languageCode;
+ m_codec = codec;
+ // Load the SABLE to Wave module.
+ sendToFestival("(load \"" +
+ KGlobal::dirs()->resourceDirs("data").last() + "kttsd/festivalint/sabletowave.scm\")");
+ }
+ else
+ {
+ kdDebug() << "FestivalIntProc::startEngine: Error starting Festival process. Is festival in the PATH?" << endl;
+ m_ready = true;
+ m_state = psIdle;
+ return;
+ }
+ }
+ // If we just started Festival, or voiceCode has changed, send code to Festival.
+ if (m_runningVoiceCode != voiceCode && !voiceCode.isEmpty()) {
+ sendToFestival("(voice_" + voiceCode + ")");
+ m_runningVoiceCode = voiceCode;
+ }
+}
+
+/**
+* Say or Synthesize text.
+* @param festivalExePath Path to the Festival executable, or just "festival".
+* @param text The text to be synthesized.
+* @param suggestedFilename If not Null, synthesize only to this filename, otherwise
+* synthesize and audibilize the text.
+* @param voiceCode Voice code in which to speak text.
+* @param time Speed percentage. 50 to 200. 200% = 2x normal.
+* @param pitch Pitch persentage. 50 to 200.
+* @param volume Volume percentage. 50 to 200.
+* @param languageCode Language code, for example, "en".
+*/
+void FestivalIntProc::synth(
+ const QString &festivalExePath,
+ const QString &text,
+ const QString &synthFilename,
+ const QString &voiceCode,
+ int time,
+ int pitch,
+ int volume,
+ const QString &languageCode,
+ QTextCodec* codec)
+{
+ // kdDebug() << "FestivalIntProc::synth: festivalExePath = " << festivalExePath
+ // << " voiceCode = " << voiceCode << endl;
+
+ // Initialize Festival only if it's not initialized
+ startEngine(festivalExePath, voiceCode, languageCode, codec);
+ // If we just started Festival, or rate changed, tell festival.
+ if (m_runningTime != time) {
+ QString timeMsg;
+ if (voiceCode.contains("_hts") > 0)
+ {
+ // Map 50% to 200% onto 0 to 1000.
+ // slider = alpha * (log(percent)-log(50))
+ // with alpha = 1000/(log(200)-log(50))
+ double alpha = 1000 / (log(200) - log(50));
+ int slider = (int)floor (0.5 + alpha * (log(time)-log(50)));
+ // Center at 0.
+ slider = slider - 500;
+ // Map -500 to 500 onto 0.15 to -0.15.
+ float stretchValue = -float(slider) * 0.15 / 500.0;
+ timeMsg = QString("(set! hts_duration_stretch %1)").arg(
+ stretchValue, 0, 'f', 3);
+ }
+ else
+ timeMsg = QString("(Parameter.set 'Duration_Stretch %1)").arg(
+ 1.0/(float(time)/100.0), 0, 'f', 2);
+ sendToFestival(timeMsg);
+ m_runningTime = time;
+ }
+ // If we just started Festival, or pitch changed, tell festival.
+ if (m_runningPitch != pitch) {
+ // Pitch values range from 50 to 200 %, with 100% as the midpoint,
+ // while frequency values range from 41 to 500 with 105 as the "midpoint".
+ int pitchValue;
+ if (pitch <= 100)
+ {
+ pitchValue = (((pitch - 50) * 64) / 50) + 41;
+ }
+ else
+ {
+ pitchValue = (((pitch - 100) * 395) / 100) + 105;
+ }
+ QString pitchMsg = QString(
+ "(set! int_lr_params '((target_f0_mean %1) (target_f0_std 14)"
+ "(model_f0_mean 170) (model_f0_std 34)))").arg(pitchValue, 0, 10);
+ sendToFestival(pitchMsg);
+ m_runningPitch = pitch;
+ }
+
+ QString saidText = text;
+
+ // Split really long sentences into shorter sentences, by looking for commas and converting
+ // to periods.
+ int len = saidText.length();
+ while (len > c_tooLong)
+ {
+ len = saidText.findRev(", ", len - (c_tooLong * 2 / 3), true);
+ if (len != -1)
+ {
+ QString c = saidText.mid(len+2, 1);
+ if (c != c.upper())
+ {
+ saidText.replace(len, 2, ". ");
+ saidText.replace(len+2, 1, c.upper());
+ kdDebug() << "FestivalIntProc::synth: Splitting long sentence at " << len << endl;
+ // kdDebug() << saidText << endl;
+ }
+ }
+ }
+
+ // Encode quotation characters.
+ saidText.replace("\\\"", "#!#!");
+ saidText.replace("\"", "\\\"");
+ saidText.replace("#!#!", "\\\"");
+ // Remove certain comment characters.
+ saidText.replace("--", "");
+
+ // Ok, let's rock.
+ if (synthFilename.isNull())
+ {
+ m_state = psSaying;
+ m_synthFilename = QString::null;
+ // kdDebug() << "FestivalIntProc::synth: Saying text: '" << saidText << "' using Festival plug in with voice "
+ // << voiceCode << endl;
+ saidText = "(SayText \"" + saidText + "\")";
+ sendToFestival(saidText);
+ } else {
+ m_state = psSynthing;
+ m_synthFilename = synthFilename;
+ // Volume must be given for each utterance.
+ // Volume values range from 50 to 200%, with 100% = normal.
+ // Map onto rescale range of .5 to 2.
+ float volumeValue = float(volume) / 100;
+ // Expand to range .25 to 4.
+ // float volumeValue = exp(log(volumeValue) * 2);
+ // kdDebug() << "FestivalIntProc::synth: Synthing text: '" << saidText << "' using Festival plug in with voice "
+ // << voiceCode << endl;
+ if (isSable(saidText))
+ {
+ // Synth the text and adjust volume.
+ saidText =
+ "(ktts_sabletowave \"" + saidText + "\" \"" +
+ synthFilename + "\" " +
+ QString::number(volumeValue) + ")";
+ }
+ else
+ {
+ saidText =
+ // Suppress pause at the beginning of each utterance.
+ "(define (insert_initial_pause utt) "
+ "(item.set_feat (utt.relation.first utt 'Segment) 'end 0.0))"
+ // Synth the text and adjust volume.
+ "(set! utt1 (Utterance Text \"" + saidText +
+ "\"))(utt.synth utt1)" +
+ "(utt.wave.rescale utt1 " + QString::number(volumeValue) + " t)" +
+ "(utt.save.wave utt1 \"" + synthFilename + "\")";
+ }
+ sendToFestival(saidText);
+ }
+}
+
+/**
+* If ready for more output, sends the given text to Festival process, otherwise,
+* puts it in the queue.
+* @param text Text to send or queue.
+*/
+void FestivalIntProc::sendToFestival(const QString& text)
+{
+ if (text.isNull()) return;
+ m_outputQueue.append(text);
+ sendIfReady();
+}
+
+/**
+* If Festival is ready for more input and there is more output to send, send it.
+* To be ready for more input, the Stdin buffer must be empty and the "festival>"
+* prompt must have been received (m_ready = true).
+* @return False when Festival is ready for more input
+* but there is nothing to be sent, or if Festival
+* has exited.
+*/
+bool FestivalIntProc::sendIfReady()
+{
+ if (!m_ready) return true;
+ if (m_writingStdin) return true;
+ if (m_outputQueue.isEmpty()) return false;
+ if (!m_festProc->isRunning()) return false;
+ QString text = m_outputQueue[0];
+ text += "\n";
+ QCString encodedText;
+ if (m_codec)
+ encodedText = m_codec->fromUnicode(text);
+ else
+ encodedText = text.latin1(); // Should not happen, but just in case.
+ m_outputQueue.pop_front();
+ m_ready = false;
+ // kdDebug() << "FestivalIntProc::sendIfReady: sending to Festival: " << text << endl;
+ m_writingStdin = true;
+ m_festProc->writeStdin(encodedText, encodedText.length());
+ return true;
+}
+
+/**
+* Determine if the text has SABLE tags. If so, we will have to use a different
+* synthesis method.
+*/
+bool FestivalIntProc::isSable(const QString &text)
+{
+ return KttsUtils::hasRootElement( text, "SABLE" );
+}
+
+/**
+* Get the generated audio filename from synthText.
+* @return Name of the audio file the plugin generated.
+* Null if no such file.
+*
+* The plugin must not re-use the filename.
+*/
+QString FestivalIntProc::getFilename() { return m_synthFilename; }
+
+/**
+ * Stop text
+ */
+void FestivalIntProc::stopText(){
+ // kdDebug() << "FestivalIntProc::stopText: Running" << endl;
+ if (m_festProc)
+ {
+ if (m_festProc->isRunning())
+ {
+ if (m_ready)
+ m_state = psIdle;
+ else
+ {
+ // If using a preloaded voice, killing Festival is a bad idea because of
+ // huge startup times. So if synthing (not saying), let Festival continue
+ // synthing. When it completes, we will emit the stopped signal.
+ if (m_preload && (m_state == psSynthing))
+ {
+ m_waitingStop = true;
+ // kdDebug() << "FestivalIntProc::stopText: Optimizing stopText() for preloaded voice." << endl;
+ }
+ else
+ {
+ // kdDebug() << "FestivalIntProc::stopText: killing Festival." << endl;
+ m_waitingStop = true;
+ m_festProc->kill();
+ }
+ }
+ } else m_state = psIdle;
+ } else m_state = psIdle;
+}
+
+void FestivalIntProc::slotProcessExited(KProcess*)
+{
+ // kdDebug() << "FestivalIntProc:slotProcessExited: Festival process has exited." << endl;
+ m_ready = true;
+ pluginState prevState = m_state;
+ if (m_waitingStop || m_waitingQueryVoices)
+ {
+ if (m_waitingStop)
+ {
+ m_waitingStop = false;
+ m_state = psIdle;
+ // kdDebug() << "FestivalIntProc::slotProcessExited: emitting stopped signal" << endl;
+ emit stopped();
+ }
+ if (m_waitingQueryVoices)
+ {
+ // kdDebug() << "FestivalIntProc::slotProcessExited: canceling queryVoices operation" << endl;
+ m_waitingQueryVoices = false;
+ m_state = psIdle;
+ }
+ } else {
+ if (m_state != psIdle) m_state = psFinished;
+ if (prevState == psSaying)
+ {
+ // kdDebug() << "FestivalIntProc::slotProcessExited: emitting sayFinished signal" << endl;
+ emit sayFinished();
+ } else
+ if (prevState == psSynthing)
+ {
+ // kdDebug() << "FestivalIntProc::slotProcessExited: emitting synthFinished signal" << endl;
+ emit synthFinished();
+ }
+ }
+ delete m_festProc;
+ m_festProc = 0;
+ m_outputQueue.clear();
+}
+
+void FestivalIntProc::slotReceivedStdout(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ // kdDebug() << "FestivalIntProc::slotReceivedStdout: Received from Festival: " << buf << endl;
+ bool promptSeen = (buf.contains("festival>") > 0);
+ bool emitQueryVoicesFinished = false;
+ QStringList voiceCodesList;
+ if (m_waitingQueryVoices && m_outputQueue.isEmpty())
+ {
+ // Look for opening ( and closing ).
+ buf.simplifyWhiteSpace();
+ if (buf.left(3) == "nil") {
+ emitQueryVoicesFinished = true;
+ m_waitingQueryVoices = false;
+ } else {
+ if (buf.left(1) == "(")
+ {
+ int rightParen = buf.find(')');
+ if (rightParen > 0)
+ {
+ m_waitingQueryVoices = false;
+ // Extract contents between parens.
+ buf = buf.mid(1, rightParen - 1);
+ // Space separated list.
+ voiceCodesList = QStringList::split(" ", buf, false);
+ emitQueryVoicesFinished = true;
+ }
+ }
+ }
+ }
+ if (promptSeen)
+ {
+ // kdDebug() << "FestivalIntProc::slotReceivedStdout: Prompt seen" << endl;
+ m_ready = true;
+ if (!sendIfReady())
+ {
+ // kdDebug() << "FestivalIntProc::slotReceivedStdout: All output sent. " << endl;
+ pluginState prevState = m_state;
+ if (m_state != psIdle) m_state = psFinished;
+ if (prevState == psSaying)
+ {
+ // kdDebug() << "FestivalIntProc::slotReceivedStdout: emitting sayFinished signal" << endl;
+ emit sayFinished();
+ } else
+ if (prevState == psSynthing)
+ {
+ if (m_waitingStop)
+ {
+ m_waitingStop = false;
+ m_state = psIdle;
+ // kdDebug() << "FestivalIntProc::slotReceivedStdout: emitting optimized stopped signal" << endl;
+ emit stopped();
+ }
+ else
+ {
+ // kdDebug() << "FestivalIntProc::slotReceivedStdout: emitting synthFinished signal" << endl;
+ emit synthFinished();
+ }
+ }
+ }
+ }
+ if (emitQueryVoicesFinished)
+ {
+ // kdDebug() << "FestivalIntProc::slotReceivedStdout: emitting queryVoicesFinished" << endl;
+ m_supportsSSML = (voiceCodesList.contains("rab_diphone")) ? ssYes : ssNo;
+ emit queryVoicesFinished(voiceCodesList);
+ }
+}
+
+void FestivalIntProc::slotReceivedStderr(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "FestivalIntProc::slotReceivedStderr: Received error from Festival: " << buf << endl;
+}
+
+void FestivalIntProc::slotWroteStdin(KProcess* /*proc*/)
+{
+ // kdDebug() << "FestivalIntProc::slotWroteStdin: Running" << endl;
+ m_writingStdin = false;
+ if (!sendIfReady())
+ {
+ // kdDebug() << "FestivalIntProc::slotWroteStdin: all output sent" << endl;
+ pluginState prevState = m_state;
+ if (m_state != psIdle) m_state = psFinished;
+ if (prevState == psSaying)
+ {
+ // kdDebug() << "FestivalIntProc::slotWroteStdin: emitting sayFinished signal" << endl;
+ emit sayFinished();
+ } else
+ if (prevState == psSynthing)
+ {
+ // kdDebug() << "FestivalIntProc::slotWroteStdin: emitting synthFinished signal" << endl;
+ emit synthFinished();
+ }
+ }
+}
+
+
+bool FestivalIntProc::isReady() { return m_ready; }
+
+/**
+* Return the current state of the plugin.
+* This function only makes sense in asynchronous mode.
+* @return The pluginState of the plugin.
+*
+* @see pluginState
+*/
+pluginState FestivalIntProc::getState() { return m_state; }
+
+/**
+* Acknowledges a finished state and resets the plugin state to psIdle.
+*
+* If the plugin is not in state psFinished, nothing happens.
+* The plugin may use this call to do any post-processing cleanup,
+* for example, blanking the stored filename (but do not delete the file).
+* Calling program should call getFilename prior to ackFinished.
+*/
+void FestivalIntProc::ackFinished()
+{
+ if (m_state == psFinished)
+ {
+ m_state = psIdle;
+ m_synthFilename = QString::null;
+ }
+}
+
+/**
+* Returns True if the plugin supports asynchronous processing,
+* i.e., returns immediately from sayText or synthText.
+* @return True if this plugin supports asynchronous processing.
+*
+* If the plugin returns True, it must also implement @ref getState .
+* It must also emit @ref sayFinished or @ref synthFinished signals when
+* saying or synthesis is completed.
+*/
+bool FestivalIntProc::supportsAsync() { return true; }
+
+/**
+* Returns True if the plugin supports synthText method,
+* i.e., is able to synthesize text to a sound file without
+* audibilizing the text.
+* @return True if this plugin supports synthText method.
+*/
+bool FestivalIntProc::supportsSynth() { return true; }
+
+/**
+* Returns the name of an XSLT stylesheet that will convert a valid SSML file
+* into a format that can be processed by the synth. For example,
+* The Festival plugin returns a stylesheet that will convert SSML into
+* SABLE. Any tags the synth cannot handle should be stripped (leaving
+* their text contents though). The default stylesheet strips all
+* tags and converts the file to plain text.
+* @return Name of the XSLT file.
+*/
+QString FestivalIntProc::getSsmlXsltFilename()
+{
+ if (m_supportsSSML == ssYes)
+ return KGlobal::dirs()->resourceDirs("data").last() + "kttsd/festivalint/xslt/SSMLtoSable.xsl";
+ else
+ return PlugInProc::getSsmlXsltFilename();
+}
+
diff --git a/kttsd/plugins/festivalint/festivalintproc.h b/kttsd/plugins/festivalint/festivalintproc.h
new file mode 100644
index 0000000..a69642c
--- /dev/null
+++ b/kttsd/plugins/festivalint/festivalintproc.h
@@ -0,0 +1,361 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Main speaking functions for the Festival (Interactive) Plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _FESTIVALINTPROC_H_
+#define _FESTIVALINTPROC_H_
+
+#include <qstringlist.h>
+#include <qmutex.h>
+
+#include <kprocess.h>
+
+#include <pluginproc.h>
+
+class QTextCodec;
+
+class FestivalIntProc : public PlugInProc{
+ Q_OBJECT
+
+ public:
+ enum SupportsSSML {
+ ssUnknown,
+ ssYes,
+ ssNo
+ };
+
+ /**
+ * Constructor
+ */
+ FestivalIntProc( QObject* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /**
+ * Destructor
+ */
+ virtual ~FestivalIntProc();
+
+ /**
+ * Initializate the speech engine.
+ * @param config Settings object.
+ * @param configGroup Settings group.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Returns true when festival is ready to speak a sentence.
+ */
+ bool isReady();
+
+ /**
+ * Say a text string.
+ * @param text The text to speak.
+ */
+ virtual void sayText(const QString &text);
+
+ /**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately
+ * and emit @ref synthFinished signal when synthesis is completed.
+ * It must also implement the @ref getState method, which must return
+ * psFinished, when synthesis is completed.
+ */
+ virtual void synthText(const QString &text, const QString &suggestedFilename);
+
+ /**
+ * Get the generated audio filename from call to @ref synthText.
+ * @return Name of the audio file the plugin generated.
+ * Null if no such file.
+ *
+ * The plugin must not re-use or delete the filename. The file may not
+ * be locked when this method is called. The file will be deleted when
+ * KTTSD is finished using it.
+ */
+ virtual QString getFilename();
+
+ /**
+ * Stop current operation (saying or synthesizing text).
+ * Important: This function may be called from a thread different from the
+ * one that called sayText or synthText.
+ * If the plugin cannot stop an in-progress @ref sayText or
+ * @ref synthText operation, it must not block waiting for it to complete.
+ * Instead, return immediately.
+ *
+ * If a plugin returns before the operation has actually been stopped,
+ * the plugin must emit the @ref stopped signal when the operation has
+ * actually stopped.
+ *
+ * The plugin should change to the psIdle state after stopping the
+ * operation.
+ */
+ virtual void stopText();
+
+ /**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @see pluginState
+ */
+ virtual pluginState getState();
+
+ /**
+ * Acknowledges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref sayFinished or @ref synthFinished signals when
+ * saying or synthesis is completed.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Returns True if the plugin supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ *
+ * If the plugin returns True, it must also implement the following methods:
+ * - @ref synthText
+ * - @ref getFilename
+ * - @ref ackFinished
+ *
+ * If the plugin returns True, it need not implement @ref sayText .
+ */
+ virtual bool supportsSynth();
+
+ /**
+ * Say or Synthesize text with the given voice code.
+ * @param festivalExePath Path to the Festival executable, or just "festival".
+ * @param text The text to be synthesized.
+ * @param suggestedFilename If not Null, synthesize only to this filename, otherwise
+ * synthesize and audibilize the text.
+ * @param voiceCode Voice code.
+ * @param time Speed percentage. 50 to 200. 200% = 2x normal.
+ * @param pitch Pitch persentage. 50 to 200.
+ * @param volume Volume percentage. 50 to 200.
+ * @param languageCode Language code, for example, "en".
+ */
+ void synth(const QString &festivalExePath, const QString &text,
+ const QString &synthFilename, const QString& voiceCode,
+ int time, int pitch, int volume, const QString &languageCode,
+ QTextCodec* codec);
+
+ /**
+ * Sends commands to Festival to query for a list of supported voice codes.
+ * Fires queryVoicesFinished when completed.
+ * @return False if busy doing something else and therefore cannot
+ * do the query.
+ */
+ bool queryVoices(const QString &festivalExePath);
+
+ /**
+ * Returns the name of an XSLT stylesheet that will convert a valid SSML file
+ * into a format that can be processed by the synth. For example,
+ * The Festival plugin returns a stylesheet that will convert SSML into
+ * SABLE. Any tags the synth cannot handle should be stripped (leaving
+ * their text contents though). The default stylesheet strips all
+ * tags and converts the file to plain text.
+ * @return Name of the XSLT file.
+ */
+ QString getSsmlXsltFilename();
+
+ /**
+ * Whether Festival supports SSML or not.
+ * 0 = Unknown
+ * 1 = Yes
+ * 2 = No
+ */
+ SupportsSSML supportsSSML() { return m_supportsSSML; }
+
+ signals:
+ /**
+ * This signal fires upon completion of a queryVoices operation.
+ * The list of voice codes do not have "voice_" prefix.
+ */
+ void queryVoicesFinished(const QStringList &voiceCodes);
+
+ private slots:
+ void slotProcessExited(KProcess* proc);
+ void slotReceivedStdout(KProcess* proc, char* buffer, int buflen);
+ void slotReceivedStderr(KProcess* proc, char* buffer, int buflen);
+ void slotWroteStdin(KProcess* proc);
+
+ private:
+ /**
+ * Start Festival engine.
+ * @param festivalExePath Path to the Festival executable, or just "festival".
+ * @param voiceCode Voice code in which to speak text.
+ * @param languageCode Language code, for example, "en".
+ */
+ void startEngine(const QString &festivalExePath, const QString &voiceCode,
+ const QString &languageCode, QTextCodec* codec);
+
+ /**
+ * If ready for more output, sends the given text to Festival process, otherwise,
+ * puts it in the queue.
+ * @param text Text to send or queue.
+ */
+ void sendToFestival(const QString& text);
+
+ /**
+ * If Festival is ready for more input and there is more output to send, send it.
+ * To be ready for more input, the Stdin buffer must be empty and the "festival>"
+ * prompt must have been received (m_ready = true).
+ * @return False when Festival is ready for more input
+ * but there is nothing to be sent, or if Festival
+ * has exited.
+ */
+ bool sendIfReady();
+
+ /**
+ * Determine if the text has SABLE tags. If so, we will have to use a different
+ * synthesis method.
+ */
+ bool isSable(const QString &text);
+
+ /**
+ * We attempt to shorten sentences longer than this by replacing commas with periods.
+ */
+ static const int c_tooLong = 600;
+
+ /**
+ * Path to the Festival executable.
+ */
+ QString m_festivalExePath;
+
+ /**
+ * Selected voice (from config).
+ */
+ QString m_voiceCode;
+
+ /**
+ * True if the voice is preloaded. Also used as a flag to supress killing
+ * Festival, since startup time will be excessive.
+ */
+ bool m_preload;
+
+ /**
+ * Selected speed (from config).
+ */
+ int m_time;
+
+ /**
+ * Selected pitch (frequency) (from config).
+ */
+ int m_pitch;
+
+ /**
+ * Selected volume (from config).
+ */
+ int m_volume;
+
+ /**
+ * Running voice.
+ */
+ QString m_runningVoiceCode;
+
+ /**
+ * Running time (speed).
+ */
+ int m_runningTime;
+
+ /**
+ * Running pitch (frequency).
+ */
+ int m_runningPitch;
+
+ /**
+ * Festival process
+ */
+ KProcess* m_festProc;
+
+ /**
+ * Synthesis filename.
+ */
+ QString m_synthFilename;
+
+ /**
+ * True when festival is ready for another input.
+ */
+ volatile bool m_ready;
+
+ /**
+ * Plugin state.
+ */
+ pluginState m_state;
+
+ /**
+ * True when stopText has been called. Used to force transition to psIdle when
+ * Festival exits.
+ */
+ bool m_waitingStop;
+
+ /**
+ * True when queryVoices has been called.
+ */
+ bool m_waitingQueryVoices;
+
+ /**
+ * A queue of outputs to be sent to the Festival process.
+ * Since Festival requires us to wait until the "festival>" prompt before
+ * sending the next command, this queue allows us to queue up multiple
+ * commands and send each one when the ReceivedStdOut signal fires.
+ */
+ QStringList m_outputQueue;
+
+ bool m_writingStdin;
+
+ /**
+ * Language code.
+ */
+ QString m_languageCode;
+
+ /**
+ * Codec.
+ */
+ QTextCodec* m_codec;
+
+ /**
+ * Flag if SSML is supported. Festival cannot support SABLE (and therefore SSML)
+ * unless rab_diphone (British male) is installed. Gawd, I hope Festival folks fix this!
+ */
+ SupportsSSML m_supportsSSML;
+};
+
+#endif // _FESTIVALINTPROC_H_
diff --git a/kttsd/plugins/festivalint/kttsd_festivalintplugin.desktop b/kttsd/plugins/festivalint/kttsd_festivalintplugin.desktop
new file mode 100644
index 0000000..e8776da
--- /dev/null
+++ b/kttsd/plugins/festivalint/kttsd_festivalintplugin.desktop
@@ -0,0 +1,72 @@
+[Desktop Entry]
+Name=Festival Interactive
+Name[da]=Festival Interaktiv
+Name[el]=Διαδραστικό Festival
+Name[eu]=Festival interaktiboa
+Name[fa]=Festival تعاملی
+Name[fi]=Interaktiivinen Festival
+Name[ga]=Festival Idirghníomhach
+Name[gl]=Festival Interactivo
+Name[is]=Festival gagnvirkni
+Name[it]=Festival Interattivo
+Name[ja]=Festival インタラクティブ
+Name[ka]=Festival ინტერაქტიული
+Name[km]=អន្តរ​មុខងារ
+Name[mk]=Интерактивен festival
+Name[ms]=Interaktif Perayaan
+Name[ne]=अन्तरक्रियात्मक फेस्टिभल
+Name[pa]=ਫੈਸੀਟੇਵਲ ਇੰਟਰੇਕਟਵ
+Name[pl]=Festival interaktywny
+Name[pt_BR]=Festival Interativo
+Name[sv]=Festival interaktiv
+Name[ta]=பெஸ்டிவல் உள்செயல்
+Name[tg]=Фестивали Интерактив
+Name[tr]=Etkileşimli Festival
+Name[vi]=Tương tác Festival
+Comment=Festival speech synthetizer
+Comment[bg]=Синтезатор на глас Festival
+Comment[ca]=Sintetitzador de veu Festival
+Comment[cs]=Hlasový syntetizér Festival
+Comment[da]=Festival tale-synthetizer
+Comment[de]=Festival Sprachsynthesizer
+Comment[el]=Συνθέτης ομιλίας Festival
+Comment[es]=Sintetizador de texto a voz Festival
+Comment[et]=Kõnesüntesaator Festival
+Comment[eu]=Festival hizketa-sintetizadorea
+Comment[fa]=ترکیب‌دهندۀ گفتار Festival
+Comment[fi]=Festival puhesyntetisaattori
+Comment[fr]=Synthèse vocale Festival
+Comment[ga]=Sintéiseoir cainte Festival
+Comment[gl]=Sistetizador de voces Festival
+Comment[hu]=Festival beszédszintetizátor
+Comment[is]=Festival talgerfill
+Comment[it]=Sintetizzatore vocale Festival
+Comment[ja]=Festival スピーチシンセサイザ
+Comment[ka]=Festival ხმის სინთეზატორი
+Comment[km]= មុខងារ​កម្មវិធី​សង្គ្រោះ​ការ​និយាយ​
+Comment[mk]=Синтетизатор за говор festival
+Comment[ms]=Pensintesis tutur perayaan
+Comment[nb]=Festival talesyntetisering
+Comment[nds]=Blicksnuut Festival
+Comment[ne]=संवाद सिन्थेसाइजर फेस्टिभल
+Comment[nl]=Festival spraaksynthetizer
+Comment[pa]=ਫੈਸੀਟੇਵਲ ਬੋਲੀ ਸੰਸਲੇਸ਼ਕ
+Comment[pl]=Syntezator mowy Festival
+Comment[pt]=O sintetizador de fala Festival
+Comment[pt_BR]=Sistema de Sintetizador de Fala Festival
+Comment[ru]=Синтезатор речи Festival
+Comment[sk]=Syntetizátor reči Festival
+Comment[sl]=Sintetizator govora Festival
+Comment[sr]=Синтетизатор говора Festival
+Comment[sr@Latn]=Sintetizator govora Festival
+Comment[sv]=Festival talsyntes
+Comment[ta]=பெஸ்டிவல் பேச்சு கூட்டிணைப்பான்
+Comment[tg]=Таҳлилгари овози Festival
+Comment[tr]=Festival konuşma bireştirici
+Comment[uk]=Синтезатор мовлення Festival
+Comment[vi]=Trình tổng hợp tiếng nói Festival
+Comment[zh_TW]=Festival 語音合成器
+Type=Service
+ServiceTypes=KTTSD/SynthPlugin
+X-KDE-Library=libkttsd_festivalintplugin
+X-KDE-Languages=en,en_US,en_GB,en_CA,es,es_mx,cy,de,fi,cs,pl,ru,it,sw,zu,fr_CA,vi
diff --git a/kttsd/plugins/festivalint/sabletowave.scm b/kttsd/plugins/festivalint/sabletowave.scm
new file mode 100644
index 0000000..71293b4
--- /dev/null
+++ b/kttsd/plugins/festivalint/sabletowave.scm
@@ -0,0 +1,92 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-*-mode:scheme-*-
+;; ;;
+;; Centre for Speech Technology Research ;;
+;; University of Edinburgh, UK ;;
+;; Copyright (c) 1996,1997 ;;
+;; All Rights Reserved. ;;
+;; ;;
+;; Permission is hereby granted, free of charge, to use and distribute ;;
+;; this software and its documentation without restriction, including ;;
+;; without limitation the rights to use, copy, modify, merge, publish, ;;
+;; distribute, sublicense, and/or sell copies of this work, and to ;;
+;; permit persons to whom this work is furnished to do so, subject to ;;
+;; the following conditions: ;;
+;; 1. The code must retain the above copyright notice, this list of ;;
+;; conditions and the following disclaimer. ;;
+;; 2. Any modifications must be clearly marked as such. ;;
+;; 3. Original authors' names are not deleted. ;;
+;; 4. The authors' names are not used to endorse or promote products ;;
+;; derived from this software without specific prior written ;;
+;; permission. ;;
+;; ;;
+;; THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK ;;
+;; DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ;;
+;; ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT ;;
+;; SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE ;;
+;; FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ;;
+;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ;;
+;; AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ;;
+;; ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF ;;
+;; THIS SOFTWARE. ;;
+;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Author: Alan W Black
+;;; Date: November 1997
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Adapted from text2wave by Alan Black. Original copyright listed above.
+;;
+;; Copyright 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+;;
+;; This scheme module is used by the Festival Interactive plugin,
+;; which is part of KTTSD. To use,
+;; (load sabletowave.scm)
+;; after starting Festival interactively, then to synth text containing
+;; SABLE tags to a single wave file.
+;; (ktts_sabletowave "sable text" "filename" volume)
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; List of generated intermediate wave files.
+(defvar ktts_wavefiles nil)
+
+(define (ktts_save_record_wave utt)
+"Saves the waveform and records its so it can be joined into a
+a single waveform at the end."
+ (let ((fn (make_tmp_filename)))
+ (utt.save.wave utt fn)
+ (set! ktts_wavefiles (cons fn ktts_wavefiles))
+ utt))
+
+(define (ktts_combine_waves outfile volume)
+ "Join all the waves together into the desired output file
+and delete the intermediate ones."
+ (let ((wholeutt (utt.synth (Utterance Text ""))))
+ (mapcar
+ (lambda (d)
+ (utt.import.wave wholeutt d t)
+ (delete-file d))
+ (reverse ktts_wavefiles))
+;; (if ktts_frequency
+;; (utt.wave.resample wholeutt (parse-number ktts_frequency)))
+ (if (not (equal? volume "1.0"))
+ (begin
+ (utt.wave.rescale wholeutt (parse-number volume))))
+ (utt.save.wave wholeutt outfile 'riff)
+ ))
+
+;;;
+;;; Redefine what happens to utterances during text to speech.
+;;; Synthesize each utterance and save to a temporary wave file.
+;;;
+(set! tts_hooks (list utt.synth ktts_save_record_wave))
+
+(define (ktts_sabletowave text filename volume)
+ (set! ktts_wavefiles nil)
+ ;; Do the synthesis, which creates multiple wave files.
+ (tts_text text 'sable)
+ ;; Now put the waveforms together and adjust volume.
+ (ktts_combine_waves filename volume)
+)
diff --git a/kttsd/plugins/festivalint/voices b/kttsd/plugins/festivalint/voices
new file mode 100644
index 0000000..f6c0d58
--- /dev/null
+++ b/kttsd/plugins/festivalint/voices
@@ -0,0 +1,738 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<voices>
+
+<voice>
+ <code>kal_diphone</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Male</name>
+</voice>
+
+<voice>
+ <code>ked_diphone</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Male</name>
+</voice>
+
+<voice>
+ <code>us1_mbrola</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Female, MBROLA</name>
+</voice>
+
+<voice>
+ <code>us2_mbrola</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Male, MBROLA</name>
+</voice>
+
+<voice>
+ <code>us3_mbrola</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Male, MBROLA</name>
+</voice>
+
+<voice>
+ <code>don_diphone</code>
+ <language>en_GB</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>British Male</name>
+</voice>
+
+<voice>
+ <code>rab_diphone</code>
+ <language>en_GB</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>British Male</name>
+</voice>
+
+<voice>
+ <code>el_diphone</code>
+ <language>es</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Castilian Spanish Male</name>
+</voice>
+
+<voice>
+ <code>cmu_us_bdl_arctic_hts</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>American Male, HTS</name>
+</voice>
+
+<voice>
+ <code>cmu_us_slt_arctic_hts</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>American Female, HTS</name>
+</voice>
+
+<voice>
+ <code>cmu_us_jmk_arctic_hts</code>
+ <language>en_CA</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Canadian English Male, HTS</name>
+</voice>
+
+<voice>
+ <code>cmu_us_awb_arctic_hts</code>
+ <language>en_GB</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Scottish Male, HTS</name>
+</voice>
+
+<voice>
+ <code>cmu_us_kal_com_hts</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>American Male, HTS</name>
+</voice>
+
+<voice>
+ <code>cstr_us_ked_timit_hts</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>American Male, HTS</name>
+</voice>
+
+<voice>
+ <code>cstr_us_jmk_arctic_multisyn</code>
+ <language>en_CA</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>true</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>false</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Canadian English Male, MultiSyn</name>
+</voice>
+
+<voice>
+ <code>cstr_us_awb_arctic_multisyn</code>
+ <language>en_GB</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>true</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>false</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Scottish Male, MultiSyn</name>
+</voice>
+
+<voice>
+ <code>german_de1_os</code>
+ <language>de</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>German Female, Festival</name>
+</voice>
+
+<voice>
+ <code>german_de2_os</code>
+ <language>de</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>German Male, Festival</name>
+</voice>
+
+<voice>
+ <code>german_de3_os</code>
+ <language>de</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>German Female, Festival</name>
+</voice>
+
+<voice>
+ <code>abc_diphone</code>
+ <language>es</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>Mexican Spanish Male, OGC</name>
+</voice>
+
+<voice>
+ <code>hvs_diphone</code>
+ <language>es</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>Mexican Spanish Female, OGC</name>
+</voice>
+
+<voice>
+ <code>mwm_diphone</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Male, OGC</name>
+</voice>
+
+<voice>
+ <code>aec_diphone</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Male, OGC</name>
+</voice>
+
+<voice>
+ <code>jph_diphone</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Male, OGC</name>
+</voice>
+
+<voice>
+ <code>tll_diphone</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Female, OGC</name>
+</voice>
+
+<voice>
+ <code>ogirab_diphone</code>
+ <language>en_UK</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>British Male, OGC</name>
+</voice>
+
+<voice>
+ <code>mwm2jph_diphone</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Male, OGC</name>
+</voice>
+
+<voice>
+ <code>mwm2tll_diphone</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>American Female, OGC</name>
+</voice>
+
+<voice>
+ <code>hy_fi_mv_diphone</code>
+ <language>fi</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Finnish Male</name>
+</voice>
+
+<voice>
+ <code>czech_mbrola_cz2</code>
+ <language>cs_CZ</language>
+ <codec>ISO 8859-2</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Czech Male, MBROLA</name>
+</voice>
+
+<voice>
+ <code>cstr_pl_em_diphone</code>
+ <language>pl</language>
+ <codec>ISO 8859-2</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>true</pitch-adjustable>
+ <name>Polish Male</name>
+</voice>
+
+<voice>
+ <code>msu_ru_nsh_diphone</code>
+ <language>ru</language>
+ <codec>KOI8-R</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Russian Male</name>
+</voice>
+
+<voice>
+ <code>pc_diphone</code>
+ <language>it</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Italian Male</name>
+</voice>
+
+<voice>
+ <code>lp_diphone</code>
+ <language>it</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Italian Female</name>
+</voice>
+
+<voice>
+ <code>lp_mbrola</code>
+ <language>it</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Italian Female</name>
+</voice>
+
+<voice>
+ <code>pc_mbrola</code>
+ <language>it</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Italian Male</name>
+</voice>
+
+<voice>
+ <code>pc_ogi_diphone</code>
+ <language>it</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Italian Male</name>
+</voice>
+
+<voice>
+ <code>lp_ogi_diphone</code>
+ <language>it</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Italian Female</name>
+</voice>
+
+<voice>
+ <code>UON_swahili_kw_multisyn</code>
+ <language>sw</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>true</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>false</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Kiswahili Male</name>
+</voice>
+
+<voice>
+ <code>uyo_ibibio_eno_multisyn</code>
+ <!-- There is no iso 639 (two-letter) code for ibibio. We use Zulu here.
+ The iso 639-2 (three-letter) code is nic (Niger-Kordofanian) -->
+ <language>zu</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>true</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>false</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Ibibio Female</name>
+</voice>
+
+<voice>
+ <code>csir_isizulu_buhle_multisyn</code>
+ <language>zu</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>true</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>false</rate-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Zulu Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_david</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_diane</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Female</name>
+</voice>
+
+<voice>
+ <code>cepstral_william</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_amy</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Female</name>
+</voice>
+
+<voice>
+ <code>cepstral_frank</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_emily</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Female</name>
+</voice>
+
+<voice>
+ <code>cepstral_duncan</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_linda</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Female</name>
+</voice>
+
+<voice>
+ <code>cepstral_robin</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Female</name>
+</voice>
+
+<voice>
+ <code>cepstral_walter</code>
+ <language>en_US</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>American Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_lawrence</code>
+ <language>en_UK</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>British Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_millie</code>
+ <language>en_UK</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>British Female</name>
+</voice>
+
+<voice>
+ <code>cepstral_jean-pierre</code>
+ <language>fr_CA</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>French Canadian Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_isabelle</code>
+ <language>fr_CA</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>French Canadian Female</name>
+</voice>
+
+<voice>
+ <code>cepstral_matthias</code>
+ <language>de</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>German Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_katrin</code>
+ <language>de</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>German Female</name>
+</voice>
+
+<voice>
+ <code>cepstral_miguel</code>
+ <language>es</language>
+ <codec>ISO 8859-1</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>Americas Spanish Male</name>
+</voice>
+
+<voice>
+ <code>cepstral_marta</code>
+ <language>es</language>
+ <codec>ISO 8859-1</codec>
+ <gender>female</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <rate-adjustable>true</rate-adjustable>
+ <pitch-adjustable>false/</pitch-adjustable>
+ <name>Americas Spanish Female</name>
+</voice>
+
+<voice>
+ <code>wow_vi_ptn_diphone</code>
+ <language>vi</language>
+ <codec>UTF-8</codec>
+ <gender>male</gender>
+ <preload>false</preload>
+ <volume-adjustable>true</volume-adjustable>
+ <speed-adjustable>true></speed-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Vietnamese Male</name>
+</voice>
+
+<voice>
+ <code>wow_vi_liz_diphone</code>
+ <language>vi</language>
+ <codec>UTF-8</codec>
+ <gender>female</gender>
+ <volume-adjustable>true</volume-adjustable>
+ <speed-adjustable>true</speed-adjustable>
+ <pitch-adjustable>false</pitch-adjustable>
+ <name>Vietnamese Female</name>
+</voice>
+
+</voices>
diff --git a/kttsd/plugins/flite/Makefile.am b/kttsd/plugins/flite/Makefile.am
new file mode 100644
index 0000000..c451be3
--- /dev/null
+++ b/kttsd/plugins/flite/Makefile.am
@@ -0,0 +1,20 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_fliteplugin.la
+
+libkttsd_fliteplugin_la_SOURCES = \
+ fliteconfwidget.ui \
+ fliteconf.cpp \
+ fliteproc.cpp \
+ fliteplugin.cpp
+libkttsd_fliteplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_fliteplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_fliteplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+noinst_HEADERS = fliteproc.h fliteconf.h fliteconfwidget.h
diff --git a/kttsd/plugins/flite/README b/kttsd/plugins/flite/README
new file mode 100644
index 0000000..1bff55b
--- /dev/null
+++ b/kttsd/plugins/flite/README
@@ -0,0 +1,3 @@
+This is the directory containing the Festival Lite plug in.
+This plug in is developed and maintained by Gary Cramblitt.
+<garycramblitt@comcast.net>
diff --git a/kttsd/plugins/flite/configure.in.bot b/kttsd/plugins/flite/configure.in.bot
new file mode 100644
index 0000000..54bd84e
--- /dev/null
+++ b/kttsd/plugins/flite/configure.in.bot
@@ -0,0 +1,15 @@
+if test "x$flite_bindir" = "xno"; then
+ if test "$compile_flite_plugin" = "yes"; then
+ echo ""
+ echo "======================================================="
+ echo "The Festival Lite (flite) program does not appear to be"
+ echo "installed on this system. The Flite plugin will"
+ echo "be built, but you need to install Flite before you"
+ echo "can use it. You can get it at"
+ echo " http://www.speech.cs.cmu.edu/flite/index.html"
+ echo "Debian users: apt-get install flite"
+ echo "======================================================"
+ all_tests=bad
+ fi
+fi
+
diff --git a/kttsd/plugins/flite/configure.in.in b/kttsd/plugins/flite/configure.in.in
new file mode 100644
index 0000000..f9b222f
--- /dev/null
+++ b/kttsd/plugins/flite/configure.in.in
@@ -0,0 +1,22 @@
+dnl =========================================
+dnl checks for Festival Lite (Flite) Plug In
+dnl =========================================
+
+AC_ARG_ENABLE(kttsd-flite,
+ AC_HELP_STRING([--enable-kttsd-flite],
+ [build KTTSD Festival Lite (flite) [default=yes]]),
+ flite_plugin=$enableval,
+ flite_plugin=yes)
+
+compile_flite_plugin="yes"
+
+if test "x$flite_plugin" = "xno"; then
+ compile_flite_plugin="no"
+fi
+
+dnl Check for flite executable.
+dnl Note that flite plugin is always built, unless
+dnl user overrides on configure command line.
+AC_PATH_PROG(flite_bindir, "flite", "no")
+
+AM_CONDITIONAL(include_kttsd_flite, test "x$compile_flite_plugin" != "xno")
diff --git a/kttsd/plugins/flite/fliteconf.cpp b/kttsd/plugins/flite/fliteconf.cpp
new file mode 100644
index 0000000..cbc4b2d
--- /dev/null
+++ b/kttsd/plugins/flite/fliteconf.cpp
@@ -0,0 +1,199 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Configuration widget and functions for Festival (Interactive) plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qlayout.h>
+#include <qfile.h>
+#include <qapplication.h>
+
+// KDE includes.
+#include <klocale.h>
+#include <kdialog.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+
+// KTTS includes.
+#include <testplayer.h>
+
+// Flite Plugin includes.
+#include "fliteproc.h"
+#include "fliteconf.h"
+#include "fliteconf.moc"
+
+/** Constructor */
+FliteConf::FliteConf( QWidget* parent, const char* name, const QStringList& /*args*/) :
+ PlugInConf(parent, name)
+{
+ // kdDebug() << "FliteConf::FliteConf: Running" << endl;
+ m_fliteProc = 0;
+ m_progressDlg = 0;
+
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "FliteConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new FliteConfWidget(this, "FliteConfigWidget");
+ layout->addWidget(m_widget);
+
+ defaults();
+
+ connect(m_widget->flitePath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->fliteTest, SIGNAL(clicked()), this, SLOT(slotFliteTest_clicked()));
+}
+
+/** Destructor */
+FliteConf::~FliteConf(){
+ // kdDebug() << "Running: FliteConf::~FliteConf()" << endl;
+ if (!m_waveFile.isNull()) QFile::remove(m_waveFile);
+ delete m_fliteProc;
+ delete m_progressDlg;
+}
+
+void FliteConf::load(KConfig *config, const QString &configGroup){
+ // kdDebug() << "FliteConf::load: Loading configuration for language " << langGroup << " with plug in " << "Festival Lite (flite)" << endl;
+
+ config->setGroup(configGroup);
+ QString fliteExe = config->readEntry("FliteExePath", QString::null);
+ if (fliteExe.isEmpty())
+ {
+ config->setGroup("Flite");
+ fliteExe = config->readEntry("FliteExePath", "flite");
+ }
+ m_widget->flitePath->setURL(fliteExe);
+}
+
+void FliteConf::save(KConfig *config, const QString &configGroup){
+ // kdDebug() << "FliteConf::save: Saving configuration for language " << langGroup << " with plug in " << "Festival Lite (flite)" << endl;
+
+ config->setGroup("Flite");
+ config->writeEntry("FliteExePath",
+ realFilePath(m_widget->flitePath->url()));
+ config->setGroup(configGroup);
+ config->writeEntry("FliteExePath",
+ realFilePath(m_widget->flitePath->url()));
+}
+
+void FliteConf::defaults(){
+ // kdDebug() << "FliteConf::defaults: Running" << endl;
+ m_widget->flitePath->setURL("flite");
+}
+
+void FliteConf::setDesiredLanguage(const QString &lang)
+{
+ m_languageCode = lang;
+}
+
+QString FliteConf::getTalkerCode()
+{
+ QString fliteExe = realFilePath(m_widget->flitePath->url());
+ if (!fliteExe.isEmpty())
+ {
+ if (!getLocation(fliteExe).isEmpty())
+ {
+ return QString(
+ "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />"
+ "<prosody volume=\"%4\" rate=\"%5\" />"
+ "<kttsd synthesizer=\"%6\" />")
+ .arg(m_languageCode)
+ .arg("fixed")
+ .arg("neutral")
+ .arg("medium")
+ .arg("medium")
+ .arg("Festival Lite (flite)");
+ }
+ }
+ return QString::null;
+}
+
+void FliteConf::slotFliteTest_clicked()
+{
+ // kdDebug() << "FliteConf::slotFliteTest_clicked(): Running" << endl;
+ // If currently synthesizing, stop it.
+ if (m_fliteProc)
+ m_fliteProc->stopText();
+ else
+ {
+ m_fliteProc = new FliteProc();
+ connect (m_fliteProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
+ }
+ // Create a temp file name for the wave file.
+ KTempFile tempFile (locateLocal("tmp", "fliteplugin-"), ".wav");
+ QString tmpWaveFile = tempFile.file()->name();
+ tempFile.close();
+
+ // Get test message in the language of the voice.
+ QString testMsg = testMessage(m_languageCode);
+
+ // Tell user to wait.
+ m_progressDlg = new KProgressDialog(m_widget, "kttsmgr_flite_testdlg",
+ i18n("Testing"),
+ i18n("Testing."),
+ true);
+ m_progressDlg->progressBar()->hide();
+ m_progressDlg->setAllowCancel(true);
+
+ // Play an English test. Flite only supports English.
+ connect (m_fliteProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ m_fliteProc->synth(
+ testMsg,
+ tmpWaveFile,
+ realFilePath(m_widget->flitePath->url()));
+
+ // Display progress dialog modally. Processing continues when plugin signals synthFinished,
+ // or if user clicks Cancel button.
+ m_progressDlg->exec();
+ disconnect (m_fliteProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ if (m_progressDlg->wasCancelled()) m_fliteProc->stopText();
+ delete m_progressDlg;
+ m_progressDlg = 0;
+}
+
+void FliteConf::slotSynthFinished()
+{
+ // If user canceled, progress dialog is gone, so exit.
+ if (!m_progressDlg)
+ {
+ m_fliteProc->ackFinished();
+ return;
+ }
+ // Hide the Cancel button so user can't cancel in the middle of playback.
+ m_progressDlg->showCancelButton(false);
+ // Get new wavefile name.
+ m_waveFile = m_fliteProc->getFilename();
+ // Tell synth we're done.
+ m_fliteProc->ackFinished();
+ // Play the wave file (possibly adjusting its Speed).
+ // Player object deletes the wave file when done.
+ if (m_player) m_player->play(m_waveFile);
+ QFile::remove(m_waveFile);
+ m_waveFile = QString::null;
+ if (m_progressDlg) m_progressDlg->close();
+}
+
+void FliteConf::slotSynthStopped()
+{
+ // Clean up after canceling test.
+ QString filename = m_fliteProc->getFilename();
+ if (!filename.isNull()) QFile::remove(filename);
+}
diff --git a/kttsd/plugins/flite/fliteconf.h b/kttsd/plugins/flite/fliteconf.h
new file mode 100644
index 0000000..aa26c7b
--- /dev/null
+++ b/kttsd/plugins/flite/fliteconf.h
@@ -0,0 +1,124 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Configuration widget and functions for Festival (Interactive) plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _FLITECONF_H_
+#define _FLITECONF_H_
+
+// Qt includes.
+#include <qstring.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include <pluginconf.h>
+
+// Flite plugin includes.
+#include "fliteconfwidget.h"
+
+class FliteProc;
+class KProgressDialog;
+
+class FliteConf : public PlugInConf {
+ Q_OBJECT
+
+ public:
+ /** Constructor */
+ FliteConf( QWidget* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /** Destructor */
+ ~FliteConf();
+
+ /** This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. NOTE that this is not called after the modules is loaded,
+ * so you probably want to call this method in the constructor.
+ */
+ void load(KConfig *config, const QString &configGroup);
+
+ /** This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok".
+ */
+ void save(KConfig *config, const QString &configGroup);
+
+ /** This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file.
+ */
+ void defaults();
+
+ /**
+ * This function informs the plugin of the desired language to be spoken
+ * by the plugin. The plugin should attempt to adapt itself to the
+ * specified language code, choosing sensible defaults if necessary.
+ * If the passed-in code is QString::null, no specific language has
+ * been chosen.
+ * @param lang The desired language code or Null if none.
+ *
+ * If the plugin is unable to support the desired language, that is OK.
+ * Language codes are given by ISO 639-1 and are in lowercase.
+ * The code may also include an ISO 3166 country code in uppercase
+ * separated from the language code by underscore (_). For
+ * example, en_GB. If your plugin supports the given language, but
+ * not the given country, treat it as though the country
+ * code were not specified, i.e., adapt to the given language.
+ */
+ void setDesiredLanguage(const QString &lang);
+
+ /**
+ * Return fully-specified talker code for the configured plugin. This code
+ * uniquely identifies the configured instance of the plugin and distinquishes
+ * one instance from another. If the plugin has not been fully configured,
+ * i.e., cannot yet synthesize, return QString::null.
+ * @return Fully-specified talker code.
+ */
+ QString getTalkerCode();
+
+ private slots:
+ void configChanged(){
+ // kdDebug() << "FliteConf::configChanged: Running" << endl;
+ emit changed(true);
+ };
+ void slotFliteTest_clicked();
+ void slotSynthFinished();
+ void slotSynthStopped();
+
+ private:
+ // Language code.
+ QString m_languageCode;
+ // Configuration Widget.
+ FliteConfWidget* m_widget;
+ // Flite synthesizer.
+ FliteProc* m_fliteProc;
+ // Synthesized wave file name.
+ QString m_waveFile;
+ // Progress dialog.
+ KProgressDialog* m_progressDlg;
+};
+#endif // _FLITECONF_H_
diff --git a/kttsd/plugins/flite/fliteconfwidget.ui b/kttsd/plugins/flite/fliteconfwidget.ui
new file mode 100644
index 0000000..839970e
--- /dev/null
+++ b/kttsd/plugins/flite/fliteconfwidget.ui
@@ -0,0 +1,186 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>FliteConfWidget</class>
+<author>Gary Cramblitt</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>FliteConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>559</width>
+ <height>233</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Flite Config UI</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the configuration dialog for the Festival Lite (Flite) speech synthesis engine.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>100</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>fliteConfigurationBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Festival &amp;Lite (flite) Configuration</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the configuration dialog for the Festival Lite (Flite) speech synthesis engine.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>flitePathBox</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>flitePathLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Flite executable path:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>flitePath</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If Flite is in your PATH environment variable, simply enter "flite", otherwise specify the complete path to the Flite executable program.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>flitePath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="url" stdset="0">
+ <string>flite</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If Flite is in your PATH environment variable, simply enter "flite", otherwise specify the complete path to the Flite executable program.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>fliteTest</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Test</string>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>221</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<includes>
+ <include location="global" impldecl="in declaration">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/plugins/flite/fliteplugin.cpp b/kttsd/plugins/flite/fliteplugin.cpp
new file mode 100644
index 0000000..602b5bb
--- /dev/null
+++ b/kttsd/plugins/flite/fliteplugin.cpp
@@ -0,0 +1,31 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so festival lite (flite) can be used as plug in.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "fliteconf.h"
+#include "fliteproc.h"
+
+typedef K_TYPELIST_2( FliteProc, FliteConf ) Flite;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_fliteplugin, KGenericFactory<Flite>("kttsd_flite") )
+
diff --git a/kttsd/plugins/flite/fliteproc.cpp b/kttsd/plugins/flite/fliteproc.cpp
new file mode 100644
index 0000000..54b15e3
--- /dev/null
+++ b/kttsd/plugins/flite/fliteproc.cpp
@@ -0,0 +1,281 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Main speaking functions for the Festival Lite (Flite) Plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qstring.h>
+#include <qstringlist.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+
+// Flite Plugin includes.
+#include "fliteproc.h"
+#include "fliteproc.moc"
+
+/** Constructor */
+FliteProc::FliteProc( QObject* parent, const char* name, const QStringList& ) :
+ PlugInProc( parent, name ){
+ kdDebug() << "FliteProc::FliteProc: Running" << endl;
+ m_state = psIdle;
+ m_waitingStop = false;
+ m_fliteProc = 0;
+}
+
+/** Destructor */
+FliteProc::~FliteProc(){
+ kdDebug() << "FliteProc::~FliteProc:: Running" << endl;
+ if (m_fliteProc)
+ {
+ stopText();
+ delete m_fliteProc;
+ }
+}
+
+/** Initialize the speech */
+bool FliteProc::init(KConfig* config, const QString& configGroup){
+ // kdDebug() << "Running: FliteProc::init(const QString &lang)" << endl;
+ // kdDebug() << "Initializing plug in: Flite" << endl;
+ // Retrieve path to flite executable.
+ config->setGroup(configGroup);
+ m_fliteExePath = config->readEntry("FliteExePath", "flite");
+ kdDebug() << "FliteProc::init: path to flite: " << m_fliteExePath << endl;
+ return true;
+}
+
+/**
+* Say a text. Synthesize and audibilize it.
+* @param text The text to be spoken.
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void FliteProc::sayText(const QString &text)
+{
+ synth(text, QString::null, m_fliteExePath);
+}
+
+/**
+* Synthesize text into an audio file, but do not send to the audio device.
+* @param text The text to be synthesized.
+* @param suggestedFilename Full pathname of file to create. The plugin
+* may ignore this parameter and choose its own
+* filename. KTTSD will query the generated
+* filename using getFilename().
+*
+* If the plugin supports asynchronous operation, it should return immediately.
+*/
+void FliteProc::synthText(const QString& text, const QString& suggestedFilename)
+{
+ synth(text, suggestedFilename, m_fliteExePath);
+}
+
+/**
+* Say or Synthesize text.
+* @param text The text to be synthesized.
+* @param suggestedFilename If not Null, synthesize only to this filename, otherwise
+* synthesize and audibilize the text.
+*/
+void FliteProc::synth(
+ const QString &text,
+ const QString &synthFilename,
+ const QString& fliteExePath)
+{
+ // kdDebug() << "Running: FliteProc::synth(const QString &text)" << endl;
+
+ if (m_fliteProc)
+ {
+ if (m_fliteProc->isRunning()) m_fliteProc->kill();
+ delete m_fliteProc;
+ m_fliteProc = 0;
+ }
+ // kdDebug()<< "FliteProc::synth: Creating Flite object" << endl;
+ m_fliteProc = new KProcess;
+ connect(m_fliteProc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*)));
+ connect(m_fliteProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStdout(KProcess*, char*, int)));
+ connect(m_fliteProc, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStderr(KProcess*, char*, int)));
+ connect(m_fliteProc, SIGNAL(wroteStdin(KProcess*)),
+ this, SLOT(slotWroteStdin(KProcess* )));
+ if (synthFilename.isNull())
+ m_state = psSaying;
+ else
+ m_state = psSynthing;
+
+
+ // Encode quotation characters.
+ QString saidText = text;
+/*
+ saidText.replace("\\\"", "#!#!");
+ saidText.replace("\"", "\\\"");
+ saidText.replace("#!#!", "\\\"");
+ // Remove certain comment characters.
+ saidText.replace("--", "");
+ saidText = "\"" + saidText + "\"";
+*/
+ saidText += "\n";
+
+ *m_fliteProc << fliteExePath;
+// *m_fliteProc << "-t" << saidText;
+ if (!synthFilename.isNull()) *m_fliteProc << "-o" << synthFilename;
+
+ // Ok, let's rock.
+ m_synthFilename = synthFilename;
+ kdDebug() << "FliteProc::synth: Synthing text: '" << saidText << "' using Flite plug in" << endl;
+ if (!m_fliteProc->start(KProcess::NotifyOnExit, KProcess::All))
+ {
+ kdDebug() << "FliteProc::synth: Error starting Flite process. Is flite in the PATH?" << endl;
+ m_state = psIdle;
+ return;
+ }
+ kdDebug()<< "FliteProc:synth: Flite initialized" << endl;
+ m_fliteProc->writeStdin(saidText.latin1(), saidText.length());
+}
+
+/**
+* Get the generated audio filename from synthText.
+* @return Name of the audio file the plugin generated.
+* Null if no such file.
+*
+* The plugin must not re-use the filename.
+*/
+QString FliteProc::getFilename()
+{
+ kdDebug() << "FliteProc::getFilename: returning " << m_synthFilename << endl;
+ return m_synthFilename;
+}
+
+/**
+* Stop current operation (saying or synthesizing text).
+* Important: This function may be called from a thread different from the
+* one that called sayText or synthText.
+* If the plugin cannot stop an in-progress @ref sayText or
+* @ref synthText operation, it must not block waiting for it to complete.
+* Instead, return immediately.
+*
+* If a plugin returns before the operation has actually been stopped,
+* the plugin must emit the @ref stopped signal when the operation has
+* actually stopped.
+*
+* The plugin should change to the psIdle state after stopping the
+* operation.
+*/
+void FliteProc::stopText(){
+ kdDebug() << "FliteProc::stopText:: Running" << endl;
+ if (m_fliteProc)
+ {
+ if (m_fliteProc->isRunning())
+ {
+ kdDebug() << "FliteProc::stopText: killing Flite." << endl;
+ m_waitingStop = true;
+ m_fliteProc->kill();
+ } else m_state = psIdle;
+ }else m_state = psIdle;
+ kdDebug() << "FliteProc::stopText: Flite stopped." << endl;
+}
+
+void FliteProc::slotProcessExited(KProcess*)
+{
+ kdDebug() << "FliteProc:slotProcessExited: Flite process has exited." << endl;
+ pluginState prevState = m_state;
+ if (m_waitingStop)
+ {
+ m_waitingStop = false;
+ m_state = psIdle;
+ emit stopped();
+ } else {
+ m_state = psFinished;
+ if (prevState == psSaying)
+ emit sayFinished();
+ else
+ if (prevState == psSynthing)
+ emit synthFinished();
+ }
+}
+
+void FliteProc::slotReceivedStdout(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "FliteProc::slotReceivedStdout: Received output from Flite: " << buf << endl;
+}
+
+void FliteProc::slotReceivedStderr(KProcess*, char* buffer, int buflen)
+{
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "FliteProc::slotReceivedStderr: Received error from Flite: " << buf << endl;
+}
+
+void FliteProc::slotWroteStdin(KProcess*)
+{
+ kdDebug() << "FliteProc::slotWroteStdin: closing Stdin" << endl;
+ m_fliteProc->closeStdin();
+}
+
+/**
+* Return the current state of the plugin.
+* This function only makes sense in asynchronous mode.
+* @return The pluginState of the plugin.
+*
+* @see pluginState
+*/
+pluginState FliteProc::getState() { return m_state; }
+
+/**
+* Acknowledges a finished state and resets the plugin state to psIdle.
+*
+* If the plugin is not in state psFinished, nothing happens.
+* The plugin may use this call to do any post-processing cleanup,
+* for example, blanking the stored filename (but do not delete the file).
+* Calling program should call getFilename prior to ackFinished.
+*/
+void FliteProc::ackFinished()
+{
+ if (m_state == psFinished)
+ {
+ m_state = psIdle;
+ m_synthFilename = QString::null;
+ }
+}
+
+/**
+* Returns True if the plugin supports asynchronous processing,
+* i.e., returns immediately from sayText or synthText.
+* @return True if this plugin supports asynchronous processing.
+*
+* If the plugin returns True, it must also implement @ref getState .
+* It must also emit @ref sayFinished or @ref synthFinished signals when
+* saying or synthesis is completed.
+*/
+bool FliteProc::supportsAsync() { return true; }
+
+/**
+* Returns True if the plugin supports synthText method,
+* i.e., is able to synthesize text to a sound file without
+* audibilizing the text.
+* @return True if this plugin supports synthText method.
+*/
+bool FliteProc::supportsSynth() { return true; }
+
diff --git a/kttsd/plugins/flite/fliteproc.h b/kttsd/plugins/flite/fliteproc.h
new file mode 100644
index 0000000..7737b3a
--- /dev/null
+++ b/kttsd/plugins/flite/fliteproc.h
@@ -0,0 +1,187 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Main speaking functions for the Festival Lite (Flite) Plug in
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _FLITEPROC_H_
+#define _FLITEPROC_H_
+
+// Qt includes.
+#include <qstringlist.h>
+#include <qmutex.h>
+
+// KTTS includes.
+#include <pluginproc.h>
+
+class KProcess;
+
+class FliteProc : public PlugInProc{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ FliteProc( QObject* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /**
+ * Destructor
+ */
+ virtual ~FliteProc();
+
+ /**
+ * Initializate the speech engine.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Say a text string.
+ * @param text The text to speak.
+ */
+ virtual void sayText(const QString &text);
+
+ /**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately.
+ */
+ virtual void synthText(const QString& text, const QString& suggestedFilename);
+
+ /**
+ * Get the generated audio filename from synthText.
+ * @return Name of the audio file the plugin generated.
+ * Null if no such file.
+ *
+ * The plugin must not re-use the filename.
+ */
+ virtual QString getFilename();
+
+ /**
+ * Stop current operation (saying or synthesizing text).
+ * Important: This function may be called from a thread different from the
+ * one that called sayText or synthText.
+ * If the plugin cannot stop an in-progress @ref sayText or
+ * @ref synthText operation, it must not block waiting for it to complete.
+ * Instead, return immediately.
+ *
+ * If a plugin returns before the operation has actually been stopped,
+ * the plugin must emit the @ref stopped signal when the operation has
+ * actually stopped.
+ *
+ * The plugin should change to the psIdle state after stopping the
+ * operation.
+ */
+ virtual void stopText();
+
+ /**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @see pluginState
+ */
+ virtual pluginState getState();
+
+ /**
+ * Acknowledges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref sayFinished or @ref synthFinished signals when
+ * saying or synthesis is completed.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Returns True if the plugin supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ */
+ virtual bool supportsSynth();
+
+ /**
+ * Say or Synthesize text.
+ * @param text The text to be synthesized.
+ * @param synthFilename If not Null, synthesize only to this filename, otherwise
+ * synthesize and audibilize the text.
+ * @param fliteExePath Path to the flite executable.
+ */
+ void synth(
+ const QString &text,
+ const QString &synthFilename,
+ const QString &fliteExePath);
+
+ private slots:
+ void slotProcessExited(KProcess* proc);
+ void slotReceivedStdout(KProcess* proc, char* buffer, int buflen);
+ void slotReceivedStderr(KProcess* proc, char* buffer, int buflen);
+ void slotWroteStdin(KProcess* proc);
+
+ private:
+
+ /**
+ * Path to flite executable (from config).
+ */
+ QString m_fliteExePath;
+
+ /**
+ * Flite process
+ */
+ KProcess* m_fliteProc;
+
+ /**
+ * Synthesis filename.
+ */
+ QString m_synthFilename;
+
+ /**
+ * Plugin state.
+ */
+ pluginState m_state;
+
+ /**
+ * True when stopText has been called. Used to force transition to psIdle when
+ * Flite exits.
+ */
+ bool m_waitingStop;
+
+};
+
+#endif // _FLITEPROC_H_
diff --git a/kttsd/plugins/flite/kttsd_fliteplugin.desktop b/kttsd/plugins/flite/kttsd_fliteplugin.desktop
new file mode 100644
index 0000000..2105253
--- /dev/null
+++ b/kttsd/plugins/flite/kttsd_fliteplugin.desktop
@@ -0,0 +1,59 @@
+[Desktop Entry]
+Name=Festival Lite (flite)
+Name[el]=Festival ελαφρύ (flite)
+Name[fi]=Festival Lite (kevytversio)
+Name[ka]=Festival მსუბუქი (flite)
+Name[km]=មុខងារ Lite (flite)
+Name[nds]=Festival Lite (FLite)
+Name[ne]=फेस्टिभल लाइट (एफ लाईट)
+Name[pt_BR]=Festival Lite
+Name[ta]=பெஸ்டிவல் லைட் (flite)
+Name[tr]=Festival Lite(flite)
+Name[zh_TW]=Festival Lite (flite)4
+Comment=Festival Lite (flite) speech synthesizer
+Comment[bg]=Олекотен синтезатор на глас Festival Lite
+Comment[ca]=Sintetitzador de veu Festival Lite (flite)
+Comment[cs]=Hlasový syntetizér Festival Lite (flite)
+Comment[da]=Festival Lite (flite) tale-synthesizer
+Comment[de]=Festival Lite (flite) Sprachsynthesizer
+Comment[el]=Συνθέτης ομιλίας Festival ελαφρύ (flite)
+Comment[es]=Sintetizador de texto a voz Festival (flite)
+Comment[et]=Kõnesüntesaator Festival lite (flite)
+Comment[eu]=Festival Lite (flite) hizketa-sintetizadorea
+Comment[fa]=ترکیب‌دهندۀ گفتار Festival Lite (flite)
+Comment[fi]=Festival Lite (kevytversio) puhesyntetisaattori
+Comment[fr]=Synthèse vocale Festival Lite (flite)
+Comment[ga]=Sintéiseoir cainte Festival Lite (flite)
+Comment[gl]=Sintetizador de voces Festival Lite (flite)
+Comment[hu]=Festival Lite (flite) beszédszintetizátor
+Comment[is]=Festival Lite (flite) talgerfill
+Comment[it]=Sintetizzatore vocale Festival Lite (flite)
+Comment[ja]=Festival Lite (flite) スピーチシンセサイザ
+Comment[ka]=Festival მარტივი (flite) ხმის სინთეზატორი
+Comment[km]=មុខងារ​កម្មវិធី​សង្គ្រោះ​ការនិយាយ Lite (flite)
+Comment[mk]=Festival Lite (flite) синтетизатор на говор
+Comment[ms]=Pensintesis tutur Festival Lite (flite)
+Comment[nb]=Festival Lite (flite) talesyntetisering
+Comment[nds]=Blicksnuut Festival lite (FLite)
+Comment[ne]=फेस्टिभल लाइट (एफ लाइट) संवाद सिन्थेसाइजर
+Comment[nl]=Festival Lite (flite) spraaksynthesizer
+Comment[pa]=Festival Lite (flite) ਬੋਲੀ ਸੰਸਲੇਸ਼ਕ
+Comment[pl]=Syntezator mowy Festival Lite (flite)
+Comment[pt]=O sintetizador de fala Festival Lite (flite)
+Comment[pt_BR]=Sintetizador de fala Festival Lite (leve)
+Comment[ru]=Синтезатор речи Festival Lite (flite)
+Comment[sk]=Syntetizátor reči Festival Lite (flite)
+Comment[sl]=Sintetizator govora Festival Lite (flite)
+Comment[sr]=Синтетизатор говора Festival Lite (flite)
+Comment[sr@Latn]=Sintetizator govora Festival Lite (flite)
+Comment[sv]=Festival Lite (flite) talsyntes
+Comment[ta]=பெஸ்டிவல் லைட் (flite) பேச்சு கூட்டிணைப்பான்
+Comment[tg]=Таҳлилгари овози Festival Lite (flite)
+Comment[tr]=Festival Lite(flite) konuşma bireştirici
+Comment[uk]=Синтезатор мовлення Festival Lite (flite)
+Comment[vi]=Trình tổng hợp tiếng nói Festival Lite (flite)
+Comment[zh_TW]=Festival Lite (flite) 語音合成器
+Type=Service
+ServiceTypes=KTTSD/SynthPlugin
+X-KDE-Library=libkttsd_fliteplugin
+X-KDE-Languages=en,en_US,en_GB
diff --git a/kttsd/plugins/freetts/Makefile.am b/kttsd/plugins/freetts/Makefile.am
new file mode 100644
index 0000000..be9312b
--- /dev/null
+++ b/kttsd/plugins/freetts/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_freettsplugin.la
+
+libkttsd_freettsplugin_la_SOURCES = \
+ freettsconfigwidget.ui \
+ freettsconf.cpp \
+ freettsproc.cpp \
+ freettsplugin.cpp
+libkttsd_freettsplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_freettsplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_freettsplugin.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/kttsd/plugins/freetts/README b/kttsd/plugins/freetts/README
new file mode 100644
index 0000000..54d9dc2
--- /dev/null
+++ b/kttsd/plugins/freetts/README
@@ -0,0 +1,6 @@
+This is the directory containing the FreeTTS plug in.
+If you intend to edit the GUI (freettsconfig.ui) you will have to first
+copy kttsd/libkttsd/pluginconf.h to a standard include directory
+like $KDEDIR/include/ since the interface has been tweaked to derive
+from PlugInConf instead of QWidget and Qt Designer refuses to open it
+if the header is not properly place.
diff --git a/kttsd/plugins/freetts/configure.in.bot b/kttsd/plugins/freetts/configure.in.bot
new file mode 100644
index 0000000..b3985b9
--- /dev/null
+++ b/kttsd/plugins/freetts/configure.in.bot
@@ -0,0 +1,15 @@
+if test "x$freetts_bindir" = "xno"; then
+ if test "$compile_freetts_plugin" = "yes"; then
+ echo ""
+ echo "======================================================"
+ echo "The freetts.jar Java archive has not been found on"
+ echo "this system. The FreeTTS plugin will be built, "
+ echo "but you must install FreeTTS it before you can use it,"
+ echo "or if it already installed you must set the path to"
+ echo "it in the KDE Text-to-Speech Manager."
+ echo "FreeTTS is available from freetts.sourceforge.net"
+ echo "====================================================="
+ all_tests=bad
+ fi
+fi
+
diff --git a/kttsd/plugins/freetts/configure.in.in b/kttsd/plugins/freetts/configure.in.in
new file mode 100644
index 0000000..78555fc
--- /dev/null
+++ b/kttsd/plugins/freetts/configure.in.in
@@ -0,0 +1,22 @@
+dnl ================
+dnl checks for FreeTTS
+dnl ================
+
+AC_ARG_ENABLE(kttsd-freetts,
+ AC_HELP_STRING([--enable-kttsd-freetts],
+ [build KTTSD FreeTTS Plugin [default=yes]]),
+ freetts_plugin=$enableval,
+ freetts_plugin=yes)
+
+compile_freetts_plugin="yes"
+
+if test "x$freetts_plugin" = "xno"; then
+ compile_freetts_plugin="no"
+fi
+
+dnl Check for festival executable.
+dnl Note that Festival Interactive plugin is always built
+dnl whether binary is found or not, unless user overrides with -disable-freetts.
+AC_PATH_PROG(freetts_bindir, "freetts.jar", "no")
+
+AM_CONDITIONAL(include_kttsd_freetts, test "x$compile_freetts_plugin" = "xyes")
diff --git a/kttsd/plugins/freetts/freettsconf.cpp b/kttsd/plugins/freetts/freettsconf.cpp
new file mode 100644
index 0000000..701af5e
--- /dev/null
+++ b/kttsd/plugins/freetts/freettsconf.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+ Configuration widget and functions for FreeTTS (interactive) plug in
+ -------------------
+ Copyright : (C) 2004 Paul Giannaros
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+ Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qfile.h>
+#include <qapplication.h>
+
+// KDE includes.
+#include <kdialog.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kprogress.h>
+
+// KTTS includes.
+#include <pluginconf.h>
+#include <testplayer.h>
+
+// FreeTTS includes.
+#include "freettsconf.h"
+#include "freettsconfigwidget.h"
+
+/** Constructor */
+FreeTTSConf::FreeTTSConf( QWidget* parent, const char* name, const QStringList&/*args*/) :
+ PlugInConf( parent, name ) {
+
+ // kdDebug() << "FreeTTSConf::FreeTTSConf: Running" << endl;
+ m_freettsProc = 0;
+ m_progressDlg = 0;
+
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "FreeTTSConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new FreeTTSConfWidget(this, "FreeTTSConfigWidget");
+ layout->addWidget(m_widget);
+
+ defaults();
+
+ connect(m_widget->freettsPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->freettsTest, SIGNAL(clicked()), this, SLOT(slotFreeTTSTest_clicked()));
+}
+
+/** Destructor */
+FreeTTSConf::~FreeTTSConf() {
+ // kdDebug() << "Running: FreeTTSConf::~FreeTTSConf()" << endl;
+ if (!m_waveFile.isNull()) QFile::remove(m_waveFile);
+ delete m_freettsProc;
+ delete m_progressDlg;
+}
+
+void FreeTTSConf::load(KConfig *config, const QString &configGroup) {
+ // kdDebug() << "FreeTTSConf::load: Running" << endl;
+
+ config->setGroup(configGroup);
+ QString freeTTSJar = config->readEntry("FreeTTSJarPath", QString::null);
+ if (freeTTSJar.isEmpty())
+ {
+ config->setGroup("FreeTTS");
+ freeTTSJar = config->readEntry("FreeTTSJarPath", QString::null);
+ }
+ if (freeTTSJar.isEmpty())
+ freeTTSJar = getLocation("freetts.jar");
+ m_widget->freettsPath->setURL(freeTTSJar);
+ /// If freettsPath is still empty, then we couldn't find the file in the path.
+}
+
+void FreeTTSConf::save(KConfig *config, const QString &configGroup){
+ // kdDebug() << "FreeTTSConf::save: Running" << endl;
+
+ config->setGroup("FreeTTS");
+ config->writeEntry("FreeTTSJarPath",
+ realFilePath(m_widget->freettsPath->url()));
+
+ config->setGroup(configGroup);
+ if(m_widget->freettsPath->url().isEmpty())
+ KMessageBox::sorry(0, i18n("Unable to locate freetts.jar in your path.\nPlease specify the path to freetts.jar in the Properties tab before using KDE Text-to-Speech"), i18n("KDE Text-to-Speech"));
+ config->writeEntry("FreeTTSJarPath",
+ realFilePath(m_widget->freettsPath->url()));
+}
+
+void FreeTTSConf::defaults(){
+ // kdDebug() << "Running: FreeTTSConf::defaults()" << endl;
+ m_widget->freettsPath->setURL("");
+}
+
+void FreeTTSConf::setDesiredLanguage(const QString &lang)
+{
+ m_languageCode = lang;
+}
+
+QString FreeTTSConf::getTalkerCode()
+{
+ QString freeTTSJar = realFilePath(m_widget->freettsPath->url());
+ if (!freeTTSJar.isEmpty())
+ {
+ if (!getLocation(freeTTSJar).isEmpty())
+ {
+ return QString(
+ "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />"
+ "<prosody volume=\"%4\" rate=\"%5\" />"
+ "<kttsd synthesizer=\"%6\" />")
+ .arg(m_languageCode)
+ .arg("fixed")
+ .arg("neutral")
+ .arg("medium")
+ .arg("medium")
+ .arg("FreeTTS");
+ }
+ }
+ return QString::null;
+}
+
+// QString FreeTTSConf::getLocation(const QString &name) {
+// /// Iterate over the path and see if 'name' exists in it. Return the
+// /// full path to it if it does. Else return an empty QString.
+// kdDebug() << "FreeTTSConf::getLocation: Searching for " << name << " in the path... " << endl;
+// kdDebug() << m_path << endl;
+// for(QStringList::iterator it = m_path.begin(); it != m_path.end(); ++it) {
+// QString fullName = *it;
+// fullName += "/";
+// fullName += name;
+// /// The user either has the directory of the file in the path...
+// if(QFile::exists(fullName)) {
+// return fullName;
+// kdDebug() << fullName << endl;
+// }
+// /// ....Or the file itself
+// else if(QFileInfo(*it).baseName().append(QString(".").append(QFileInfo(*it).extension())) == name) {
+// return fullName;
+// kdDebug() << fullName << endl;
+// }
+// }
+// return "";
+// }
+
+
+void FreeTTSConf::slotFreeTTSTest_clicked()
+{
+ // kdDebug() << "FreeTTSConf::slotFreeTTSTest_clicked(): Running" << endl;
+ // If currently synthesizing, stop it.
+ if (m_freettsProc)
+ m_freettsProc->stopText();
+ else
+ {
+ m_freettsProc = new FreeTTSProc();
+ connect (m_freettsProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
+ }
+ // Create a temp file name for the wave file.
+ KTempFile tempFile (locateLocal("tmp", "freettsplugin-"), ".wav");
+ QString tmpWaveFile = tempFile.file()->name();
+ tempFile.close();
+
+ // Get test message in the language of the voice.
+ QString testMsg = testMessage(m_languageCode);
+
+ // Tell user to wait.
+ m_progressDlg = new KProgressDialog(m_widget, "kttsmgr_freetts_testdlg",
+ i18n("Testing"),
+ i18n("Testing."),
+ true);
+ m_progressDlg->progressBar()->hide();
+ m_progressDlg->setAllowCancel(true);
+
+ // I think FreeTTS only officialy supports English, but if anyone knows of someone
+ // whos built up a different language lexicon and has it working with FreeTTS gimme an email at ceruleanblaze@gmail.com
+ connect (m_freettsProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ m_freettsProc->synth(
+ testMsg,
+ tmpWaveFile,
+ realFilePath(m_widget->freettsPath->url()));
+
+ // Display progress dialog modally. Processing continues when plugin signals synthFinished,
+ // or if user clicks Cancel button.
+ m_progressDlg->exec();
+ disconnect (m_freettsProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ if (m_progressDlg->wasCancelled()) m_freettsProc->stopText();
+ delete m_progressDlg;
+ m_progressDlg = 0;
+}
+
+void FreeTTSConf::slotSynthFinished()
+{
+ // If user canceled, progress dialog is gone, so exit.
+ if (!m_progressDlg)
+ {
+ m_freettsProc->ackFinished();
+ return;
+ }
+ // Hide the Cancel button so user can't cancel in the middle of playback.
+ m_progressDlg->showCancelButton(false);
+ // Get new wavefile name.
+ m_waveFile = m_freettsProc->getFilename();
+ // Tell synth we're done.
+ m_freettsProc->ackFinished();
+ // Play the wave file (possibly adjusting its Speed).
+ // Player object deletes the wave file when done.
+ if (m_player) m_player->play(m_waveFile);
+ QFile::remove(m_waveFile);
+ m_waveFile = QString::null;
+ if (m_progressDlg) m_progressDlg->close();
+}
+
+void FreeTTSConf::slotSynthStopped()
+{
+ // Clean up after canceling test.
+ QString filename = m_freettsProc->getFilename();
+ if (!filename.isNull()) QFile::remove(filename);
+}
+
+#include "freettsconf.moc"
diff --git a/kttsd/plugins/freetts/freettsconf.h b/kttsd/plugins/freetts/freettsconf.h
new file mode 100644
index 0000000..9ab3ae8
--- /dev/null
+++ b/kttsd/plugins/freetts/freettsconf.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+ Configuration widget and functions for FreeTTS (interactive) plug in
+ -------------------
+ Copyright : (C) 2004 Paul Giannaros
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+ Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _FREETTSCONF_H_
+#define _FREETTSCONF_H_
+
+#include <qstringlist.h>
+
+#include <kdebug.h>
+#include <kconfig.h>
+
+#include <pluginconf.h>
+
+#include "freettsconfigwidget.h"
+#include "freettsproc.h"
+
+class QStringList;
+class KProgressDialog;
+
+class FreeTTSConf : public PlugInConf {
+ Q_OBJECT
+
+ public:
+ /** Constructor */
+ FreeTTSConf( QWidget* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /** Destructor */
+ ~FreeTTSConf();
+
+ /** This method is invoked whenever the module should read its
+ configuration (most of the times from a config file) and update the
+ user interface. This happens when the user clicks the "Reset" button in
+ the control center, to undo all of his changes and restore the currently
+ valid settings. NOTE that this is not called after the modules is loaded,
+ so you probably want to call this method in the constructor.*/
+ void load(KConfig *config, const QString &configGroup);
+
+ /** This function gets called when the user wants to save the settings in
+ the user interface, updating the config files or wherever the
+ configuration is stored. The method is called when the user clicks "Apply"
+ or "Ok". */
+ void save(KConfig *config, const QString &configGroup);
+
+ /** This function is called to set the settings in the module to sensible
+ default values. It gets called when hitting the "Default" button. The
+ default values should probably be the same as the ones the application
+ uses when started without a config file. */
+ void defaults();
+
+ /**
+ * This function informs the plugin of the desired language to be spoken
+ * by the plugin. The plugin should attempt to adapt itself to the
+ * specified language code, choosing sensible defaults if necessary.
+ * If the passed-in code is QString::null, no specific language has
+ * been chosen.
+ * @param lang The desired language code or Null if none.
+ *
+ * If the plugin is unable to support the desired language, that is OK.
+ * Language codes are given by ISO 639-1 and are in lowercase.
+ * The code may also include an ISO 3166 country code in uppercase
+ * separated from the language code by underscore (_). For
+ * example, en_GB. If your plugin supports the given language, but
+ * not the given country, treat it as though the country
+ * code were not specified, i.e., adapt to the given language.
+ */
+ void setDesiredLanguage(const QString &lang);
+
+ /**
+ * Return fully-specified talker code for the configured plugin. This code
+ * uniquely identifies the configured instance of the plugin and distinquishes
+ * one instance from another. If the plugin has not been fully configured,
+ * i.e., cannot yet synthesize, return QString::null.
+ * @return Fully-specified talker code.
+ */
+ QString getTalkerCode();
+
+ /**
+ * Function searches the $PATH for a file. If it exists, it returns the full path
+ * to that file. If not, then it returns an empty QString.
+ * @param name The name of the file to search for.
+ * @returns The full path to the file or an empty QString.
+ */
+
+ private slots:
+ void configChanged(bool t = true) {
+ emit changed(t);
+ };
+ void slotFreeTTSTest_clicked();
+ void slotSynthFinished();
+ void slotSynthStopped();
+
+ private:
+ /// Language code.
+ QString m_languageCode;
+
+ /// Configuration Widget.
+ FreeTTSConfWidget *m_widget;
+
+ /// FreeTTS synthesizer.
+ FreeTTSProc *m_freettsProc;
+
+ /// Synthesized wave file name.
+ QString m_waveFile;
+
+ /// Progress dialog.
+ KProgressDialog* m_progressDlg;
+};
+#endif
diff --git a/kttsd/plugins/freetts/freettsconfigwidget.ui b/kttsd/plugins/freetts/freettsconfigwidget.ui
new file mode 100644
index 0000000..1d95751
--- /dev/null
+++ b/kttsd/plugins/freetts/freettsconfigwidget.ui
@@ -0,0 +1,200 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>FreeTTSConfWidget</class>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>FreeTTSConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>576</width>
+ <height>134</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>FreeTTS Config UI</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>freettsConfigurationBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>FreeTTS Interactive Configuration</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>voicesPathBox</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>freettsPathLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;FreeTTS jar file:</string>
+ </property>
+ <property name="textFormat">
+ <enum>AutoText</enum>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>freettsPath</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>freettsPath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>selectVoiceBox</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>410</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>freettsTest</cstring>
+ </property>
+ <property name="text">
+ <string>Test</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<includes>
+ <include location="global" impldecl="in declaration">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/plugins/freetts/freettsplugin.cpp b/kttsd/plugins/freetts/freettsplugin.cpp
new file mode 100644
index 0000000..c8a75df
--- /dev/null
+++ b/kttsd/plugins/freetts/freettsplugin.cpp
@@ -0,0 +1,26 @@
+/****************************************************************************
+ Factory generation for the FreeTTS plugin so it can actually be used
+ as such.
+ -------------------
+ Copyright : (C) 2004 Paul Giannaros
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+ Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "freettsconf.h"
+#include "freettsproc.h"
+
+typedef K_TYPELIST_2( FreeTTSProc, FreeTTSConf ) FreeTTS;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_freettsplugin, KGenericFactory<FreeTTS>("kttsd_freetts"))
+
diff --git a/kttsd/plugins/freetts/freettsproc.cpp b/kttsd/plugins/freetts/freettsproc.cpp
new file mode 100644
index 0000000..829fee9
--- /dev/null
+++ b/kttsd/plugins/freetts/freettsproc.cpp
@@ -0,0 +1,275 @@
+/****************************************************************************
+ Main speaking functions for the FreeTTS Plug in
+ -------------------
+ Copyright : (C) 2004 Paul Giannaros
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+ Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qfileinfo.h>
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+
+#include "freettsproc.h"
+
+/** Constructor */
+FreeTTSProc::FreeTTSProc( QObject* parent, const char* name, const QStringList& /*args*/) :
+ PlugInProc( parent, name ) {
+ kdDebug() << "Running: FreeTTSProc::FreeTTSProc" << endl;
+ m_state = psIdle;
+ m_waitingStop = false;
+ m_freettsProc = 0;
+}
+
+/** Desctructor */
+FreeTTSProc::~FreeTTSProc() {
+ kdDebug() << "Running: FreeTTSProc::~FreeTTSProc" << endl;
+ if (m_freettsProc) {
+ stopText();
+ delete m_freettsProc;
+ }
+}
+
+/** Initializate the speech */
+bool FreeTTSProc::init(KConfig *config, const QString &configGroup) {
+ kdDebug() << "Running: FreeTTSProc::init()" << endl;
+ kdDebug() << "Initializing plug in: FreeTTS" << endl;
+ config->setGroup(configGroup);
+ m_freettsJarPath = config->readEntry("FreeTTSJarPath", "freetts.jar");
+ kdDebug() << "FreeTTSProc::init: path to freetts.jar: " << m_freettsJarPath << endl;
+ return true;
+}
+
+/**
+ * Say a text. Synthesize and audibilize it.
+ * @param text The text to be spoken.
+ *
+ * If the plugin supports asynchronous operation, it should return immediately.
+ */
+void FreeTTSProc::sayText(const QString &text) {
+ synth(text, QString::null, m_freettsJarPath);
+}
+
+/**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately.
+ */
+void FreeTTSProc::synthText(const QString& text, const QString& suggestedFilename) {
+ kdDebug() << "Running: FreeTTSProc::synthText" << endl;
+ synth(text, suggestedFilename, m_freettsJarPath);
+}
+
+// A little helper function because KDE 3.2 kdDebug() does not support QValueList<QCString>.
+QStringList argsToQStringList(const QValueList<QCString> list)
+{
+ QStringList newList;
+ QValueList<QCString>::ConstIterator it = list.begin();
+ for ( ; it != list.end(); ++it ) newList.append(*it);
+ return newList;
+}
+
+void FreeTTSProc::synth(
+ const QString &text,
+ const QString &synthFilename,
+ const QString& freettsJarPath) {
+
+ kdDebug() << "Running: FreeTTSProc::synth" << endl;
+
+ if (m_freettsProc) {
+ if (m_freettsProc->isRunning()) m_freettsProc->kill();
+ delete m_freettsProc;
+ m_freettsProc = 0;
+
+ }
+
+ m_freettsProc = new KProcess;
+ connect(m_freettsProc, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotProcessExited(KProcess*)));
+ connect(m_freettsProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStdout(KProcess*, char*, int)));
+ connect(m_freettsProc, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotReceivedStderr(KProcess*, char*, int)));
+ connect(m_freettsProc, SIGNAL(wroteStdin(KProcess*)),
+ this, SLOT(slotWroteStdin(KProcess* )));
+ if (synthFilename.isNull())
+ m_state = psSaying;
+ else
+ m_state = psSynthing;
+
+
+ QString saidText = text;
+ saidText += "\n";
+
+ /// As freetts.jar doesn't seem to like being called from an absolute path,
+ /// we need to strip off the path to freetts.jar and pass it to
+ /// KProcess::setWorkingDirectory()
+ /// We could just strip off 11 characters from the end of the path to freetts.jar, but thats
+ /// not exactly very portable...
+ QString filename = QFileInfo(freettsJarPath).baseName().append(QString(".").append(QFileInfo(freettsJarPath).extension()));
+ QString freettsJarDir = freettsJarPath.left((freettsJarPath.length() - filename.length()) - 1);
+
+ m_freettsProc->setWorkingDirectory(freettsJarDir);
+ kdDebug() << "FreeTTSProc::synthText: moved to directory '" << freettsJarDir << "'" << endl;
+ kdDebug() << "FreeTTSProc::synthText: Running file: '" << filename << "'" << endl;
+ *m_freettsProc << "java" << "-jar" << filename;
+
+ /// Dump audio into synthFilename
+
+ if (!synthFilename.isNull()) *m_freettsProc << "-dumpAudio" << synthFilename;
+
+ m_synthFilename = synthFilename;
+
+ kdDebug() << "FreeTTSProc::synth: Synthing text: '" << saidText << "' using FreeTTS plug in" << endl;
+ if (!m_freettsProc->start(KProcess::NotifyOnExit, KProcess::All)) {
+ kdDebug() << "FreeTTSProc::synth: Error starting FreeTTS process. Is freetts.jar in the PATH?" << endl;
+ m_state = psIdle;
+ kdDebug() << "KProcess args: " << argsToQStringList(m_freettsProc->args()) << endl;
+ return;
+ }
+ kdDebug()<< "FreeTTSProc:synth: FreeTTS initialized" << endl;
+ m_freettsProc->writeStdin(saidText.latin1(), saidText.length());
+}
+
+/**
+ * Returning the filename of the synth'd text
+ * @returns The filename of the last synth'd text
+ */
+QString FreeTTSProc::getFilename() {
+ kdDebug() << "FreeTTSProc::getFilename: returning " << m_synthFilename << endl;
+ return m_synthFilename;
+}
+
+/**
+ * Stop current operation (saying or synthesizing text).
+ * Important: This function may be called from a thread different from the
+ * one that called sayText or synthText.
+ * If the plugin cannot stop an in-progress @ref sayText or
+ * @ref synthText operation, it must not block waiting for it to complete.
+ * Instead, return immediately.
+ *
+ * If a plugin returns before the operation has actually been stopped,
+ * the plugin must emit the @ref stopped signal when the operation has
+ * actually stopped.
+ *
+ * The plugin should change to the psIdle state after stopping the
+ * operation.
+ */
+void FreeTTSProc::stopText() {
+ kdDebug() << "FreeTTSProc::stopText:: Running" << endl;
+ if (m_freettsProc) {
+ if (m_freettsProc->isRunning()) {
+ kdDebug() << "FreeTTSProc::stopText: killing FreeTTS." << endl;
+ m_waitingStop = true;
+ m_freettsProc->kill();
+ }
+ else m_state = psIdle;
+ }
+ else m_state = psIdle;
+ kdDebug() << "FreeTTSProc::stopText: FreeTTS stopped." << endl;
+}
+
+void FreeTTSProc::slotProcessExited(KProcess*) {
+ kdDebug() << "FreeTTSProc:slotProcessExited: FreeTTS process has exited." << endl;
+ pluginState prevState = m_state;
+ if (m_waitingStop) {
+ m_waitingStop = false;
+ m_state = psIdle;
+ emit stopped();
+ }
+ else {
+ m_state = psFinished;
+ if (prevState == psSaying)
+ emit sayFinished();
+ else if (prevState == psSynthing)
+ emit synthFinished();
+ }
+}
+
+void FreeTTSProc::slotReceivedStdout(KProcess*, char* buffer, int buflen) {
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "FreeTTSProc::slotReceivedStdout: Received output from FreeTTS: " << buf << endl;
+}
+
+void FreeTTSProc::slotReceivedStderr(KProcess*, char* buffer, int buflen) {
+ QString buf = QString::fromLatin1(buffer, buflen);
+ kdDebug() << "FreeTTSProc::slotReceivedStderr: Received error from FreeTTS: " << buf << endl;
+}
+
+void FreeTTSProc::slotWroteStdin(KProcess*) {
+ kdDebug() << "FreeTTSProc::slotWroteStdin: closing Stdin" << endl;
+ m_freettsProc->closeStdin();
+}
+
+/**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @see pluginState
+ */
+pluginState FreeTTSProc::getState() {
+ return m_state;
+}
+
+/**
+ * Acknowledges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+void FreeTTSProc::ackFinished() {
+ if (m_state == psFinished) {
+ m_state = psIdle;
+ m_synthFilename = QString::null;
+ }
+}
+
+/**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref sayFinished or @ref synthFinished signals when
+ * saying or synthesis is completed.
+ */
+bool FreeTTSProc::supportsAsync() {
+// return true;
+ return true;
+}
+
+/**
+ * Returns True if the plugIn supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ */
+bool FreeTTSProc::supportsSynth() {
+// return true;
+ return true;
+}
+
+
+#include "freettsproc.moc"
diff --git a/kttsd/plugins/freetts/freettsproc.h b/kttsd/plugins/freetts/freettsproc.h
new file mode 100644
index 0000000..b2bb631
--- /dev/null
+++ b/kttsd/plugins/freetts/freettsproc.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+ Main speaking functions for the FreeTTS Plug in
+ -------------------
+ Copyright : (C) 2004 Paul Giannaros
+ -------------------
+ Original author: Paul Giannaros <ceruleanblaze@gmail.com>
+ Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef _FREETTSPROC_H_
+#define _FREETTSPROC_H_
+
+
+#include <qstringlist.h>
+#include <qmutex.h>
+
+#include <pluginproc.h>
+
+class KProcess;
+
+class FreeTTSProc : public PlugInProc{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor
+ */
+ FreeTTSProc( QObject* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /**
+ * Destructor
+ */
+ virtual ~FreeTTSProc();
+
+ /**
+ * Initializate the speech engine.
+ * @param config Settings object.
+ * @param configGroup Settings group.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Say a text string.
+ * @param text The text to speak.
+ */
+ virtual void sayText(const QString &text);
+
+ /**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately.
+ */
+ virtual void synthText(const QString& text, const QString& suggestedFilename);
+
+ /**
+ * Get the generated audio filename from synthText.
+ * @return Name of the audio file the plugin generated.
+ * Null if no such file.
+ *
+ * The plugin must not re-use the filename.
+ */
+ virtual QString getFilename();
+
+ /**
+ * Stop current operation (saying or synthesizing text).
+ * Important: This function may be called from a thread different from the
+ * one that called sayText or synthText.
+ * If the plugin cannot stop an in-progress @ref sayText or
+ * @ref synthText operation, it must not block waiting for it to complete.
+ * Instead, return immediately.
+ *
+ * If a plugin returns before the operation has actually been stopped,
+ * the plugin must emit the @ref stopped signal when the operation has
+ * actually stopped.
+ *
+ * The plugin should change to the psIdle state after stopping the
+ * operation.
+ */
+ virtual void stopText();
+
+ /**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @see pluginState
+ */
+ virtual pluginState getState();
+
+ /**
+ * Acknowledges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref sayFinished or @ref synthFinished signals when
+ * saying or synthesis is completed.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Returns True if the plugin supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ */
+ virtual bool supportsSynth();
+
+ /**
+ * Say or Synthesize text.
+ * @param text The text to be synthesized.
+ * @param synthFilename If not Null, synthesize only to this filename, otherwise
+ * synthesize and audibilize the text.
+ * @param freettsJarPath Path to the freetts jar file.
+ */
+ void synth(
+ const QString &text,
+ const QString &synthFilename,
+ const QString &freettsJarPath);
+
+private slots:
+ void slotProcessExited(KProcess* proc);
+ void slotReceivedStdout(KProcess* proc, char* buffer, int buflen);
+ void slotReceivedStderr(KProcess* proc, char* buffer, int buflen);
+ void slotWroteStdin(KProcess* proc);
+
+private:
+
+ /**
+ * Path to FreeTTS jar file (from config).
+ */
+ QString m_freettsJarPath;
+
+ /**
+ * FreeTTS process
+ */
+ KProcess* m_freettsProc;
+
+ /**
+ * Synthesis filename.
+ */
+ QString m_synthFilename;
+
+ /**
+ * Plugin state.
+ */
+ pluginState m_state;
+
+ /**
+ * True when stopText has been called. Used to force transition to psIdle when
+ * FreeTTS exits.
+ */
+ bool m_waitingStop;
+
+};
+
+#endif // _FREETTSPROC_H_
diff --git a/kttsd/plugins/freetts/kttsd_freettsplugin.desktop b/kttsd/plugins/freetts/kttsd_freettsplugin.desktop
new file mode 100644
index 0000000..cdfab63
--- /dev/null
+++ b/kttsd/plugins/freetts/kttsd_freettsplugin.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=FreeTTS
+Name[tr]=Freetts
+Name[vi]=Văn bản sang Tiếng nói Tự do
+Comment=FreeTTS speech synthesizer
+Comment[bg]=Синтезатор на глас FreeTTS
+Comment[ca]=Sintetitzador de veu FreeTTS
+Comment[cs]=Hlasový syntetizér FreeTTS
+Comment[da]=FreeTTS tale-synthesizer
+Comment[de]=FreeTTS Sprachsynthesizer
+Comment[el]=Συνθέτης ομιλίας FreeTTS
+Comment[es]=Sintetizador de texto a voz FreeTTS
+Comment[et]=Kõnesüntesaator FreeTTS
+Comment[eu]=FreeTTS hizketa-sintetizadorea
+Comment[fa]=ترکیب‌دهندۀ گفتار FreeTTS
+Comment[fi]=FreeTTS puhesyntetisaattori
+Comment[fr]=Synthèse vocale FreeTTS
+Comment[ga]=Sintéiseoir cainte FreeTTS
+Comment[gl]=Sintetizador de voces FreeTTS
+Comment[hu]=FreeTTS beszédszintetizátor
+Comment[is]=FreeTTS talgerfill
+Comment[it]=Sintetizzatore vocale FreeTTS
+Comment[ja]=FreeTTS スピーチシンセサイザ
+Comment[ka]=FreeTTS ხმის სინთეზატორი
+Comment[km]=កម្មវិធី​សង្គ្រោះ​ការនិយាយ FreeTTS
+Comment[mk]=FreeTTS синтетизатор на говор
+Comment[ms]=Pensintesis tutur FreeTTS
+Comment[nb]=FreeTTS talesyntetisering
+Comment[nds]=Blicksnuut FreeTTS
+Comment[ne]=FreeTTS संवाद सिन्थेसाइजर
+Comment[nl]=FreeTTS spraaksynthesizer
+Comment[pa]=FreeTTS ਬੋਲੀ ਸੰਸਲੇਸ਼ਕ
+Comment[pl]=Syntezator mowy FreeTTS
+Comment[pt]=O sintetizador de fala FreeTTS
+Comment[pt_BR]=Sintetizador de fala FreeTTS
+Comment[ru]=Синтезатор речи FreeTTS
+Comment[sk]=Syntetizátor reči FreeTTS
+Comment[sl]=Sintetizator govora FreeTTS
+Comment[sr]=Синтетизатор говора FreeTTS
+Comment[sr@Latn]=Sintetizator govora FreeTTS
+Comment[sv]=FreeTTS talsyntes
+Comment[ta]=FreeTTS பேச்சு கூட்டிணைப்பான்
+Comment[tg]=Таҳлилгари овози FreeTTS
+Comment[tr]=FreeTTS konuşma bireştirici
+Comment[uk]=Синтезатор мовлення FreeTTS
+Comment[vi]=Trình tổng hợp tiếng nói Tự do
+Comment[zh_TW]=FreeTTS 語音合成器
+Type=Service
+ServiceTypes=KTTSD/SynthPlugin
+X-KDE-Library=libkttsd_freettsplugin
+X-KDE-Languages=en,en_US,en_GB
diff --git a/kttsd/plugins/hadifix/Makefile.am b/kttsd/plugins/hadifix/Makefile.am
new file mode 100644
index 0000000..35ca445
--- /dev/null
+++ b/kttsd/plugins/hadifix/Makefile.am
@@ -0,0 +1,23 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_hadifixplugin.la
+
+libkttsd_hadifixplugin_la_SOURCES = \
+ hadifixconf.cpp \
+ hadifixproc.cpp \
+ hadifixplugin.cpp \
+ hadifixconfigui.ui \
+ voicefileui.ui
+libkttsd_hadifixplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_hadifixplugin_la_LIBADD = $(LIB_KDECORE) $(LIB_KFILE) $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_hadifixplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+# Data files.
+festivalintxsltdatadir = $(kde_datadir)/kttsd/hadifix/xslt/
+festivalintxsltdata_DATA = SSMLtoTxt2pho.xsl
diff --git a/kttsd/plugins/hadifix/README b/kttsd/plugins/hadifix/README
new file mode 100644
index 0000000..f41b967
--- /dev/null
+++ b/kttsd/plugins/hadifix/README
@@ -0,0 +1,3 @@
+This is the directory containing the Hadifix plug in.
+This plug in is developed and maintained by Gunnar Schmi Dt.
+Rework by Gary Cramblitt <garycramblitt@comcast.net>
diff --git a/kttsd/plugins/hadifix/SSMLtoTxt2pho.xsl b/kttsd/plugins/hadifix/SSMLtoTxt2pho.xsl
new file mode 100644
index 0000000..5a81c8f
--- /dev/null
+++ b/kttsd/plugins/hadifix/SSMLtoTxt2pho.xsl
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text" encoding="ISO-8859-1" indent="no"/>
+
+<!-- XSLT stylesheet to convert SSML into a format that can be processed by the
+ Hadifix txt2pho processor.
+
+ (c) 2004 by Gary Cramblitt
+
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify *
+ it under the terms of the GNU General Public License as published by *
+ the Free Software Foundation; either version 2 of the License, or *
+ (at your option) any later version. *
+
+ The txt2pho processor permits special markup to be embedded in text to control
+ speech attributes such as speed (duration), pitch, etc.
+ The markup must be inside curly braces and separated from other text by a space.
+ Spaces within the markup are not permitted.
+ See the txt2pho README file for details.
+
+ Something the README does not say is that {Pitch} markup applies only to one
+ sentence and reverts back to normal when the sentence is completed.
+ It means that we must repeatedly ouput {Pitch} markup
+ for each sentence in the text. For example, the SSML
+
+ <prosody pitch="high">Sentence one. Sentence two.</prosody> Sentence three.
+
+ must be converted to
+
+ {Pitch:300} Sentence one. {Pitch:300} Sentence two. Sentence three.
+
+ {Duration} markup, on the other hand, is addative and stays in effect until
+ changed. For example, the SSML
+
+ <prosody rate="fast">Sentence one. Sentence two.</prosody> Sentence three.
+
+ must be converted to
+
+ {Duration:-0.5} Sentence one. Sentence two. {Duration:0.5} Sentence three.
+
+ txt2pho will also stop processing when it sees a newline. Therefore, we must take
+ care to strip all newlines and avoid inserting any newlines.
+ -->
+
+<!-- Strip all elements and attributes from output. -->
+<xsl:strip-space elements="*" />
+
+<xsl:template match="speak">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<!-- Handle markup that maintains state. -->
+<xsl:template match="prosody">
+ <!-- Rate (speed), Rates are addative and stay in effect until changed. -->
+ <!-- TODO: SSML permits nesting of prosody elements. As coded below,
+ <prosody rate="slow">One<prosody rate="slow">Two</prosody</prosody>
+ will pronounce "Two" doubly slow, which it should not do. -->
+ <xsl:choose>
+ <xsl:when test="@rate='fast'">
+ <!-- Increase speed. -->
+ <xsl:value-of select="'{Duration:-0.5} '"/>
+ <!-- Continue processing. -->
+ <xsl:apply-templates/>
+ <!-- Decrease speed. -->
+ <xsl:value-of select="'{Duration:0.5} '"/>
+ </xsl:when>
+ <xsl:when test="@rate='slow'">
+ <!-- Decrease speed. -->
+ <xsl:value-of select="'{Duration:0.5} '"/>
+ <!-- Continue processing. -->
+ <xsl:apply-templates/>
+ <!-- Increase speed. -->
+ <xsl:value-of select="'{Duration:-0.5} '"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Outputs a sentence with txt2pho markup.
+ Called in the context of a text node. Obtain markup by
+ extracting ancestor node attributes.
+ @param sentence The sentence to mark up.
+ @return Sentence preceeded by txt2pho markup.
+ -->
+<xsl:template name="output-sentence">
+ <xsl:param name="sentence"/>
+ <!-- Pitch -->
+ <xsl:if test="ancestor::prosody/@pitch='high'">
+ <xsl:value-of select="'{Pitch:300} '"/>
+ </xsl:if>
+ <xsl:if test="ancestor::prosody/@pitch='low'">
+ <xsl:value-of select="'{Pitch:-40} '"/>
+ </xsl:if>
+ <!-- Output the sentence itself. -->
+ <xsl:value-of select="$sentence"/>
+</xsl:template>
+
+<!-- Return the first sentence of argument.
+ Sentence delimiters are '.:;!?'
+ @param paragraph Paragraph from which to extract first sentence.
+ @return The first sentence, or if no such sentence, the paragraph.
+ -->
+<xsl:template name="parse-sentence">
+ <xsl:param name="paragraph"/>
+ <!-- Copy paragraph, replacing all delimeters with period. -->
+ <xsl:variable name="tmp">
+ <xsl:value-of select="translate($paragraph,':;!?','....')"/>
+ </xsl:variable>
+ <!-- Look for first period and space and extract corresponding substring from original. -->
+ <xsl:choose>
+ <xsl:when test="contains($tmp, '. ')">
+ <xsl:value-of select="substring($paragraph, 1, string-length(substring-before($tmp, '. '))+2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$paragraph"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Process a paragraph, outputting each sentence with txt2pho markup.
+ @param paragraph The paragraph to process.
+ @return The paragraph with each sentence preceeded by txt2pho markup.
+ -->
+<xsl:template name="output-paragraph">
+ <xsl:param name="paragraph" />
+ <!-- Stop when no more sentences to output. -->
+ <xsl:choose>
+ <xsl:when test="normalize-space($paragraph)!=''">
+ <!-- Split the paragraph into first sentence and rest of paragraph (if any). -->
+ <xsl:variable name="sentence">
+ <xsl:call-template name="parse-sentence">
+ <xsl:with-param name="paragraph" select="$paragraph"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- debug: <xsl:value-of select="concat('[sentence: ',$sentence,']')"/> -->
+ <xsl:variable name="rest">
+ <xsl:value-of select="substring-after($paragraph,$sentence)" />
+ </xsl:variable>
+ <!-- Output the sentence with markup. -->
+ <xsl:call-template name="output-sentence" >
+ <xsl:with-param name="sentence" select="$sentence" />
+ </xsl:call-template>
+ <!-- Recursively process the rest of the paragraph. -->
+ <xsl:call-template name="output-paragraph">
+ <xsl:with-param name="paragraph" select="$rest" />
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<!-- Process each text node. -->
+<xsl:template match="text()">
+ <!-- debug: <xsl:value-of select="concat('[paragraph: ',normalize-space(.),']')"/> -->
+ <xsl:call-template name="output-paragraph">
+ <xsl:with-param name="paragraph" select="concat(normalize-space(.),' ')"/>
+ </xsl:call-template>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/kttsd/plugins/hadifix/configure.in.bot b/kttsd/plugins/hadifix/configure.in.bot
new file mode 100644
index 0000000..ffada4f
--- /dev/null
+++ b/kttsd/plugins/hadifix/configure.in.bot
@@ -0,0 +1,37 @@
+if test "x$compile_hadifix_plugin" = "xyes"; then
+ if test "x$hadifix_inst" = "xno"; then
+ echo ""
+ echo "======================================================"
+ echo "Some of the tools needed to run Hadifix do not appear"
+ echo "to be installed on this system. (mbrola and txt2pho"
+ echo "were not found in the PATH or /etc/txt2pho was not"
+ echo "found). The Hadifix plugin will be built, but you need"
+ echo "to install the required tools before you can use it:"
+ echo ""
+ if test "x$hadifix_mbrola_bin" = "xno"; then
+ echo "- mbrola was not found. You can get it from"
+ echo " http://tcts.fpms.ac.be/synthesis/mbrola.html"
+ fi
+ if test "x$hadifix_txt2pho_bin" = "xno"; then
+ echo "- txt2pho was not found. You can get it from"
+ echo " http://www.ikp.uni-bonn.de/dt/forsch/phonetik/"
+ echo " hadifix/HADIFIXforMBROLA.html"
+ fi
+ echo ""
+ echo "Please read the KTTS Handbook for further information."
+ echo "====================================================="
+ all_tests=bad
+ fi
+ if test "x$hadifix_inst" = "xyes"; then
+ if test "x$hadifix_txt2pho" = "xno"; then
+ echo ""
+ echo "======================================================"
+ echo "The configuration file /etc/txt2pho was not found on"
+ echo "this system. This is no problem as long as all users"
+ echo "have a valid ~/.txt2phorc in their home directories if"
+ echo "they want to use the Hadifix plugin."
+ echo "======================================================"
+ fi
+ fi
+fi
+
diff --git a/kttsd/plugins/hadifix/configure.in.in b/kttsd/plugins/hadifix/configure.in.in
new file mode 100644
index 0000000..3c997c2
--- /dev/null
+++ b/kttsd/plugins/hadifix/configure.in.in
@@ -0,0 +1,37 @@
+dnl ==========================
+dnl checks for Hadifix plug in
+dnl ==========================
+
+AC_ARG_ENABLE(kttsd-hadifix,
+ AC_HELP_STRING([--enable-kttsd-hadifix],
+ [build KTTSD Hadifix Plugin [default=yes]]),
+ hadifix_plugin=$enableval,
+ hadifix_plugin=yes)
+
+compile_hadifix_plugin="no"
+
+if test "x$hadifix_plugin" = "xyes"; then
+ compile_hadifix_plugin="yes"
+fi
+
+if test "x$compile_hadifix_plugin" = "xyes"; then
+ dnl Check for Hadifix installation.
+ dnl Note that Hadifix plugin is always built,
+ dnl unless user overrides with -disable-kttsd-hadifix.
+ AC_PATH_PROG(hadifix_mbrola_bin, "mbrola", "no", [$PATH:])
+ AC_PATH_PROG(hadifix_txt2pho_bin, "txt2pho", "no", [$PATH:])
+
+ hadifix_inst="yes"
+ if test "x$hadifix_mbrola_bin" = "xno"; then
+ hadifix_inst="no"
+ fi
+ if test "x$hadifix_txt2pho_bin" = "xno"; then
+ hadifix_inst="no"
+ fi
+
+ if test "x$hadifix_inst" = "xyes"; then
+ AC_CHECK_FILE(/etc/txt2pho, [hadifix_txt2pho="yes"], [hadifix_txt2pho="no"])
+ fi
+fi
+
+AM_CONDITIONAL(include_kttsd_hadifix, test "x$compile_hadifix_plugin" = "xyes")
diff --git a/kttsd/plugins/hadifix/hadifixconf.cpp b/kttsd/plugins/hadifix/hadifixconf.cpp
new file mode 100644
index 0000000..a2c5547
--- /dev/null
+++ b/kttsd/plugins/hadifix/hadifixconf.cpp
@@ -0,0 +1,406 @@
+/***************************************************************************
+ begin : Mon Okt 14 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : gunnar@schmi-dt.de
+ current mainainer: : Gary Cramblitt <garycramblitt@comcast.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qfile.h>
+
+// KDE includes.
+#include <ktempfile.h>
+#include <kaboutdata.h>
+#include <kaboutapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kcombobox.h>
+#include <kstandarddirs.h>
+#include <kurlrequester.h>
+#include <kdialogbase.h>
+#include <klineedit.h>
+#include <knuminput.h>
+#include <kprogress.h>
+
+// KTTS includes.
+#include <pluginconf.h>
+#include <testplayer.h>
+#include <talkercode.h>
+
+// Hadifix includes.
+#include "hadifixproc.h"
+#include "voicefileui.h"
+#include "hadifixconfigui.h"
+#include "hadifixconf.h"
+#include "hadifixconf.moc"
+
+class HadifixConfPrivate {
+ friend class HadifixConf;
+ private:
+ HadifixConfPrivate() {
+ hadifixProc = 0;
+ progressDlg = 0;
+ findInitialConfig();
+ };
+
+ ~HadifixConfPrivate() {
+ if (hadifixProc) hadifixProc->stopText();
+ delete hadifixProc;
+ if (!waveFile.isNull()) QFile::remove(waveFile);
+ delete progressDlg;
+ };
+
+ #include "initialconfig.h"
+
+ void setConfiguration (QString hadifixExec, QString mbrolaExec,
+ QString voice, bool male,
+ int volume, int time, int pitch,
+ QString codecName)
+ {
+ configWidget->hadifixURL->setURL (hadifixExec);
+ configWidget->mbrolaURL->setURL (mbrolaExec);
+ configWidget->setVoice (voice, male);
+
+ configWidget->volumeBox->setValue (volume);
+ configWidget->timeBox->setValue (time);
+ configWidget->frequencyBox->setValue (pitch);
+ int codec = PlugInProc::codecNameToListIndex(codecName, codecList);
+ configWidget->characterCodingBox->setCurrentItem(codec);
+ }
+
+ void initializeVoices () {
+ QStringList::iterator it;
+ for (it = defaultVoices.begin(); it != defaultVoices.end(); ++it) {
+ HadifixProc::VoiceGender gender;
+ QString name = QFileInfo(*it).fileName();
+ gender = HadifixProc::determineGender(defaultMbrolaExec, *it);
+ if (gender == HadifixProc::MaleGender)
+ configWidget->addVoice(*it, true, i18n("Male voice \"%1\"").arg(name));
+ else if (gender == HadifixProc::FemaleGender)
+ configWidget->addVoice(*it, false, i18n("Female voice \"%1\"").arg(name));
+ else {
+ if (name == "de1")
+ configWidget->addVoice(*it, false, i18n("Female voice \"%1\"").arg(name));
+ else {
+ configWidget->addVoice(*it, true, i18n("Unknown voice \"%1\"").arg(name));
+ configWidget->addVoice(*it, false, i18n("Unknown voice \"%1\"").arg(name));
+ }
+ }
+ }
+ };
+
+ void initializeCharacterCodes() {
+ // Build codec list and fill combobox.
+ codecList = PlugInProc::buildCodecList();
+ configWidget->characterCodingBox->clear();
+ configWidget->characterCodingBox->insertStringList(codecList);
+ }
+
+ void setDefaultEncodingFromVoice() {
+ QString voiceFile = configWidget->getVoiceFilename();
+ QString voiceCode = QFileInfo(voiceFile).baseName(false);
+ voiceCode = voiceCode.left(2);
+ QString codecName = "Local";
+ if (voiceCode == "de") codecName = "ISO 8859-1";
+ if (voiceCode == "hu") codecName = "ISO 8859-2";
+ configWidget->characterCodingBox->setCurrentItem(PlugInProc::codecNameToListIndex(
+ codecName, codecList));
+}
+
+ void setDefaults () {
+ QStringList::iterator it = defaultVoices.begin();
+ // Find a voice that matches language code, if any.
+ if (!languageCode.isEmpty())
+ {
+ QString justLang = languageCode.left(2);
+ for (;it != defaultVoices.end();++it)
+ {
+ QString voiceCode = QFileInfo(*it).baseName(false).left(2);
+ if (voiceCode == justLang) break;
+ }
+ if (it == defaultVoices.end()) it = defaultVoices.begin();
+ }
+ HadifixProc::VoiceGender gender;
+ gender = HadifixProc::determineGender(defaultMbrolaExec, *it);
+
+ setConfiguration (defaultHadifixExec, defaultMbrolaExec,
+ *it, gender == HadifixProc::MaleGender,
+ 100, 100, 100, "Local");
+ };
+
+ void load (KConfig *config, const QString &configGroup) {
+ config->setGroup(configGroup);
+
+ QString voice = config->readEntry("voice", configWidget->getVoiceFilename());
+
+ HadifixProc::VoiceGender gender;
+ gender = HadifixProc::determineGender(defaultMbrolaExec, voice);
+ bool isMale = (gender == HadifixProc::MaleGender);
+
+ QString defaultCodecName = "Local";
+ // TODO: Need a better way to determine proper codec for each voice.
+ // This will do for now.
+ QString voiceCode = QFileInfo(voice).baseName(false);
+ if (voiceCode.left(2) == "de") defaultCodecName = "ISO 8859-1";
+ if (voiceCode.left(2) == "hu") defaultCodecName = "ISO 8859-2";
+
+ setConfiguration (
+ config->readEntry ("hadifixExec",defaultHadifixExec),
+ config->readEntry ("mbrolaExec", defaultMbrolaExec),
+ config->readEntry ("voice", voice),
+ config->readBoolEntry("gender", isMale),
+ config->readNumEntry ("volume", 100),
+ config->readNumEntry ("time", 100),
+ config->readNumEntry ("pitch", 100),
+ config->readEntry ("codec", defaultCodecName)
+ );
+ };
+
+ void save (KConfig *config, const QString &configGroup) {
+ config->setGroup(configGroup);
+ config->writeEntry ("hadifixExec", PlugInConf::realFilePath(configWidget->hadifixURL->url()));
+ config->writeEntry ("mbrolaExec", PlugInConf::realFilePath(configWidget->mbrolaURL->url()));
+ config->writeEntry ("voice", configWidget->getVoiceFilename());
+ config->writeEntry ("gender", configWidget->isMaleVoice());
+ config->writeEntry ("volume", configWidget->volumeBox->value());
+ config->writeEntry ("time", configWidget->timeBox->value());
+ config->writeEntry ("pitch", configWidget->frequencyBox->value());
+ config->writeEntry ("codec", PlugInProc::codecIndexToCodecName(
+ configWidget->characterCodingBox->currentItem(), codecList));
+ }
+
+ HadifixConfigUI *configWidget;
+
+ QString languageCode;
+ QString defaultHadifixExec;
+ QString defaultMbrolaExec;
+ QStringList defaultVoices;
+ QStringList codecList;
+
+ // Wave file playing on play object.
+ QString waveFile;
+ // Synthesizer.
+ HadifixProc* hadifixProc;
+ // Progress Dialog.
+ KProgressDialog* progressDlg;
+};
+
+/** Constructor */
+HadifixConf::HadifixConf( QWidget* parent, const char* name, const QStringList &) :
+ PlugInConf( parent, name ){
+ // kdDebug() << "HadifixConf::HadifixConf: Running" << endl;
+ QVBoxLayout *layout = new QVBoxLayout (this, KDialog::marginHint(), KDialog::spacingHint(), "CommandConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+
+ d = new HadifixConfPrivate();
+ d->configWidget = new HadifixConfigUI (this, "configWidget");
+
+ QString file = locate("data", "LICENSES/LGPL_V2");
+ i18n("This plugin is distributed under the terms of the GPL v2 or later.");
+
+ connect(d->configWidget->voiceButton, SIGNAL(clicked()), this, SLOT(voiceButton_clicked()));
+ connect(d->configWidget->testButton, SIGNAL(clicked()), this, SLOT(testButton_clicked()));
+ connect(d->configWidget, SIGNAL(changed(bool)), this, SLOT(configChanged (bool)));
+ connect(d->configWidget->characterCodingBox, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(d->configWidget->voiceCombo, SIGNAL(activated(int)), this, SLOT(voiceCombo_activated(int)));
+ d->initializeCharacterCodes();
+ d->initializeVoices();
+ d->setDefaults();
+ layout->addWidget (d->configWidget);
+}
+
+/** Destructor */
+HadifixConf::~HadifixConf(){
+ // kdDebug() << "HadifixConf::~HadifixConf: Running" << endl;
+ delete d;
+}
+
+void HadifixConf::load(KConfig *config, const QString &configGroup) {
+ // kdDebug() << "HadifixConf::load: Running" << endl;
+ d->setDefaults();
+ d->load (config, configGroup);
+}
+
+void HadifixConf::save(KConfig *config, const QString &configGroup) {
+ // kdDebug() << "HadifixConf::save: Running" << endl;
+ d->save (config, configGroup);
+}
+
+void HadifixConf::defaults() {
+ // kdDebug() << "HadifixConf::defaults: Running" << endl;
+ d->setDefaults();
+}
+
+void HadifixConf::setDesiredLanguage(const QString &lang)
+{
+ d->languageCode = lang;
+}
+
+QString HadifixConf::getTalkerCode()
+{
+ if (!d->configWidget->hadifixURL->url().isEmpty() && !d->configWidget->mbrolaURL->url().isEmpty())
+ {
+ QString voiceFile = d->configWidget->getVoiceFilename();
+ if (QFileInfo(voiceFile).exists())
+ {
+ // mbrola voice file names usually start with two-letter language code,
+ // but this is by no means guaranteed.
+ QString voiceCode = QFileInfo(voiceFile).baseName(false);
+ QString voiceLangCode = voiceCode.left(2);
+ if (d->languageCode.left(2) != voiceLangCode)
+ {
+ // Verify that first two letters of voice filename are a valid language code.
+ // If they are, switch to that language.
+ if (!TalkerCode::languageCodeToLanguage(voiceLangCode).isEmpty())
+ d->languageCode = voiceLangCode;
+ }
+ QString gender = "male";
+ if (!d->configWidget->isMaleVoice()) gender = "female";
+ QString volume = "medium";
+ if (d->configWidget->volumeBox->value() < 75) volume = "soft";
+ if (d->configWidget->volumeBox->value() > 125) volume = "loud";
+ QString rate = "medium";
+ if (d->configWidget->timeBox->value() < 75) rate = "slow";
+ if (d->configWidget->timeBox->value() > 125) rate = "fast";
+ return QString(
+ "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />"
+ "<prosody volume=\"%4\" rate=\"%5\" />"
+ "<kttsd synthesizer=\"%6\" />")
+ .arg(d->languageCode)
+ .arg(voiceCode)
+ .arg(gender)
+ .arg(volume)
+ .arg(rate)
+ .arg("Hadifix");
+ }
+ }
+ return QString::null;
+}
+
+void HadifixConf::voiceButton_clicked () {
+ KDialogBase *dialog = new KDialogBase (this, 0, true,
+ i18n("Voice File - Hadifix Plugin"),
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok, true);
+ VoiceFileWidget *widget = new VoiceFileWidget(dialog);
+ dialog->setMainWidget (widget);
+
+ widget->femaleOption->setChecked(!d->configWidget->isMaleVoice());
+ widget->maleOption->setChecked(d->configWidget->isMaleVoice());
+ widget->voiceFileURL->setURL(d->configWidget->getVoiceFilename());
+ widget->mbrola = d->defaultMbrolaExec;
+
+ if (dialog->exec() == QDialog::Accepted) {
+ d->configWidget->setVoice (widget->voiceFileURL->url(),
+ widget->maleOption->isChecked());
+ d->setDefaultEncodingFromVoice();
+ emit changed(true);
+ }
+
+ delete dialog;
+}
+
+void HadifixConf::voiceCombo_activated(int /*index*/)
+{
+ d->setDefaultEncodingFromVoice();
+}
+
+void HadifixConf::testButton_clicked () {
+ // If currently synthesizing, stop it.
+ if (d->hadifixProc)
+ d->hadifixProc->stopText();
+ else
+ {
+ d->hadifixProc = new HadifixProc();
+ connect (d->hadifixProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
+ }
+ // Create a temp file name for the wave file.
+ KTempFile tempFile (locateLocal("tmp", "hadifixplugin-"), ".wav");
+ QString tmpWaveFile = tempFile.file()->name();
+ tempFile.close();
+
+ // Tell user to wait.
+ d->progressDlg = new KProgressDialog(d->configWidget, "ktts_hadifix_testdlg",
+ i18n("Testing"),
+ i18n("Testing."),
+ true);
+ d->progressDlg->progressBar()->hide();
+ d->progressDlg->setAllowCancel(true);
+
+ // Speak a German sentence as hadifix is a German tts
+ // TODO: Actually, Hadifix does support English (and other languages?) as well,
+ // If you install the right voice files. The hard part is finding and installing
+ // a working txt2pho for the desired language. There seem to be some primitive french,
+ // italian, and a few others, written in perl, but they have many issues.
+ // Go to the mbrola website and click on "TTS" to learn more.
+
+ // QString testMsg = "K D E ist eine moderne grafische Arbeitsumgebung für UNIX-Computer.";
+ QString testMsg = testMessage(d->languageCode);
+ connect (d->hadifixProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ d->hadifixProc->synth (testMsg,
+ realFilePath(d->configWidget->hadifixURL->url()),
+ d->configWidget->isMaleVoice(),
+ realFilePath(d->configWidget->mbrolaURL->url()),
+ d->configWidget->getVoiceFilename(),
+ d->configWidget->volumeBox->value(),
+ d->configWidget->timeBox->value(),
+ d->configWidget->frequencyBox->value(),
+ PlugInProc::codecIndexToCodec(d->configWidget->characterCodingBox->currentItem(), d->codecList),
+ tmpWaveFile);
+
+ // Display progress dialog modally. Processing continues when plugin signals synthFinished,
+ // or if user clicks Cancel button.
+ d->progressDlg->exec();
+ disconnect (d->hadifixProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
+ if (d->progressDlg->wasCancelled()) d->hadifixProc->stopText();
+ delete d->progressDlg;
+ d->progressDlg = 0;
+}
+
+void HadifixConf::slotSynthFinished()
+{
+ // If user canceled, progress dialog is gone, so exit.
+ if (!d->progressDlg)
+ {
+ d->hadifixProc->ackFinished();
+ return;
+ }
+ // Hide the Cancel button so user can't cancel in the middle of playback.
+ d->progressDlg->showCancelButton(false);
+ // Get new wavefile name.
+ d->waveFile = d->hadifixProc->getFilename();
+ // Tell synth we're done.
+ d->hadifixProc->ackFinished();
+ // Play the wave file (possibly adjusting its Speed).
+ // Player object deletes the wave file when done.
+ if (m_player) m_player->play(d->waveFile);
+ QFile::remove(d->waveFile);
+ d->waveFile = QString::null;
+ if (d->progressDlg) d->progressDlg->close();
+}
+
+void HadifixConf::slotSynthStopped()
+{
+ // Clean up after canceling test.
+ QString filename = d->hadifixProc->getFilename();
+ // kdDebug() << "HadifixConf::slotSynthStopped: filename = " << filename << endl;
+ if (!filename.isNull()) QFile::remove(filename);
+}
diff --git a/kttsd/plugins/hadifix/hadifixconf.h b/kttsd/plugins/hadifix/hadifixconf.h
new file mode 100644
index 0000000..a53ecb1
--- /dev/null
+++ b/kttsd/plugins/hadifix/hadifixconf.h
@@ -0,0 +1,83 @@
+#ifndef _HADIFIXCONF_H_
+#define _HADIFIXCONF_H_
+
+#include <qstringlist.h>
+
+#include <kconfig.h>
+
+#include <pluginconf.h>
+
+class HadifixProc;
+class HadifixConfPrivate;
+
+class HadifixConf : public PlugInConf {
+ Q_OBJECT
+
+ public:
+ /** Constructor */
+ HadifixConf( QWidget* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /** Destructor */
+ ~HadifixConf();
+
+ /** This method is invoked whenever the module should read its
+ configuration (most of the times from a config file) and update the
+ user interface. This happens when the user clicks the "Reset" button in
+ the control center, to undo all of his changes and restore the currently
+ valid settings. NOTE that this is not called after the modules is loaded,
+ so you probably want to call this method in the constructor.*/
+ void load(KConfig *config, const QString &configGroup);
+
+ /** This function gets called when the user wants to save the settings in
+ the user interface, updating the config files or wherever the
+ configuration is stored. The method is called when the user clicks "Apply"
+ or "Ok". */
+ void save(KConfig *config, const QString &configGroup);
+
+ /** This function is called to set the settings in the module to sensible
+ default values. It gets called when hitting the "Default" button. The
+ default values should probably be the same as the ones the application
+ uses when started without a config file. */
+ void defaults();
+
+ /**
+ * This function informs the plugin of the desired language to be spoken
+ * by the plugin. The plugin should attempt to adapt itself to the
+ * specified language code, choosing sensible defaults if necessary.
+ * If the passed-in code is QString::null, no specific language has
+ * been chosen.
+ * @param lang The desired language code or Null if none.
+ *
+ * If the plugin is unable to support the desired language, that is OK.
+ * Language codes are given by ISO 639-1 and are in lowercase.
+ * The code may also include an ISO 3166 country code in uppercase
+ * separated from the language code by underscore (_). For
+ * example, en_GB. If your plugin supports the given language, but
+ * not the given country, treat it as though the country
+ * code were not specified, i.e., adapt to the given language.
+ */
+ void setDesiredLanguage(const QString &lang);
+
+ /**
+ * Return fully-specified talker code for the configured plugin. This code
+ * uniquely identifies the configured instance of the plugin and distinquishes
+ * one instance from another. If the plugin has not been fully configured,
+ * i.e., cannot yet synthesize, return QString::null.
+ * @return Fully-specified talker code.
+ */
+ QString getTalkerCode();
+
+ public slots:
+ void configChanged(bool t = true){emit changed(t);};
+
+ private slots:
+ virtual void voiceButton_clicked();
+ virtual void testButton_clicked();
+ virtual void voiceCombo_activated(int index);
+ void slotSynthFinished();
+ void slotSynthStopped();
+
+ private:
+ HadifixConfPrivate *d;
+};
+#endif
diff --git a/kttsd/plugins/hadifix/hadifixconfigui.ui b/kttsd/plugins/hadifix/hadifixconfigui.ui
new file mode 100644
index 0000000..302c1de
--- /dev/null
+++ b/kttsd/plugins/hadifix/hadifixconfigui.ui
@@ -0,0 +1,692 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>HadifixConfigUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>HadifixConfigUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>578</width>
+ <height>388</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Hadifix Configuration</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the configuration dialog for the Hadifix (txt2pho and Mbrola) speech synthesizer.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>GroupBox4</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Had&amp;ifix Configuration</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the configuration dialog for the Hadifix (txt2pho and Mbrola) speech synthesizer.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>basicOptions</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>&amp;Basic Options</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>voiceLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Voice file:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>voiceCombo</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select a voice for speaking text. If no voices are listed, check your Mbrola configuration. You must install at least one voice.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>voiceCombo</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select a voice for speaking text. If no voices are listed, check your Mbrola configuration. You must install at least one voice.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="0" column="3">
+ <property name="name">
+ <cstring>voiceButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Select...</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>volumeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Volume &amp;ratio:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>volumeBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the volume of speech. Slide to left for softer speech; to the right for louder.</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>volumeBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the volume of speech. Slide to left for softer speech; to the right for louder.</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="1" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>volumeSlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="tickmarks">
+ <enum>NoMarks</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the volume of speech. Slide to left for softer speech; to the right for louder.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>timeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Speed:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the speed of speech. Slide to left for slower speech; to the right for faster.</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="2" column="1">
+ <property name="name">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the speed of speech. Slide to left for slower speech; to the right for faster.</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="2" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>timeSlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the speed of speech. Slide to left for slower speech; to the right for faster.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>frequencyLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Pitch:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>frequencyBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the pitch (tone) of speech. Slide to left for lower speech; to the right for higher.</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="3" column="1">
+ <property name="name">
+ <cstring>frequencyBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the pitch (tone) of speech. Slide to left for lower speech; to the right for higher.</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="3" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>frequencySlider</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Adjusts the pitch (tone) of speech. Slide to left for lower speech; to the right for higher.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>advancedOptions</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>&amp;Advanced Options</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>hadifixBinLabel</cstring>
+ </property>
+ <property name="text">
+ <string>txt2pho e&amp;xecutable:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>hadifixURL</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If the txt2pho program is in your PATH environment variable, simply enter "txt2pho", otherwise specify the full path to the txt2pho executable program.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>hadifixURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If the txt2pho program is in your PATH environment variable, simply enter "txt2pho", otherwise specify the full path to the txt2pho executable program.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>mbrolaBinLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Mbrola executable:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>mbrolaURL</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If the Mbrola program is in your PATH environment variable, simply enter "mbrola", otherwise specify the full path to the Mbrola executable program.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>mbrolaURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If the Mbrola program is in your PATH environment variable, simply enter "mbrola", otherwise specify the full path to the Mbrola executable program.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>characterCodingLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Character &amp;encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>characterCodingBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This combo box specifies which character encoding is used for passing the text. For most western languages, use ISO-8859-1. For Hungarian, use ISO-8859-2.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>240</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>testButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Test</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to test the configuration. You should hear a spoken sentence.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>volumeBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>volumeBox_valueChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>volumeSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>volumeSlider_valueChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>timeBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>timeBox_valueChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>timeSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>timeSlider_valueChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>frequencyBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>frequencyBox_valueChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>frequencySlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>frequencySlider_valueChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>voiceCombo</sender>
+ <signal>activated(const QString&amp;)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>changed(const QString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>volumeBox</sender>
+ <signal>valueChanged(const QString&amp;)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>changed(const QString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>timeBox</sender>
+ <signal>valueChanged(const QString&amp;)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>changed(const QString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>frequencyBox</sender>
+ <signal>valueChanged(const QString&amp;)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>changed(const QString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>hadifixURL</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>changed(const QString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>mbrolaURL</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>HadifixConfigUI</receiver>
+ <slot>changed(const QString&amp;)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in declaration">qradiobutton.h</include>
+ <include location="global" impldecl="in declaration">qpixmap.h</include>
+ <include location="global" impldecl="in declaration">kurl.h</include>
+ <include location="global" impldecl="in declaration">qmap.h</include>
+ <include location="global" impldecl="in implementation">kglobal.h</include>
+ <include location="global" impldecl="in implementation">qstringlist.h</include>
+ <include location="global" impldecl="in implementation">math.h</include>
+ <include location="global" impldecl="in implementation">kiconloader.h</include>
+</includes>
+<forwards>
+ <forward>class QStringList;</forward>
+</forwards>
+<variables>
+ <variable>QMap&lt;QString,int&gt; maleVoices;</variable>
+ <variable>QMap&lt;int,QString&gt; defaultVoices;</variable>
+ <variable>QPixmap female;</variable>
+ <variable>QPixmap male;</variable>
+ <variable>QMap&lt;QString,int&gt; femaleVoices;</variable>
+</variables>
+<signals>
+ <signal>changed(bool)</signal>
+</signals>
+<slots>
+ <slot access="protected" specifier="non virtual">volumeBox_valueChanged( int percentValue )</slot>
+ <slot access="protected" specifier="non virtual">timeBox_valueChanged( int percentValue )</slot>
+ <slot access="protected" specifier="non virtual">frequencyBox_valueChanged( int percentValue )</slot>
+ <slot access="protected" specifier="non virtual">volumeSlider_valueChanged( int sliderValue )</slot>
+ <slot access="protected" specifier="non virtual">timeSlider_valueChanged( int sliderValue )</slot>
+ <slot access="protected" specifier="non virtual">frequencySlider_valueChanged( int sliderValue )</slot>
+ <slot access="protected">changed( const QString &amp; )</slot>
+</slots>
+<functions>
+ <function access="protected" specifier="non virtual" returnType="int">percentToSlider( int percentValue )</function>
+ <function access="protected" specifier="non virtual" returnType="int">sliderToPercent( int sliderValue )</function>
+ <function access="private" specifier="non virtual">init()</function>
+ <function specifier="non virtual">addVoice( const QString &amp;filename, bool isMale )</function>
+ <function specifier="non virtual">addVoice( const QString &amp;filename, bool isMale, const QString &amp;displayname )</function>
+ <function specifier="non virtual">setVoice( const QString &amp;filename, bool isMale )</function>
+ <function specifier="non virtual" returnType="QString">getVoiceFilename()</function>
+ <function specifier="non virtual" returnType="bool">isMaleVoice()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/plugins/hadifix/hadifixconfigui.ui.h b/kttsd/plugins/hadifix/hadifixconfigui.ui.h
new file mode 100644
index 0000000..e3a7a04
--- /dev/null
+++ b/kttsd/plugins/hadifix/hadifixconfigui.ui.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename slots use Qt Designer which will
+** update this file, preserving your code. Create an init() slot in place of
+** a constructor, and a destroy() slot in place of a destructor.
+*****************************************************************************/
+
+// Basically the slider values are logarithmic (0,...,1000) whereas percent
+// values are linear (50%,...,200%).
+//
+// slider = alpha * (log(percent)-log(50))
+// with alpha = 1000/(log(200)-log(50))
+
+int HadifixConfigUI::percentToSlider (int percentValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor (0.5 + alpha * (log(percentValue)-log(50)));
+}
+
+int HadifixConfigUI::sliderToPercent (int sliderValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor(0.5 + exp (sliderValue/alpha + log(50)));
+}
+
+void HadifixConfigUI::volumeBox_valueChanged (int percentValue) {
+ volumeSlider->setValue (percentToSlider (percentValue));
+}
+
+void HadifixConfigUI::timeBox_valueChanged (int percentValue) {
+ timeSlider->setValue (percentToSlider (percentValue));
+}
+
+void HadifixConfigUI::frequencyBox_valueChanged (int percentValue) {
+ frequencySlider->setValue (percentToSlider (percentValue));
+}
+
+void HadifixConfigUI::volumeSlider_valueChanged (int sliderValue) {
+ volumeBox->setValue (sliderToPercent (sliderValue));
+}
+
+void HadifixConfigUI::timeSlider_valueChanged (int sliderValue) {
+ timeBox->setValue (sliderToPercent (sliderValue));
+}
+
+void HadifixConfigUI::frequencySlider_valueChanged (int sliderValue) {
+ frequencyBox->setValue (sliderToPercent (sliderValue));
+}
+
+void HadifixConfigUI::init () {
+ male = KGlobal::iconLoader()->loadIcon("male", KIcon::Small);
+ female = KGlobal::iconLoader()->loadIcon("female", KIcon::Small);
+}
+
+void HadifixConfigUI::addVoice (const QString &filename, bool isMale) {
+ if (isMale) {
+ if (!maleVoices.contains(filename)) {
+ int id = voiceCombo->count();
+ maleVoices.insert (filename, id);
+ voiceCombo->insertItem (male, filename, id);
+ }
+ }
+ else {
+ if (!femaleVoices.contains(filename)) {
+ int id = voiceCombo->count();
+ femaleVoices.insert (filename, id);
+ voiceCombo->insertItem (female, filename, id);
+ }
+ }
+}
+
+void HadifixConfigUI::addVoice (const QString &filename, bool isMale, const QString &displayname) {
+ addVoice (filename, isMale);
+
+ if (isMale) {
+ defaultVoices [maleVoices [filename]] = filename;
+ voiceCombo->changeItem (male, displayname, maleVoices [filename]);
+ }
+ else{
+ defaultVoices [femaleVoices [filename]] = filename;
+ voiceCombo->changeItem (female, displayname, femaleVoices [filename]);
+ }
+}
+
+void HadifixConfigUI::setVoice (const QString &filename, bool isMale) {
+ addVoice (filename, isMale);
+ if (isMale)
+ voiceCombo->setCurrentItem (maleVoices[filename]);
+ else
+ voiceCombo->setCurrentItem (femaleVoices[filename]);
+}
+
+QString HadifixConfigUI::getVoiceFilename() {
+ int curr = voiceCombo->currentItem();
+
+ QString filename = voiceCombo->text(curr);
+ if (defaultVoices.contains(curr))
+ filename = defaultVoices[curr];
+
+ return filename;
+}
+
+bool HadifixConfigUI::isMaleVoice() {
+ int curr = voiceCombo->currentItem();
+ QString filename = getVoiceFilename();
+
+ if (maleVoices.contains(filename))
+ return maleVoices[filename] == curr;
+ else
+ return false;
+}
+
+void HadifixConfigUI::changed (const QString &) {
+ emit changed (true);
+}
diff --git a/kttsd/plugins/hadifix/hadifixplugin.cpp b/kttsd/plugins/hadifix/hadifixplugin.cpp
new file mode 100644
index 0000000..b52052c
--- /dev/null
+++ b/kttsd/plugins/hadifix/hadifixplugin.cpp
@@ -0,0 +1,23 @@
+/***************************************************************************
+ begin : Mon Okt 14 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : gunnar@schmi-dt.de
+ current mainainer: : Gary Cramblitt <garycramblitt@comcast.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "hadifixconf.h"
+#include "hadifixproc.h"
+
+typedef K_TYPELIST_2( HadifixProc, HadifixConf ) Hadifix;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_hadifixplugin, KGenericFactory<Hadifix>("kttsd_hadifix") )
diff --git a/kttsd/plugins/hadifix/hadifixproc.cpp b/kttsd/plugins/hadifix/hadifixproc.cpp
new file mode 100644
index 0000000..42730b3
--- /dev/null
+++ b/kttsd/plugins/hadifix/hadifixproc.cpp
@@ -0,0 +1,411 @@
+/***************************************************************************
+ hadifixproc.cpp - description
+ -------------------
+ begin : Mon Okt 14 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : gunnar@schmi-dt.de
+ current mainainer: : Gary Cramblitt <garycramblitt@comcast.net>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextcodec.h>
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+
+#include "hadifixproc.h"
+#include "hadifixproc.moc"
+
+class HadifixProcPrivate {
+ friend class HadifixProc;
+ private:
+ HadifixProcPrivate () {
+ hadifixProc = 0;
+ waitingStop = false;
+ state = psIdle;
+ synthFilename = QString::null;
+ gender = false;
+ volume = 100;
+ time = 100;
+ pitch = 100;
+ codec = 0;
+ };
+
+ ~HadifixProcPrivate() {
+ delete hadifixProc;
+ };
+
+ void load(KConfig *config, const QString &configGroup) {
+ config->setGroup(configGroup);
+ hadifix = config->readEntry ("hadifixExec", QString::null);
+ mbrola = config->readEntry ("mbrolaExec", QString::null);
+ voice = config->readEntry ("voice", QString::null);
+ gender = config->readBoolEntry("gender", false);
+ volume = config->readNumEntry ("volume", 100);
+ time = config->readNumEntry ("time", 100);
+ pitch = config->readNumEntry ("pitch", 100);
+ codec = PlugInProc::codecNameToCodec(config->readEntry ("codec", "Local"));
+ };
+
+ QString hadifix;
+ QString mbrola;
+ QString voice;
+ bool gender;
+ int volume;
+ int time;
+ int pitch;
+
+ bool waitingStop;
+ KShellProcess* hadifixProc;
+ volatile pluginState state;
+ QTextCodec* codec;
+ QString synthFilename;
+};
+
+/** Constructor */
+HadifixProc::HadifixProc( QObject* parent, const char* name, const QStringList &) :
+ PlugInProc( parent, name ){
+ // kdDebug() << "HadifixProc::HadifixProc: Running" << endl;
+ d = 0;
+}
+
+/** Destructor */
+HadifixProc::~HadifixProc(){
+ // kdDebug() << "HadifixProc::~HadifixProc: Running" << endl;
+
+ if (d != 0) {
+ delete d;
+ d = 0;
+ }
+}
+
+/** Initializate the speech */
+bool HadifixProc::init(KConfig *config, const QString &configGroup){
+ // kdDebug() << "HadifixProc::init: Initializing plug in: Hadifix" << endl;
+
+ if (d == 0)
+ d = new HadifixProcPrivate();
+ d->load(config, configGroup);
+ return true;
+}
+
+/**
+* Say a text. Synthesize and audibilize it.
+* @param text The text to be spoken.
+*
+* If the plugin supports asynchronous operation, it should return immediately
+* and emit sayFinished signal when synthesis and audibilizing is finished.
+* It must also implement the @ref getState method, which must return
+* psFinished, when saying is completed.
+*/
+void HadifixProc::sayText(const QString& /*text*/)
+{
+ kdDebug() << "HadifixProc::sayText: Warning, sayText not implemented." << endl;
+ return;
+}
+
+/**
+* Synthesize text into an audio file, but do not send to the audio device.
+* @param text The text to be synthesized.
+* @param suggestedFilename Full pathname of file to create. The plugin
+* may ignore this parameter and choose its own
+* filename. KTTSD will query the generated
+* filename using getFilename().
+*
+* If the plugin supports asynchronous operation, it should return immediately
+* and emit @ref synthFinished signal when synthesis is completed.
+* It must also implement the @ref getState method, which must return
+* psFinished, when synthesis is completed.
+*/
+void HadifixProc::synthText(const QString &text, const QString &suggestedFilename)
+{
+ if (d == 0) return; // Caller should have called init.
+ synth(text, d->hadifix, d->gender, d->mbrola, d->voice, d->volume,
+ d->time, d->pitch, d->codec, suggestedFilename);
+}
+
+/**
+* Synthesize text using a specified configuration.
+* @param text The text to synthesize.
+* @param hadifix Command to run hadifix (txt2pho).
+* @param isMale True to use male voice.
+* @param mbrola Command to run mbrola.
+* @param voice Voice file for mbrola to use.
+* @param volume Volume percent. 100 = normal
+* @param time Speed percent. 100 = normal
+* @param pitch Frequency. 100 = normal
+* @param waveFilename Name of file to synthesize to.
+*/
+void HadifixProc::synth(QString text,
+ QString hadifix, bool isMale,
+ QString mbrola, QString voice,
+ int volume, int time, int pitch,
+ QTextCodec *codec,
+ const QString waveFilename)
+{
+ // kdDebug() << "HadifixProc::synth: Saying text: '" << text << "' using Hadifix plug in" << endl;
+ if (d == 0)
+ {
+ d = new HadifixProcPrivate();
+ }
+ if (hadifix.isNull() || hadifix.isEmpty())
+ return;
+ if (mbrola.isNull() || mbrola.isEmpty())
+ return;
+ if (voice.isNull() || voice.isEmpty())
+ return;
+
+ // If process exists, delete it so we can create a new one.
+ // kdDebug() << "HadifixProc::synth: creating process" << endl;
+ if (d->hadifixProc) delete d->hadifixProc;
+
+ // Create process.
+ d->hadifixProc = new KShellProcess;
+
+ // Set up txt2pho and mbrola commands.
+ // kdDebug() << "HadifixProc::synth: setting up commands" << endl;
+ QString hadifixCommand = d->hadifixProc->quote(hadifix);
+ if (isMale)
+ hadifixCommand += " -m";
+ else
+ hadifixCommand += " -f";
+
+ QString mbrolaCommand = d->hadifixProc->quote(mbrola);
+ mbrolaCommand += " -e"; //Ignore fatal errors on unkown diphone
+ mbrolaCommand += QString(" -v %1").arg(volume/100.0); // volume ratio
+ mbrolaCommand += QString(" -f %1").arg(pitch/100.0); // freqency ratio
+ mbrolaCommand += QString(" -t %1").arg(1/(time/100.0)); // time ratio
+ mbrolaCommand += " " + d->hadifixProc->quote(voice);
+ mbrolaCommand += " - " + d->hadifixProc->quote(waveFilename);
+
+ // kdDebug() << "HadifixProc::synth: Hadifix command: " << hadifixCommand << endl;
+ // kdDebug() << "HadifixProc::synth: Mbrola command: " << mbrolaCommand << endl;
+
+ QString command = hadifixCommand + "|" + mbrolaCommand;
+ *(d->hadifixProc) << command;
+
+ // Connect signals from process.
+ connect(d->hadifixProc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(slotProcessExited(KProcess *)));
+ connect(d->hadifixProc, SIGNAL(wroteStdin(KProcess *)),
+ this, SLOT(slotWroteStdin(KProcess *)));
+
+ // Store off name of wave file to be generated.
+ d->synthFilename = waveFilename;
+ // Set state, busy synthing.
+ d->state = psSynthing;
+ if (!d->hadifixProc->start(KProcess::NotifyOnExit, KProcess::Stdin))
+ {
+ kdDebug() << "HadifixProc::synth: start process failed." << endl;
+ d->state = psIdle;
+ } else {
+ QCString encodedText;
+ if (codec) {
+ encodedText = codec->fromUnicode(text);
+ // kdDebug() << "HadifixProc::synth: encoding using " << codec->name() << endl;
+ } else
+ encodedText = text.latin1(); // Should not happen, but just in case.
+ // Send the text to be synthesized to process.
+ d->hadifixProc->writeStdin(encodedText, encodedText.length());
+ }
+}
+
+/**
+* Get the generated audio filename from call to @ref synthText.
+* @return Name of the audio file the plugin generated.
+* Null if no such file.
+*
+* The plugin must not re-use or delete the filename. The file may not
+* be locked when this method is called. The file will be deleted when
+* KTTSD is finished using it.
+*/
+QString HadifixProc::getFilename() { return d->synthFilename; }
+
+/**
+* Stop current operation (saying or synthesizing text).
+* Important: This function may be called from a thread different from the
+* one that called sayText or synthText.
+* If the plugin cannot stop an in-progress @ref sayText or
+* @ref synthText operation, it must not block waiting for it to complete.
+* Instead, return immediately.
+*
+* If a plugin returns before the operation has actually been stopped,
+* the plugin must emit the @ref stopped signal when the operation has
+* actually stopped.
+*
+* The plugin should change to the psIdle state after stopping the
+* operation.
+*/
+void HadifixProc::stopText(){
+ // kdDebug() << "Running: HadifixProc::stopText()" << endl;
+ if (d->hadifixProc)
+ {
+ if (d->hadifixProc->isRunning())
+ {
+ // kdDebug() << "HadifixProc::stopText: killing Hadifix shell." << endl;
+ d->waitingStop = true;
+ d->hadifixProc->kill();
+ } else d->state = psIdle;
+ } else d->state = psIdle;
+ // d->state = psIdle;
+ // kdDebug() << "HadifixProc::stopText: Hadifix stopped." << endl;
+}
+
+/**
+* Return the current state of the plugin.
+* This function only makes sense in asynchronous mode.
+* @return The pluginState of the plugin.
+*
+* @see pluginState
+*/
+pluginState HadifixProc::getState() { return d->state; }
+
+/**
+* Acknowledges a finished state and resets the plugin state to psIdle.
+*
+* If the plugin is not in state psFinished, nothing happens.
+* The plugin may use this call to do any post-processing cleanup,
+* for example, blanking the stored filename (but do not delete the file).
+* Calling program should call getFilename prior to ackFinished.
+*/
+void HadifixProc::ackFinished()
+{
+ if (d->state == psFinished)
+ {
+ d->state = psIdle;
+ d->synthFilename = QString::null;
+ }
+}
+
+/**
+* Returns True if the plugin supports asynchronous processing,
+* i.e., returns immediately from sayText or synthText.
+* @return True if this plugin supports asynchronous processing.
+*
+* If the plugin returns True, it must also implement @ref getState .
+* It must also emit @ref sayFinished or @ref synthFinished signals when
+* saying or synthesis is completed.
+*/
+bool HadifixProc::supportsAsync() { return true; }
+
+/**
+* Returns True if the plugin supports synthText method,
+* i.e., is able to synthesize text to a sound file without
+* audibilizing the text.
+* @return True if this plugin supports synthText method.
+*
+* If the plugin returns True, it must also implement the following methods:
+* - @ref synthText
+* - @ref getFilename
+* - @ref ackFinished
+*
+* If the plugin returns True, it need not implement @ref sayText .
+*/
+bool HadifixProc::supportsSynth() { return true; }
+
+
+void HadifixProc::slotProcessExited(KProcess*)
+{
+ // kdDebug() << "HadifixProc:hadifixProcExited: Hadifix process has exited." << endl;
+ pluginState prevState = d->state;
+ if (d->waitingStop)
+ {
+ d->waitingStop = false;
+ d->state = psIdle;
+ emit stopped();
+ } else {
+ d->state = psFinished;
+ if (prevState == psSynthing)
+ emit synthFinished();
+ }
+}
+
+void HadifixProc::slotWroteStdin(KProcess*)
+{
+ // kdDebug() << "HadifixProc::slotWroteStdin: closing Stdin" << endl;
+ d->hadifixProc->closeStdin();
+}
+
+
+/***************************************************************************/
+
+/**
+* Static function to determine whether the voice file is male or female.
+* @param mbrola the mbrola executable
+* @param voice the voice file
+* @param output the output of mbrola will be written into this QString*
+* @return HadifixSpeech::MaleGender if the voice is male,
+* HadifixSpeech::FemaleGender if the voice is female,
+* HadifixSpeech::NoGender if the gender cannot be determined,
+* HadifixSpeech::NoVoice if there is an error in the voice file
+*/
+HadifixProc::VoiceGender HadifixProc::determineGender(QString mbrola, QString voice, QString *output)
+{
+ QString command = mbrola + " -i " + voice + " - -";
+
+ // create a new process
+ HadifixProc speech;
+ KShellProcess proc;
+ proc << command;
+ connect(&proc, SIGNAL(receivedStdout(KProcess *, char *, int)),
+ &speech, SLOT(receivedStdout(KProcess *, char *, int)));
+ connect(&proc, SIGNAL(receivedStderr(KProcess *, char *, int)),
+ &speech, SLOT(receivedStderr(KProcess *, char *, int)));
+
+ speech.stdOut = QString::null;
+ speech.stdErr = QString::null;
+ proc.start (KProcess::Block, KProcess::AllOutput);
+
+ VoiceGender result;
+ if (!speech.stdErr.isNull() && !speech.stdErr.isEmpty()) {
+ if (output != 0)
+ *output = speech.stdErr;
+ result = NoVoice;
+ }
+ else {
+ if (output != 0)
+ *output = speech.stdOut;
+ if (speech.stdOut.contains("female", false))
+ result = FemaleGender;
+ else if (speech.stdOut.contains("male", false))
+ result = MaleGender;
+ else
+ result = NoGender;
+ }
+
+ return result;
+}
+
+void HadifixProc::receivedStdout (KProcess *, char *buffer, int buflen) {
+ stdOut += QString::fromLatin1(buffer, buflen);
+}
+
+void HadifixProc::receivedStderr (KProcess *, char *buffer, int buflen) {
+ stdErr += QString::fromLatin1(buffer, buflen);
+}
+
+/**
+ * Returns the name of an XSLT stylesheet that will convert a valid SSML file
+ * into a format that can be processed by the synth. For example,
+ * The Festival plugin returns a stylesheet that will convert SSML into
+ * SABLE. Any tags the synth cannot handle should be stripped (leaving
+ * their text contents though). The default stylesheet strips all
+ * tags and converts the file to plain text.
+ * @return Name of the XSLT file.
+ */
+QString HadifixProc::getSsmlXsltFilename()
+{
+ return KGlobal::dirs()->resourceDirs("data").last() + "kttsd/hadifix/xslt/SSMLtoTxt2pho.xsl";
+}
diff --git a/kttsd/plugins/hadifix/hadifixproc.h b/kttsd/plugins/hadifix/hadifixproc.h
new file mode 100644
index 0000000..225c7ed
--- /dev/null
+++ b/kttsd/plugins/hadifix/hadifixproc.h
@@ -0,0 +1,203 @@
+/***************************************************************************
+ hadifixproc.h - description
+ -------------------
+ begin : Mon Okt 14 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : gunnar@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef _HADIFIXPROC_H_
+#define _HADIFIXPROC_H_
+
+#include <qstringlist.h>
+
+#include <pluginproc.h>
+
+class KProcess;
+
+class HadifixProcPrivate;
+class HadifixProc : public PlugInProc{
+ Q_OBJECT
+
+ public:
+ enum VoiceGender {
+ MaleGender = 2,
+ FemaleGender = 1,
+ NoGender = 0,
+ NoVoice = -1
+ };
+
+ /** Constructor */
+ HadifixProc( QObject* parent = 0, const char* name = 0, const QStringList &args = QStringList());
+
+ /** Destructor */
+ ~HadifixProc();
+
+ /** Initializate the speech */
+ virtual bool init (KConfig *config, const QString &configGroup);
+
+ /**
+ * Say a text. Synthesize and audibilize it.
+ * @param text The text to be spoken.
+ *
+ * If the plugin supports asynchronous operation, it should return immediately
+ * and emit sayFinished signal when synthesis and audibilizing is finished.
+ * It must also implement the @ref getState method, which must return
+ * psFinished, when saying is completed.
+ */
+ virtual void sayText(const QString &text);
+
+ /**
+ * Synthesize text into an audio file, but do not send to the audio device.
+ * @param text The text to be synthesized.
+ * @param suggestedFilename Full pathname of file to create. The plugin
+ * may ignore this parameter and choose its own
+ * filename. KTTSD will query the generated
+ * filename using getFilename().
+ *
+ * If the plugin supports asynchronous operation, it should return immediately
+ * and emit @ref synthFinished signal when synthesis is completed.
+ * It must also implement the @ref getState method, which must return
+ * psFinished, when synthesis is completed.
+ */
+ virtual void synthText(const QString &text, const QString &suggestedFilename);
+
+ /**
+ * Get the generated audio filename from call to @ref synthText.
+ * @return Name of the audio file the plugin generated.
+ * Null if no such file.
+ *
+ * The plugin must not re-use or delete the filename. The file may not
+ * be locked when this method is called. The file will be deleted when
+ * KTTSD is finished using it.
+ */
+ virtual QString getFilename();
+
+ /**
+ * Stop current operation (saying or synthesizing text).
+ * Important: This function may be called from a thread different from the
+ * one that called sayText or synthText.
+ * If the plugin cannot stop an in-progress @ref sayText or
+ * @ref synthText operation, it must not block waiting for it to complete.
+ * Instead, return immediately.
+ *
+ * If a plugin returns before the operation has actually been stopped,
+ * the plugin must emit the @ref stopped signal when the operation has
+ * actually stopped.
+ *
+ * The plugin should change to the psIdle state after stopping the
+ * operation.
+ */
+ virtual void stopText();
+
+ /**
+ * Return the current state of the plugin.
+ * This function only makes sense in asynchronous mode.
+ * @return The pluginState of the plugin.
+ *
+ * @see pluginState
+ */
+ virtual pluginState getState();
+
+ /**
+ * Acknowledges a finished state and resets the plugin state to psIdle.
+ *
+ * If the plugin is not in state psFinished, nothing happens.
+ * The plugin may use this call to do any post-processing cleanup,
+ * for example, blanking the stored filename (but do not delete the file).
+ * Calling program should call getFilename prior to ackFinished.
+ */
+ virtual void ackFinished();
+
+ /**
+ * Returns True if the plugin supports asynchronous processing,
+ * i.e., returns immediately from sayText or synthText.
+ * @return True if this plugin supports asynchronous processing.
+ *
+ * If the plugin returns True, it must also implement @ref getState .
+ * It must also emit @ref sayFinished or @ref synthFinished signals when
+ * saying or synthesis is completed.
+ */
+ virtual bool supportsAsync();
+
+ /**
+ * Returns True if the plugin supports synthText method,
+ * i.e., is able to synthesize text to a sound file without
+ * audibilizing the text.
+ * @return True if this plugin supports synthText method.
+ *
+ * If the plugin returns True, it must also implement the following methods:
+ * - @ref synthText
+ * - @ref getFilename
+ * - @ref ackFinished
+ *
+ * If the plugin returns True, it need not implement @ref sayText .
+ */
+ virtual bool supportsSynth();
+
+ /**
+ * Synthesize text using a specified configuration.
+ * @param text The text to synthesize.
+ * @param hadifix Command to run hadifix (txt2pho).
+ * @param isMale True to use male voice.
+ * @param mbrola Command to run mbrola.
+ * @param voice Voice file for mbrola to use.
+ * @param volume Volume percent. 100 = normal
+ * @param time Speed percent. 100 = normal
+ * @param pitch Frequency. 100 = normal
+ * @param waveFilename Name of file to synthesize to.
+ */
+ void synth(QString text,
+ QString hadifix, bool isMale,
+ QString mbrola, QString voice,
+ int volume, int time, int pitch,
+ QTextCodec* codec,
+ const QString waveFilename);
+
+ /**
+ * Static function to determine whether the voice file is male or female.
+ * @param mbrola the mbrola executable
+ * @param voice the voice file
+ * @param output the output of mbrola will be written into this QString*
+ * @return HadifixSpeech::MaleGender if the voice is male,
+ * HadifixSpeech::FemaleGender if the voice is female,
+ * HadifixSpeech::NoGender if the gender cannot be determined,
+ * HadifixSpeech::NoVoice if there is an error in the voice file
+ */
+ static VoiceGender determineGender(QString mbrola, QString voice, QString *output = 0);
+
+ /**
+ * Returns the name of an XSLT stylesheet that will convert a valid SSML file
+ * into a format that can be processed by the synth. For example,
+ * The Festival plugin returns a stylesheet that will convert SSML into
+ * SABLE. Any tags the synth cannot handle should be stripped (leaving
+ * their text contents though). The default stylesheet strips all
+ * tags and converts the file to plain text.
+ * @return Name of the XSLT file.
+ */
+ virtual QString getSsmlXsltFilename();
+
+ private slots:
+ void slotProcessExited(KProcess*);
+ void slotWroteStdin(KProcess*);
+
+ void receivedStdout (KProcess *, char *buffer, int buflen);
+ void receivedStderr (KProcess *, char *buffer, int buflen);
+
+ private:
+ HadifixProcPrivate *d;
+
+ QString stdOut;
+ QString stdErr;
+};
+
+#endif
diff --git a/kttsd/plugins/hadifix/initialconfig.h b/kttsd/plugins/hadifix/initialconfig.h
new file mode 100644
index 0000000..4fac632
--- /dev/null
+++ b/kttsd/plugins/hadifix/initialconfig.h
@@ -0,0 +1,164 @@
+
+/**
+ * Tries to find hadifix and mbrola by looking onto the hard disk. This is
+ * neccessary because both hadifix and mbrola do not have standard
+ * installation directories.
+ */
+void findInitialConfig() {
+ QString hadifixDataPath = findHadifixDataPath();
+
+ defaultHadifixExec = findExecutable("txt2pho", hadifixDataPath+"/../");
+
+ QStringList list; list += "mbrola"; list += "mbrola-linux-i386";
+ defaultMbrolaExec = findExecutable(list, hadifixDataPath+"/../../mbrola/");
+
+ defaultVoices = findVoices (defaultMbrolaExec, hadifixDataPath);
+}
+
+/** Tries to find the hadifix data path by looking into a number of files. */
+QString findHadifixDataPath () {
+ QStringList files;
+ files += "/etc/txt2pho";
+ files += QDir::homeDirPath()+"/.txt2phorc";
+
+ QStringList::iterator it;
+ for (it = files.begin(); it != files.end(); ++it) {
+
+ QFile file(*it);
+ if ( file.open(IO_ReadOnly) ) {
+ QTextStream stream(&file);
+
+ while (!stream.atEnd()) {
+ QString s = stream.readLine().stripWhiteSpace();
+ // look for a line "DATAPATH=..."
+
+ if (s.startsWith("DATAPATH")) {
+ s = s.mid(8, s.length()-8).stripWhiteSpace();
+ if (s.startsWith("=")) {
+ s = s.mid(1, s.length()-1).stripWhiteSpace();
+ if (s.startsWith("/"))
+ return s;
+ else {
+ QFileInfo info (QFileInfo(*it).dirPath() + "/" + s);
+ return info.absFilePath();
+ }
+ }
+ }
+ }
+ file.close();
+ }
+ }
+ return "/usr/local/txt2pho/";
+}
+
+/** Tries to find the an executable by looking onto the hard disk. */
+QString findExecutable (const QStringList &names, const QString &possiblePath) {
+ // a) Try to find it directly
+ QStringList::ConstIterator it;
+ QStringList::ConstIterator itEnd = names.constEnd();
+ for (it = names.constBegin(); it != itEnd; ++it) {
+ QString executable = KStandardDirs::findExe (*it);
+ if (!executable.isNull() && !executable.isEmpty())
+ return executable;
+ }
+
+ // b) Try to find it in the path specified by the second parameter
+ for (it = names.constBegin(); it != itEnd; ++it) {
+ QFileInfo info (possiblePath+*it);
+ if (info.exists() && info.isExecutable() && info.isFile()) {
+ return info.absFilePath();
+ }
+ }
+
+ // Both tries failed, so the user has to locate the executable.
+ return QString::null;
+}
+
+/** Tries to find the voice files by looking onto the hard disk. */
+QStringList findVoices(QString mbrolaExec, const QString &hadifixDataPath) {
+
+ // First of all:
+ // dereference links to the mbrola executable (if mbrolaExec is a link).
+ for (int i = 0; i < 10; ++i) {
+ // If we have a chain of more than ten links something is surely wrong.
+ QFileInfo info (mbrolaExec);
+ if (info.exists() && info.isSymLink())
+ mbrolaExec = info.readLink();
+ }
+
+ // Second:
+ // create a list of directories that possibly contain voice files
+ QStringList list;
+
+ // 2a) search near the mbrola executable
+ QFileInfo info (mbrolaExec);
+ if (info.exists() && info.isFile() && info.isExecutable()) {
+ QString mbrolaPath = info.dirPath (true);
+ list += mbrolaPath;
+ }
+
+ // 2b) search near the hadifix data path
+ info.setFile(hadifixDataPath + "../../mbrola");
+ QString mbrolaPath = info.dirPath (true) + "/mbrola";
+ if (!list.contains(mbrolaPath))
+ list += mbrolaPath;
+
+ // 2c) broaden the search by adding subdirs (with a depth of 2)
+ QStringList subDirs = findSubdirs (list);
+ QStringList subSubDirs = findSubdirs (subDirs);
+ list += subDirs;
+ list += subSubDirs;
+
+ // Third:
+ // look into each of these directories and search for voice files.
+ QStringList result;
+ QStringList::iterator it;
+ for (it = list.begin(); it != list.end(); ++it) {
+ QDir baseDir (*it, QString::null,
+ QDir::Name|QDir::IgnoreCase, QDir::Files);
+ QStringList files = baseDir.entryList();
+
+ QStringList::iterator iter;
+ for (iter = files.begin(); iter != files.end(); ++iter) {
+ // Voice files start with "MBROLA", but are afterwards binary files
+ QString filename = *it + "/" + *iter;
+ QFile file (filename);
+ if (file.open(IO_ReadOnly)) {
+ QTextStream stream(&file);
+ if (!stream.atEnd()) {
+ QString s = stream.readLine();
+ if (s.startsWith("MBROLA"))
+ if (HadifixProc::determineGender(mbrolaExec, filename)
+ != HadifixProc::NoVoice
+ )
+ result += filename;
+ file.close();
+ }
+ }
+ }
+ }
+ return result;
+}
+
+/** Returns a list of subdirs (with absolute paths) */
+QStringList findSubdirs (const QStringList &baseDirs) {
+ QStringList result;
+
+ QStringList::ConstIterator it;
+ QStringList::ConstIterator itEnd = baseDirs.constEnd();
+ for (it = baseDirs.constBegin(); it != itEnd; ++it) {
+ // a) get a list of directory names
+ QDir baseDir (*it, QString::null,
+ QDir::Name|QDir::IgnoreCase, QDir::Dirs);
+ QStringList list = baseDir.entryList();
+
+ // b) produce absolute paths
+ QStringList::ConstIterator iter;
+ QStringList::ConstIterator iterEnd = list.constEnd();
+ for (iter = list.constBegin(); iter != iterEnd; ++iter) {
+ if ((*iter != ".") && (*iter != ".."))
+ result += *it + "/" + *iter;
+ }
+ }
+ return result;
+}
diff --git a/kttsd/plugins/hadifix/kttsd_hadifixplugin.desktop b/kttsd/plugins/hadifix/kttsd_hadifixplugin.desktop
new file mode 100644
index 0000000..2db3e1c
--- /dev/null
+++ b/kttsd/plugins/hadifix/kttsd_hadifixplugin.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=Hadifix
+Name[ne]=ह्याडिफिक्स
+Comment=German hadifix text-to-speech system
+Comment[bg]=Синтезатор на глас за немски език Hadifix
+Comment[ca]=Sistema de text a veu alemany hadifix
+Comment[cs]=Německý systém hlasové syntézy hadifix
+Comment[da]=Tysk hadifix tekst-til-tale system
+Comment[de]=Deutsches hadifix-Sprachausgabesystem
+Comment[el]=Σύστημα κειμένου-σε-ομιλία γερμανικού hadifix
+Comment[es]=Sintetizador de texto a voz en alemán hadifix
+Comment[et]=Saksa teksti kõneks muutmise süsteem Hadifix
+Comment[eu]=Alemanierazko hadifix testutik hizketarako sistema
+Comment[fa]=سیستم متن به گفتار hadifix آلمانی
+Comment[fi]=Saksalainen hadifix teksti puheeksi -systeemi
+Comment[fr]=Système allemand de synthèse vocale hadifix
+Comment[ga]=Córas téacs-go-caint Gearmáinise hadifix
+Comment[gl]=Sistema alemao de texto-para-fala hadifix
+Comment[hu]=Hadifix szövegfelolvasó (Mbrola-alapú)
+Comment[is]=Þýska hadifix texti-í-tal kerfið
+Comment[it]=Sistema di pronuncia tedesca Hadifix
+Comment[ja]=ドイツ語 hadifix テキスト読み上げシステム
+Comment[ka]=გერმანული hadifix ტექსტის გახმოვანების სისტემა
+Comment[km]=ប្រព័ន្ធ​អត្ថបទ​ដែល​ត្រូវ​និយាយ​ hadifix អាល្លឺម៉ង់
+Comment[mk]=Германски hadifix систем за текст-во-говор
+Comment[ms]=Sistem teks-ke-tutur hadifiks Jerman
+Comment[mt]=Sistema test-għal-vuċi hadifix Ġermaniż
+Comment[nb]=Tysk hadifix system for tekst-til-tale
+Comment[nds]=Düütsch Blicksnuut Hadifix
+Comment[ne]=जर्मनी ह्याडिफिक्स पाठ वाचक प्रणाली
+Comment[nl]=Duits hadifix tekst-tot-spraak-systeem
+Comment[pa]=ਜਰਮਨ hadifix ਪਾਠ ਤੋਂ ਬੋਲੀ ਸਿਸਟਮ
+Comment[pl]=Niemiecki system syntezy mowy hadifix
+Comment[pt]=Sistema alemão de texto-para-voz hadifix
+Comment[pt_BR]=Sistema de conversão de texto para áudio almeão hadifix
+Comment[ru]=Немецкая система синтеза речи Hadifix
+Comment[sk]=Nemecký systém text-na-reč hadifix
+Comment[sl]=Nemški sistem besedila v govor hadifix
+Comment[sr]=Hadifix, немачки систем за текст-у-говор
+Comment[sr@Latn]=Hadifix, nemački sistem za tekst-u-govor
+Comment[sv]=Tyska Hadifix text-till-tal system
+Comment[ta]=ஜெர்மன் ஹாடிஃபிக்ஸ் உரையில் இருந்து பேச்சு அமைப்பு
+Comment[tg]=Системаи олмонии таҳлили овози hadifix
+Comment[tr]=Alman hadifix metinden konuşmaya sistemi
+Comment[uk]=Німецька система синтезу мовлення hadifix
+Comment[vi]=Hệ thống tổng hợp tiếng nói Đức hadifix
+Comment[zh_TW]=德語 hadifix 文字轉語音系統
+Type=Service
+ServiceTypes=KTTSD/SynthPlugin
+X-KDE-Library=libkttsd_hadifixplugin
+X-KDE-Languages=de,hu
diff --git a/kttsd/plugins/hadifix/voicefileui.ui b/kttsd/plugins/hadifix/voicefileui.ui
new file mode 100644
index 0000000..6c038f7
--- /dev/null
+++ b/kttsd/plugins/hadifix/voicefileui.ui
@@ -0,0 +1,119 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>VoiceFileWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>VoiceFileWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>452</width>
+ <height>117</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Selecting Voice File</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>voiceFileLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Path of the voice file:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>voiceFileURL</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>genderOption</cstring>
+ </property>
+ <property name="title">
+ <string>Gender</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>femaleOption</cstring>
+ </property>
+ <property name="text">
+ <string>Female</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="1">
+ <property name="name">
+ <cstring>maleOption</cstring>
+ </property>
+ <property name="text">
+ <string>Male</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>genderButton</cstring>
+ </property>
+ <property name="text">
+ <string>Try to Determine From Voice File</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>genderButton</sender>
+ <signal>clicked()</signal>
+ <receiver>VoiceFileWidget</receiver>
+ <slot>genderButton_clicked()</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequesterdlg.h</include>
+ <include location="global" impldecl="in implementation">kmessagebox.h</include>
+ <include location="local" impldecl="in implementation">hadifixproc.h</include>
+ <include location="local" impldecl="in implementation">voicefileui.ui.h</include>
+</includes>
+<variables>
+ <variable access="public">QString mbrola;</variable>
+</variables>
+<slots>
+ <slot>genderButton_clicked()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/plugins/hadifix/voicefileui.ui.h b/kttsd/plugins/hadifix/voicefileui.ui.h
new file mode 100644
index 0000000..9d37375
--- /dev/null
+++ b/kttsd/plugins/hadifix/voicefileui.ui.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void VoiceFileWidget::genderButton_clicked()
+{
+ HadifixProc::VoiceGender gender;
+ QString details;
+ gender = HadifixProc::determineGender(mbrola, voiceFileURL->url(), &details);
+
+ if (gender == HadifixProc::MaleGender) {
+ maleOption->setChecked (true);
+ femaleOption->setChecked (false);
+ }
+ else if (gender == HadifixProc::FemaleGender) {
+ maleOption->setChecked (false);
+ femaleOption->setChecked (true);
+ }
+ else if (gender == HadifixProc::NoGender) {
+ KMessageBox::sorry (this,
+ i18n("The gender of the voice file %1 could not be detected.").arg(voiceFileURL->url()),
+ i18n("Trying to Determine the Gender - Hadifix Plug In"));
+ }
+ else {
+ KMessageBox::detailedSorry (this,
+ i18n("The file %1 does not seem to be a voice file.").arg(voiceFileURL->url()),
+ details, i18n("Trying to Determine the Gender - Hadifix Plug In"));
+ }
+}
diff --git a/kttsd/sample.polish b/kttsd/sample.polish
new file mode 100644
index 0000000..dfe51ec
--- /dev/null
+++ b/kttsd/sample.polish
@@ -0,0 +1,8 @@
+Cze, nazywam si Mikoaj.
+Odwiedz wasz wysp w przyszym tygodniu.
+Pno ju jest.
+
+Gwiazdkowe prezenty mona otworzy dopiero pod choink, wic autorzy MPlayera
+zaklinaj, eby opublikowane wczoraj rda nowej wersji trzyma w stanie
+nienaruszonym i pod adnym pozorem nie odpakowywa ich do kompilacji wczeniej!
+A pokusa jest spora...
diff --git a/kttsd/sample.ssml b/kttsd/sample.ssml
new file mode 100644
index 0000000..1971343
--- /dev/null
+++ b/kttsd/sample.ssml
@@ -0,0 +1 @@
+<speak><p><voice gender="male">Hello there.<prosody rate="x-slow">This is some extra slow text</prosody> and here <prosody pitch="high" rate="fast">is some fast high text</prosody></voice></p></speak>